tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ //ret->Line = Parser->CurLine;
ret->Type = NODETYPE_BLOCK;
ret->Block.FirstChild = NULL;
ret->Block.LastChild = NULL;
}
}
-tAST_Node *AST_NewIf(tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
+tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_IF;
ret->If.Condition = Condition;
ret->If.True = True;
return ret;
}
-tAST_Node *AST_NewLoop(tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
+tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_LOOP;
ret->For.Init = Init;
ret->For.bCheckAfter = !!bPostCheck;
return ret;
}
-tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
+tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_ASSIGN;
ret->Assign.Operation = Operation;
ret->Assign.Dest = Dest;
return ret;
}
-tAST_Node *AST_NewCast(int Target, tAST_Node *Value)
+tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_CAST;
ret->Cast.DataType = Target;
ret->Cast.Value = Value;
return ret;
}
-tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
+tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = Operation;
ret->BinOp.Left = Left;
ret->BinOp.Right = Right;
/**
*/
-tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
+tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = Operation;
ret->UniOp.Value = Value;
/**
* \brief Create a new string node
*/
-tAST_Node *AST_NewString(const char *String, int Length)
+tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_STRING;
ret->String.Length = Length;
memcpy(ret->String.Data, String, Length);
/**
* \brief Create a new integer node
*/
-tAST_Node *AST_NewInteger(uint64_t Value)
+tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_INTEGER;
ret->Integer = Value;
return ret;
/**
* \brief Create a new variable reference node
*/
-tAST_Node *AST_NewVariable(const char *Name)
+tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_VARIABLE;
strcpy(ret->Variable.Name, Name);
return ret;
/**
* \brief Create a new variable definition node
*/
-tAST_Node *AST_NewDefineVar(int Type, const char *Name)
+tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_DEFVAR;
ret->DefVar.DataType = Type;
ret->DefVar.LevelSizes = NULL;
/**
* \brief Create a new runtime constant reference node
*/
-tAST_Node *AST_NewConstant(const char *Name)
+tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_CONSTANT;
strcpy(ret->Variable.Name, Name);
return ret;
* \brief Create a function call node
* \note Argument list is manipulated using AST_AppendFunctionCallArg
*/
-tAST_Node *AST_NewFunctionCall(const char *Name)
+tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
- //ret->Line = giLineNumber;
+ ret->Line = Parser->CurLine;
ret->Type = NODETYPE_FUNCTIONCALL;
ret->FunctionCall.FirstArg = NULL;
ret->FunctionCall.LastArg = NULL;
#define _AST_H_
#include <spiderscript.h>
+#include "tokens.h"
typedef enum eAST_NodeTypes tAST_NodeType;
typedef struct sAST_Script tAST_Script;
tAST_Node *NextSibling;
tAST_NodeType Type;
+ const char *File;
int Line;
union
extern tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name);
extern void AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Arg);
extern void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root);
-extern tAST_Node *AST_NewString(const char *String, int Length);
-extern tAST_Node *AST_NewInteger(uint64_t Value);
-extern tAST_Node *AST_NewVariable(const char *Name);
-extern tAST_Node *AST_NewDefineVar(int Type, const char *Name);
-extern tAST_Node *AST_NewConstant(const char *Name);
-extern tAST_Node *AST_NewFunctionCall(const char *Name);
+extern tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length);
+extern tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value);
+extern tAST_Node *AST_NewVariable(tParser *Parser, const char *Name);
+extern tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name);
+extern tAST_Node *AST_NewConstant(tParser *Parser, const char *Name);
+extern tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name);
extern void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg);
extern tAST_Node *AST_NewCodeBlock(void);
extern void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child);
-extern tAST_Node *AST_NewIf(tAST_Node *Condition, tAST_Node *True, tAST_Node *False);
+extern tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False);
-extern tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value);
-extern tAST_Node *AST_NewCast(int Target, tAST_Node *Value);
-extern tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right);
-extern tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value);
+extern tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value);
+extern tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value);
+extern tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right);
+extern tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value);
extern void AST_FreeNode(tAST_Node *Node);
tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node);
tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name);
-void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
+ int Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
tSpiderValue *Variable_GetValue(tAST_BlockState *Block, const char *Name);
void Variable_Destroy(tAST_Variable *Variable);
{
tSpiderValue *ret = ERRPTR;
int len = 0;
+
+ if( !Source ) return NULL;
// Check if anything needs to be done
if( Source->Type == Type ) {
switch( (enum eSpiderScript_DataTypes)Type )
{
case SS_DATATYPE_UNDEF:
- case SS_DATATYPE_NULL:
case SS_DATATYPE_ARRAY:
case SS_DATATYPE_OPAQUE:
fprintf(stderr, "SpiderScript_CastValueTo - Invalid cast to %i\n", Type);
switch( (enum eSpiderScript_DataTypes)Value->Type )
{
case SS_DATATYPE_UNDEF:
- case SS_DATATYPE_NULL:
return 0;
case SS_DATATYPE_INTEGER:
switch( (enum eSpiderScript_DataTypes)Value->Type )
{
case SS_DATATYPE_UNDEF: return strdup("undefined");
- case SS_DATATYPE_NULL: return strdup("null type");
case SS_DATATYPE_INTEGER:
ret = malloc( sizeof(Value->Integer)*2 + 3 );
}
ret = AST_ExecuteNode(Block, Node->Assign.Value);
if(ret != ERRPTR)
- Variable_SetValue( Block, Node->Assign.Dest->Variable.Name, ret );
+ {
+ if( Variable_SetValue( Block, Node->Assign.Dest->Variable.Name, ret ) ) {
+ Object_Dereference( ret );
+ fprintf(stderr, "on line %i\n", Node->Line);
+ return ERRPTR;
+ }
+ }
break;
// Function Call
return ERRPTR;
}
- // No conversion done for NULL
- // TODO: Determine if this will ever be needed
- if( op1->Type == SS_DATATYPE_NULL )
- {
- // NULLs always typecheck
- ret = SpiderScript_CreateInteger(op2->Type == SS_DATATYPE_NULL);
- break;
- }
-
// Convert types
if( op1->Type != op2->Type ) {
// If dynamically typed, convert op2 to op1's type
// Do operation
switch(op1->Type)
{
- // - NULL
- case SS_DATATYPE_NULL: break;
// - String Compare (does a strcmp, well memcmp)
case SS_DATATYPE_STRING:
// Call memcmp to do most of the work
}
}
+ // NULL Check
+ if( op1 == NULL || op2 == NULL ) {
+ ret = NULL;
+ break;
+ }
+
// Do operation
switch(op1->Type)
{
- case SS_DATATYPE_NULL: break;
// String Concatenation
case SS_DATATYPE_STRING:
switch(Node->Type)
/**
* \brief Set the value of a variable
+ * \return Boolean Failure
*/
-void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value)
+int Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value)
{
tAST_Variable *var;
tAST_BlockState *bs;
if( !Block->Script->Variant->bDyamicTyped
&& (Value && var->Type != Value->Type) ) {
fprintf(stderr, "ERROR: Type mismatch assigning to '%s'\n", Name);
- return ;
+ return -2;
}
Object_Reference(Value);
Object_Dereference(var->Object);
var->Object = Value;
- return ;
+ return 0;
}
}
}
var = Variable_Define(Block, Value->Type, Name);
Object_Reference(Value);
var->Object = Value;
+ return 0;
}
else
{
fprintf(stderr, "ERROR: Variable '%s' set while undefined\n", Name);
+ return -1;
}
}
fcn = AST_AppendFunction( ret, "" );
AST_SetFunctionCode( fcn, mainCode );
- printf("---- %p parsed as SpiderScript ----\n", Buffer);
+ //printf("---- %p parsed as SpiderScript ----\n", Buffer);
return ret;
}
case TOK_RWD_RETURN:
//printf("return\n");
GetToken(Parser);
- ret = AST_NewUniOp(NODETYPE_RETURN, Parse_DoExpr0(Parser));
+ ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
break;
// Control Statements
GetToken(Parser);
false = Parse_DoCodeBlock(Parser);
}
- ret = AST_NewIf(cond, true, false);
+ ret = AST_NewIf(Parser, cond, true, false);
}
return ret;
case TOK_RWD_FOR:
memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
name[Parser->TokenLen-1] = 0;
// Define the variable
- ret = AST_NewDefineVar(Type, name);
+ ret = AST_NewDefineVar(Parser, Type, name);
// Handle arrays
while( LookAhead(Parser) == TOK_SQUARE_OPEN )
{
{
case TOK_ASSIGN:
GetToken(Parser); // Eat Token
- ret = AST_NewAssign(NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
+ ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
break;
#if 0
case TOK_DIV_EQU:
GetToken(Parser); // Eat Token
- ret = AST_NewAssign(NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
+ ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
break;
case TOK_MULT_EQU:
GetToken(Parser); // Eat Token
- ret = AST_NewAssign(NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
+ ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
break;
#endif
default:
switch(GetToken(Parser))
{
case TOK_LOGICAND:
- ret = AST_NewBinOp(NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
break;
case TOK_LOGICOR:
- ret = AST_NewBinOp(NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
break;
case TOK_LOGICXOR:
- ret = AST_NewBinOp(NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
break;
default:
PutBack(Parser);
switch(GetToken(Parser))
{
case TOK_EQUALS:
- ret = AST_NewBinOp(NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
break;
case TOK_LT:
- ret = AST_NewBinOp(NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
break;
case TOK_GT:
- ret = AST_NewBinOp(NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
break;
default:
PutBack(Parser);
switch(GetToken(Parser))
{
case TOK_OR:
- ret = AST_NewBinOp(NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
break;
case TOK_AND:
- ret = AST_NewBinOp(NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
break;
case TOK_XOR:
- ret = AST_NewBinOp(NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
break;
default:
PutBack(Parser);
switch(GetToken(Parser))
{
case TOK_SHL:
- ret = AST_NewBinOp(NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
break;
case TOK_SHR:
- ret = AST_NewBinOp(NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
break;
default:
PutBack(Parser);
switch(GetToken(Parser))
{
case TOK_PLUS:
- ret = AST_NewBinOp(NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
break;
case TOK_MINUS:
- ret = AST_NewBinOp(NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
break;
default:
PutBack(Parser);
switch(GetToken(Parser))
{
case TOK_MUL:
- ret = AST_NewBinOp(NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
break;
case TOK_DIV:
- ret = AST_NewBinOp(NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
break;
default:
PutBack(Parser);
GetToken(Parser);
TOKEN_GET_DATATYPE(type, Parser->Token);
SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
- ret = AST_NewCast(type, Parse_DoParen(Parser));
+ ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
break;
default:
ret = Parse_DoExpr0(Parser);
}
// TODO: Parse Escape Codes
- ret = AST_NewString( data, j );
+ ret = AST_NewString( Parser, data, j );
}
return ret;
}
uint64_t value;
GetToken( Parser );
value = atoi( Parser->TokenStr );
- return AST_NewInteger( value );
+ return AST_NewInteger( Parser, value );
}
/**
char name[Parser->TokenLen];
memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
name[Parser->TokenLen-1] = 0;
- ret = AST_NewVariable( name );
+ ret = AST_NewVariable( Parser, name );
#if DEBUG >= 2
printf("Parse_GetVariable: name = '%s'\n", name);
#endif
while( LookAhead(Parser) == TOK_SQUARE_OPEN )
{
GetToken(Parser);
- ret = AST_NewBinOp(NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
+ ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
}
return ret;
printf("Parse_GetIdent: Calling '%s'\n", name);
#endif
// Function Call
- ret = AST_NewFunctionCall( name );
+ ret = AST_NewFunctionCall( Parser, name );
// Read arguments
if( GetToken(Parser) != TOK_PAREN_CLOSE )
{
printf("Parse_GetIdent: Referencing '%s'\n", name);
#endif
PutBack(Parser);
- ret = AST_NewConstant( name );
+ ret = AST_NewConstant( Parser, name );
}
free(name);
*/
enum eSpiderScript_DataTypes
{
- SS_DATATYPE_UNDEF, //!< Undefined
- SS_DATATYPE_NULL, //!< NULL (Probably will never be used)
- SS_DATATYPE_DYNAMIC, //!< Dynamically typed variable (will this be used?)
- SS_DATATYPE_OPAQUE, //!< Opaque data type
- SS_DATATYPE_OBJECT, //!< Object reference
- SS_DATATYPE_ARRAY, //!< Array
- SS_DATATYPE_INTEGER, //!< Integer (64-bits)
+ /**
+ * \brief Undefined data
+ * \note Default type of an undefined dynamic variable
+ */
+ SS_DATATYPE_UNDEF,
+ /**
+ * \brief Dynamically typed variable
+ * \note Used to dentote a non-fixed type for function parameters
+ */
+ SS_DATATYPE_DYNAMIC,
+ /**
+ * \brief Opaque Data Pointer
+ *
+ * Opaque data types are used for resource handles or for system buffers.
+ */
+ SS_DATATYPE_OPAQUE,
+ /**
+ * \brief Object reference
+ *
+ * A reference to a SpiderScript class instance. Can be accessed
+ * using the -> operator.
+ */
+ SS_DATATYPE_OBJECT,
+ /**
+ * \brief Array data type
+ */
+ SS_DATATYPE_ARRAY,
+ /**
+ * \brief Integer datatype
+ *
+ * 64-bit integer
+ */
+ SS_DATATYPE_INTEGER,
SS_DATATYPE_REAL, //!< Real Number (double)
SS_DATATYPE_STRING, //!< String
NUM_SS_DATATYPES
*/
struct {
void *Data; //!< Data (can be anywhere)
- int Size; //!< Data size (zero means full opaque)
void (*Destroy)(void *Data); //!< Called on GC
} Opaque;