size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
{
tAST_Function *fcn;
- size_t ret = 0, ptr;
+ size_t ret = 0, ptr = 0;
for( fcn = Script->Functions; fcn; fcn = fcn->Next )
{
ret += AST_WriteNode(Buffer, ret, fcn->Code);
WRITE_32(Buffer, ptr, ret); // Actually set next
}
- ptr -= 4;
- WRITE_32(Buffer, ptr, 0); // Clear next for final
+ if( ptr )
+ {
+ ptr -= 4;
+ WRITE_32(Buffer, ptr, 0); // Clear next for final
+ }
return ret;
}
*/
size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node)
{
- size_t ptr;
size_t baseOfs = Offset;
if(!Node) {
// Unary Operations
case NODETYPE_RETURN:
- ptr = Offset;
+ case NODETYPE_BWNOT:
+ case NODETYPE_LOGICALNOT:
+ case NODETYPE_NEGATE:
+ case NODETYPE_POSTINC:
+ case NODETYPE_POSTDEC:
Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
break;
case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
case NODETYPE_EQUALS:
- case NODETYPE_LESSTHAN:
- case NODETYPE_GREATERTHAN:
+ case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL:
+ case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL:
Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left);
Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right);
break;
// Unary Operations
case NODETYPE_RETURN:
+ case NODETYPE_BWNOT:
+ case NODETYPE_LOGICALNOT:
+ case NODETYPE_NEGATE:
+ case NODETYPE_POSTINC:
+ case NODETYPE_POSTDEC:
AST_FreeNode(Node->UniOp.Value);
break;
case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
case NODETYPE_EQUALS:
- case NODETYPE_LESSTHAN:
- case NODETYPE_GREATERTHAN:
+ case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL:
+ case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL:
AST_FreeNode( Node->BinOp.Left );
AST_FreeNode( Node->BinOp.Right );
break;
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_BLOCK;
ret->Block.FirstChild = NULL;
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_IF;
ret->If.Condition = Condition;
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_LOOP;
ret->For.Init = Init;
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_ASSIGN;
ret->Assign.Operation = Operation;
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_CAST;
ret->Cast.DataType = Target;
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = Operation;
ret->BinOp.Left = Left;
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = Operation;
ret->UniOp.Value = Value;
return ret;
}
+tAST_Node *AST_NewNop(tParser *Parser)
+{
+ tAST_Node *ret = malloc( sizeof(tAST_Node) );
+
+ ret->NextSibling = NULL;
+ ret->File = NULL;
+ ret->Line = Parser->CurLine;
+ ret->Type = NODETYPE_NOP;
+
+ return ret;
+}
+
/**
* \brief Create a new string node
*/
tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_STRING;
ret->String.Length = Length;
/**
* \brief Create a new integer node
*/
-tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
+tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value)
{
tAST_Node *ret = malloc( sizeof(tAST_Node) );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_INTEGER;
ret->Integer = Value;
return ret;
}
+/**
+ * \brief Create a new real number node
+ */
+tAST_Node *AST_NewReal(tParser *Parser, double Value)
+{
+ tAST_Node *ret = malloc( sizeof(tAST_Node) );
+ ret->NextSibling = NULL;
+ ret->File = NULL;
+ ret->Line = Parser->CurLine;
+ ret->Type = NODETYPE_REAL;
+ ret->Real = Value;
+ return ret;
+}
+
/**
* \brief Create a new variable reference node
*/
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_VARIABLE;
strcpy(ret->Variable.Name, Name);
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_DEFVAR;
ret->DefVar.DataType = Type;
{
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_CONSTANT;
strcpy(ret->Variable.Name, Name);
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_FUNCTIONCALL;
ret->FunctionCall.Object = NULL;
ret->FunctionCall.FirstArg = NULL;
ret->FunctionCall.LastArg = NULL;
+ ret->FunctionCall.NumArgs = 0;
strcpy(ret->FunctionCall.Name, Name);
return ret;
}
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_METHODCALL;
ret->FunctionCall.Object = Object;
ret->FunctionCall.FirstArg = NULL;
ret->FunctionCall.LastArg = NULL;
+ ret->FunctionCall.NumArgs = 0;
strcpy(ret->FunctionCall.Name, Name);
return ret;
}
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_CREATEOBJECT;
ret->FunctionCall.Object = NULL;
ret->FunctionCall.FirstArg = NULL;
ret->FunctionCall.LastArg = NULL;
+ ret->FunctionCall.NumArgs = 0;
strcpy(ret->FunctionCall.Name, Name);
return ret;
}
Node->FunctionCall.FirstArg = Arg;
Node->FunctionCall.LastArg = Arg;
}
+ Node->FunctionCall.NumArgs ++;
}
/**
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_SCOPE;
ret->Scope.Element = Child;
tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
ret->NextSibling = NULL;
+ ret->File = NULL;
ret->Line = Parser->CurLine;
ret->Type = NODETYPE_ELEMENT;
ret->Scope.Element = Object;
NODETYPE_RETURN, //!< Return from a function (reserved word)
NODETYPE_ASSIGN, //!< Variable assignment operator
+ NODETYPE_POSTINC, //!< Post-increment (i++) - Uniop
+ NODETYPE_POSTDEC, //!< Post-decrement (i--) - Uniop
NODETYPE_FUNCTIONCALL, //!< Call a function
NODETYPE_METHODCALL, //!< Call a class method
NODETYPE_CREATEOBJECT, //!< Create an object
NODETYPE_INDEX, //!< Index into an array
+ NODETYPE_LOGICALNOT, //!< Logical NOT operator
NODETYPE_LOGICALAND, //!< Logical AND operator
NODETYPE_LOGICALOR, //!< Logical OR operator
NODETYPE_LOGICALXOR, //!< Logical XOR operator
NODETYPE_EQUALS, //!< Comparison Equals
NODETYPE_LESSTHAN, //!< Comparison Less Than
+ NODETYPE_LESSTHANEQUAL, //!< Comparison Less Than or Equal
NODETYPE_GREATERTHAN, //!< Comparison Greater Than
+ NODETYPE_GREATERTHANEQUAL, //!< Comparison Greater Than or Equal
+ NODETYPE_BWNOT, //!< Bitwise NOT
NODETYPE_BWAND, //!< Bitwise AND
NODETYPE_BWOR, //!< Bitwise OR
NODETYPE_BWXOR, //!< Bitwise XOR
NODETYPE_BITSHIFTRIGHT, //!< Bitwise Shift Right (Shrink)
NODETYPE_BITROTATELEFT, //!< Bitwise Rotate Left (Grow)
+ NODETYPE_NEGATE, //!< Negagte
NODETYPE_ADD, //!< Add
NODETYPE_SUBTRACT, //!< Subtract
NODETYPE_MULTIPLY, //!< Multiply
tAST_Node *Object;
tAST_Node *FirstArg;
tAST_Node *LastArg;
+ int NumArgs;
char Name[];
} FunctionCall;
extern void AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Arg);
extern void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root);
+extern tAST_Node *AST_NewNop(tParser *Parser);
+
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_NewInteger(tParser *Parser, int64_t Value);
+extern tAST_Node *AST_NewReal(tParser *Parser, double 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);
tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node);
tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, int Operation, tSpiderValue *Left, tSpiderValue *Right);
+tSpiderValue *AST_ExecuteNode_UniOp(tAST_BlockState *Block, int Operation, tSpiderValue *Value);
tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name);
int Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
tSpiderValue *ret = ERRPTR;
int len = 0;
- if( !Source ) return NULL;
+ if( !Source )
+ {
+ switch(Type)
+ {
+ case SS_DATATYPE_INTEGER: return SpiderScript_CreateInteger(0);
+ case SS_DATATYPE_REAL: return SpiderScript_CreateReal(0);
+ case SS_DATATYPE_STRING: return SpiderScript_CreateString(4, "null");
+ }
+ return NULL;
+ }
// Check if anything needs to be done
if( Source->Type == Type ) {
return Source;
}
+ #if 0
+ {
+ printf("Casting %i ", Source->Type);
+ switch(Source->Type)
+ {
+ case SS_DATATYPE_INTEGER: printf("0x%lx", Source->Integer); break;
+ case SS_DATATYPE_STRING: printf("\"%s\"", Source->String.Data); break;
+ case SS_DATATYPE_REAL: printf("%f", Source->Real); break;
+ default: break;
+ }
+ printf(" to %i\n", Type);
+ }
+ #endif
+
#if 0
if( Source->Type == SS_DATATYPE_OBJECT )
{
}
break;
+ case SS_DATATYPE_REAL:
+ ret = malloc(sizeof(tSpiderValue));
+ ret->Type = SS_DATATYPE_REAL;
+ ret->ReferenceCount = 1;
+ switch(Source->Type)
+ {
+ case SS_DATATYPE_STRING: ret->Real = atof(Source->String.Data); break;
+ case SS_DATATYPE_INTEGER: ret->Real = Source->Integer; break;
+ default:
+ AST_RuntimeError(NULL, "Invalid cast from %i to Real", Source->Type);
+ free(ret);
+ ret = ERRPTR;
+ break;
+ }
+ break;
+
case SS_DATATYPE_STRING:
switch(Source->Type)
{
case SS_DATATYPE_INTEGER: len = snprintf(NULL, 0, "%li", Source->Integer); break;
- case SS_DATATYPE_REAL: snprintf(NULL, 0, "%f", Source->Real); break;
+ case SS_DATATYPE_REAL: len = snprintf(NULL, 0, "%g", Source->Real); break;
default: break;
}
ret = malloc(sizeof(tSpiderValue) + len + 1);
switch(Source->Type)
{
case SS_DATATYPE_INTEGER: sprintf(ret->String.Data, "%li", Source->Integer); break;
- case SS_DATATYPE_REAL: sprintf(ret->String.Data, "%f", Source->Real); break;
+ case SS_DATATYPE_REAL:
+ sprintf(ret->String.Data, "%g", Source->Real); break;
default:
AST_RuntimeError(NULL, "Invalid cast from %i to String", Source->Type);
free(ret);
break;
default:
- AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target");
+ AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target %i", Type);
+ ret = ERRPTR;
break;
}
bs.CurNamespace = NULL;
bs.Script = Script;
-
+ // Parse arguments
for( arg = astFcn->Arguments; arg; arg = arg->NextSibling, i++ )
{
// TODO: Type checks
tSpiderValue *ret = NULL, *tmpobj;
tSpiderValue *op1, *op2; // Binary operations
int cmp; // Used in comparisons
- int i=0;
+ int i;
switch(Node->Type)
{
case NODETYPE_BLOCK:
{
tAST_BlockState blockInfo;
- memcpy(&blockInfo, Block, sizeof(tAST_BlockState));
+ blockInfo.Parent = Block;
+ blockInfo.Script = Block->Script;
blockInfo.FirstVar = NULL;
blockInfo.RetVal = NULL;
- blockInfo.Parent = Block;
+ blockInfo.BaseNamespace = Block->BaseNamespace;
+ blockInfo.CurNamespace = NULL;
ret = NULL;
for(node = Node->Block.FirstChild; node && !blockInfo.RetVal; node = node->NextSibling )
{
- tmpobj = AST_ExecuteNode(&blockInfo, node);
- if(tmpobj == ERRPTR) { // Error check
- ret = ERRPTR;
+ ret = AST_ExecuteNode(&blockInfo, node);
+ if(ret == ERRPTR) { // Error check
break ;
}
- if(tmpobj) Object_Dereference(tmpobj); // Free unused value
- tmpobj = NULL;
+ if(ret) Object_Dereference(ret); // Free unused value
}
// Clean up variables
while(blockInfo.FirstVar)
Variable_Destroy( blockInfo.FirstVar );
blockInfo.FirstVar = nextVar;
}
-
+ if(ret != ERRPTR)
+ ret = NULL;
if( blockInfo.RetVal )
Block->RetVal = blockInfo.RetVal;
}
if( value == ERRPTR )
return ERRPTR;
if(ret) Object_Dereference(ret);
- Object_Dereference(varVal);
+ if(varVal) Object_Dereference(varVal);
ret = value;
}
}
break;
+ case NODETYPE_POSTINC:
+ case NODETYPE_POSTDEC:
+ {
+ tSpiderValue *varVal, *value, *one;
+ if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) {
+ AST_RuntimeError(Node, "LVALUE of assignment is not a variable");
+ return ERRPTR;
+ }
+
+ varVal = Variable_GetValue(Block, Node->Assign.Dest->Variable.Name);
+ one = SpiderScript_CreateInteger(1);
+
+ if( Node->Type == NODETYPE_POSTDEC )
+ value = AST_ExecuteNode_BinOp(Block, NODETYPE_SUBTRACT, varVal, one);
+ else
+ value = AST_ExecuteNode_BinOp(Block, NODETYPE_ADD, varVal, one);
+ if( value == ERRPTR )
+ return ERRPTR;
+ Object_Dereference(one); // Free constant one
+
+ ret = varVal;
+
+ if( Variable_SetValue( Block, Node->Assign.Dest->Variable.Name, value ) ) {
+ Object_Dereference( ret );
+ return ERRPTR;
+ }
+ Object_Dereference( value );
+ }
+ break;
+
// Function Call
case NODETYPE_METHODCALL:
case NODETYPE_FUNCTIONCALL:
case NODETYPE_CREATEOBJECT:
+ // Logical block (used to allocate `params`)
{
- int nParams = 0;
- for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) {
- nParams ++;
- }
- // Logical block (used to allocate `params`)
+ tSpiderValue *params[Node->FunctionCall.NumArgs];
+ i = 0;
+ for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
{
- tSpiderValue *params[nParams];
- i = 0;
- for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
- {
- params[i] = AST_ExecuteNode(Block, node);
- if( params[i] == ERRPTR ) {
- while(i--) Object_Dereference(params[i]);
- ret = ERRPTR;
- goto _return;
- }
- i ++;
- }
-
- if( !Block->CurNamespace )
- Block->CurNamespace = Block->BaseNamespace;
-
- // Call the function
- if( Node->Type == NODETYPE_CREATEOBJECT )
- {
- ret = SpiderScript_CreateObject(Block->Script,
- Block->CurNamespace,
- Node->FunctionCall.Name,
- nParams, params
- );
- }
- else if( Node->Type == NODETYPE_METHODCALL )
- {
- tSpiderValue *obj = AST_ExecuteNode(Block, Node->FunctionCall.Object);
- if( !obj || obj->Type != SS_DATATYPE_OBJECT ) {
- AST_RuntimeError(Node->FunctionCall.Object,
- "Type Mismatch - Required SS_DATATYPE_OBJECT for method call");
- while(i--) Object_Dereference(params[i]);
- ret = ERRPTR;
- break;
- }
- ret = SpiderScript_ExecuteMethod(Block->Script,
- obj->Object, Node->FunctionCall.Name,
- nParams, params
- );
- Object_Dereference(obj);
+ params[i] = AST_ExecuteNode(Block, node);
+ if( params[i] == ERRPTR ) {
+ while(i--) Object_Dereference(params[i]);
+ ret = ERRPTR;
+ goto _return;
}
- else
- {
- ret = SpiderScript_ExecuteFunction(Block->Script,
- Block->CurNamespace, Node->FunctionCall.Name,
- nParams, params
- );
+ i ++;
+ }
+
+ if( !Block->CurNamespace )
+ Block->CurNamespace = Block->BaseNamespace;
+
+ // Call the function
+ if( Node->Type == NODETYPE_CREATEOBJECT )
+ {
+ ret = SpiderScript_CreateObject(Block->Script,
+ Block->CurNamespace,
+ Node->FunctionCall.Name,
+ Node->FunctionCall.NumArgs, params
+ );
+ }
+ else if( Node->Type == NODETYPE_METHODCALL )
+ {
+ tSpiderValue *obj = AST_ExecuteNode(Block, Node->FunctionCall.Object);
+ if( !obj || obj->Type != SS_DATATYPE_OBJECT ) {
+ AST_RuntimeError(Node->FunctionCall.Object,
+ "Type Mismatch - Required SS_DATATYPE_OBJECT for method call");
+ while(i--) Object_Dereference(params[i]);
+ ret = ERRPTR;
+ break;
}
-
-
- // Dereference parameters
- while(i--) Object_Dereference(params[i]);
-
- // falls out
+ ret = SpiderScript_ExecuteMethod(Block->Script,
+ obj->Object, Node->FunctionCall.Name,
+ Node->FunctionCall.NumArgs, params
+ );
+ Object_Dereference(obj);
+ }
+ else
+ {
+ ret = SpiderScript_ExecuteFunction(Block->Script,
+ Block->CurNamespace, Node->FunctionCall.Name,
+ Node->FunctionCall.NumArgs, params
+ );
}
+
+
+ // Dereference parameters
+ while(i--) Object_Dereference(params[i]);
+
+ // falls out
}
break;
// --- Operations ---
// Boolean Operations
+ case NODETYPE_LOGICALNOT: // Logical NOT (!)
+ op1 = AST_ExecuteNode(Block, Node->UniOp.Value);
+ if(op1 == ERRPTR) return ERRPTR;
+ ret = SpiderScript_CreateInteger( !SpiderScript_IsValueTrue(op1) );
+ Object_Dereference(op1);
+ break;
case NODETYPE_LOGICALAND: // Logical AND (&&)
case NODETYPE_LOGICALOR: // Logical OR (||)
case NODETYPE_LOGICALXOR: // Logical XOR (^^)
case NODETYPE_EQUALS:
case NODETYPE_LESSTHAN:
case NODETYPE_GREATERTHAN:
+ case NODETYPE_LESSTHANEQUAL:
+ case NODETYPE_GREATERTHANEQUAL:
op1 = AST_ExecuteNode(Block, Node->BinOp.Left);
if(op1 == ERRPTR) return ERRPTR;
op2 = AST_ExecuteNode(Block, Node->BinOp.Right);
if(op2 == ERRPTR) {
Object_Dereference(op1);
- return ERRPTR;
+ ret = ERRPTR;
+ break;
+ }
+
+ if( !op1 || !op2 ) {
+ AST_RuntimeError(Node, "NULL Comparison (%p and %p)\n", op1, op2);
+ if(op1) Object_Dereference(op1);
+ if(op2) Object_Dereference(op2);
+ ret = SpiderScript_CreateInteger( !op1 && !op2 );
+ break;
}
// Convert types
else
cmp = 1;
break;
+ // - Real Number Comparisons
+ case SS_DATATYPE_REAL:
+ cmp = (op1->Real - op2->Real) / op2->Real * 10000; // < 0.1% difference is equality
+ break;
default:
AST_RuntimeError(Node, "TODO - Comparison of type %i", op1->Type);
ret = ERRPTR;
case NODETYPE_EQUALS: ret = SpiderScript_CreateInteger(cmp == 0); break;
case NODETYPE_LESSTHAN: ret = SpiderScript_CreateInteger(cmp < 0); break;
case NODETYPE_GREATERTHAN: ret = SpiderScript_CreateInteger(cmp > 0); break;
+ case NODETYPE_LESSTHANEQUAL: ret = SpiderScript_CreateInteger(cmp <= 0); break;
+ case NODETYPE_GREATERTHANEQUAL: ret = SpiderScript_CreateInteger(cmp >= 0); break;
default:
AST_RuntimeError(Node, "Exec,CmpOp unknown op %i", Node->Type);
ret = ERRPTR;
}
break;
+ // General Unary Operations
+ case NODETYPE_BWNOT: // Bitwise NOT (~)
+ case NODETYPE_NEGATE: // Negation (-)
+ op1 = AST_ExecuteNode(Block, Node->UniOp.Value);
+ if(op1 == ERRPTR) return ERRPTR;
+ ret = AST_ExecuteNode_UniOp(Block, Node->Type, op1);
+ Object_Dereference(op1);
+ break;
+
// General Binary Operations
case NODETYPE_ADD:
case NODETYPE_SUBTRACT:
return ret;
}
+tSpiderValue *AST_ExecuteNode_UniOp(tAST_BlockState *Block, int Operation, tSpiderValue *Value)
+{
+ tSpiderValue *ret;
+ #if 0
+ if( Value->Type == SS_DATATYPE_OBJECT )
+ {
+ const char *fcnname;
+ switch(Operation)
+ {
+ case NODETYPE_NEGATE: fcnname = "-ve"; break;
+ case NODETYPE_BWNOT: fcnname = "~"; break;
+ default: fcnname = NULL; break;
+ }
+
+ if( fcnname )
+ {
+ ret = Object_ExecuteMethod(Value->Object, fcnname, );
+ if( ret != ERRPTR )
+ return ret;
+ // Fall through and try casting (which will usually fail)
+ }
+ }
+ #endif
+ switch(Value->Type)
+ {
+ // Integer Operations
+ case SS_DATATYPE_INTEGER:
+ switch(Operation)
+ {
+ case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Integer ); break;
+ case NODETYPE_BWNOT: ret = SpiderScript_CreateInteger( ~Value->Integer ); break;
+ default:
+ AST_RuntimeError(NULL, "SpiderScript internal error: Exec,UniOP,Integer unknown op %i", Operation);
+ ret = ERRPTR;
+ break;
+ }
+ break;
+ // Real number Operations
+ case SS_DATATYPE_REAL:
+ switch(Operation)
+ {
+ case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Real ); break;
+ default:
+ AST_RuntimeError(NULL, "SpiderScript internal error: Exec,UniOP,Real unknown op %i", Operation);
+ ret = ERRPTR;
+ break;
+ }
+ break;
+
+ default:
+ AST_RuntimeError(NULL, "Invalid operation (%i) on type (%i)", Operation, Value->Type);
+ ret = ERRPTR;
+ break;
+ }
+
+ return ret;
+}
+
tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, int Operation, tSpiderValue *Left, tSpiderValue *Right)
{
tSpiderValue *preCastValue = Right;
case SS_DATATYPE_REAL:
switch(Operation)
{
+ case NODETYPE_ADD: ret = SpiderScript_CreateReal( Left->Real + Right->Real ); break;
+ case NODETYPE_SUBTRACT: ret = SpiderScript_CreateReal( Left->Real - Right->Real ); break;
+ case NODETYPE_MULTIPLY: ret = SpiderScript_CreateReal( Left->Real * Right->Real ); break;
+ case NODETYPE_DIVIDE: ret = SpiderScript_CreateReal( Left->Real / Right->Real ); break;
default:
AST_RuntimeError(NULL, "SpiderScript internal error: Exec,BinOP,Real unknown op %i", Operation);
ret = ERRPTR;
ret = TOK_AND;
break;
- case '/': ret = TOK_DIV; break;
- case '*': ret = TOK_MUL; break;
+ case '/':
+ if( *File->CurPos == '=' ) {
+ File->CurPos ++;
+ ret = TOK_ASSIGN_DIV;
+ break;
+ }
+ ret = TOK_DIV;
+ break;
+ case '*':
+ if( *File->CurPos == '=' ) {
+ File->CurPos ++;
+ ret = TOK_ASSIGN_MUL;
+ break;
+ }
+ ret = TOK_MUL;
+ break;
case '+':
if( *File->CurPos == '+' ) {
File->CurPos ++;
case '"':
while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') )
File->CurPos ++;
- File->CurPos ++;
- ret = TOK_STR;
+ if( *File->CurPos )
+ {
+ File->CurPos ++;
+ ret = TOK_STR;
+ }
+ else
+ ret = TOK_EOF;
break;
// Brackets
ret = TOK_GT;
break;
+ // Logical NOT
+ case '!':
+ ret = TOK_LOGICNOT;
+ break;
+ // Bitwise NOT
+ case '~':
+ ret = TOK_BWNOT;
+ break;
+
// Variables
// \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]*
case '$':
// Numbers
if( isdigit(*File->CurPos) )
{
+ ret = TOK_INTEGER;
if( *File->CurPos == '0' && File->CurPos[1] == 'x' ) {
File->CurPos += 2;
while(('0' <= *File->CurPos && *File->CurPos <= '9')
else {
while( isdigit(*File->CurPos) )
File->CurPos ++;
+
+ // Decimal
+ if( *File->CurPos == '.' )
+ {
+ ret = TOK_REAL;
+ File->CurPos ++;
+ while( isdigit(*File->CurPos) )
+ File->CurPos ++;
+ }
+ // Exponent
+ if( *File->CurPos == 'e' || *File->CurPos == 'E' )
+ {
+ ret = TOK_REAL;
+ File->CurPos ++;
+ if(*File->CurPos == '-' || *File->CurPos == '+')
+ File->CurPos ++;
+ while( isdigit(*File->CurPos) )
+ File->CurPos ++;
+ }
}
- ret = TOK_INTEGER;
break;
}
// Identifier
if( is_ident(*File->CurPos) )
{
+ ret = TOK_IDENT;
+
// Identifier
while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
File->CurPos ++;
// This is set later too, but we use it below
File->TokenLen = File->CurPos - File->TokenStr;
- ret = TOK_IDENT;
// Check if it's a reserved word
{
return NULL;
}
- // Create the script
- ret = malloc(sizeof(tSpiderScript));
- ret->Variant = Variant;
-
fseek(fp, 0, SEEK_END);
fLen = ftell(fp);
fseek(fp, 0, SEEK_SET);
// Allocate and read data
data = malloc(fLen + 1);
if(!data) return NULL;
- fread(data, fLen, 1, fp);
+ fLen = fread(data, 1, fLen, fp);
+ if( fLen < 0 ) {
+ free(data);
+ return NULL;
+ }
data[fLen] = '\0';
fclose(fp);
+ // Create the script
+ ret = malloc(sizeof(tSpiderScript));
+ ret->Variant = Variant;
+
ret->CurNamespace = NULL;
ret->Script = Parse_Buffer(Variant, data);
if( ret->Script == NULL ) {
tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts
tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic
tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div
+tAST_Node *Parse_DoExpr7(tParser *Parser); // Right Unary Operations
+tAST_Node *Parse_DoExpr8(tParser *Parser); // Left Unary Operations
tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last)
tAST_Node *Parse_DoValue(tParser *Parser); // Values
GetToken(Parser);
false = Parse_DoCodeBlock(Parser);
}
+ else
+ false = AST_NewNop(Parser);
ret = AST_NewIf(Parser, cond, true, false);
}
return ret;
return ret;
case TOK_RWD_DO:
- case TOK_RWD_WHILE:
- TODO(Parser, "Implement do and while\n");
+ {
+ tAST_Node *code, *cond;
+ GetToken(Parser); // Eat 'do'
+ code = Parse_DoCodeBlock(Parser);
+ SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
+ SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
+ cond = Parse_DoExpr0(Parser);
+ SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
+ ret = AST_NewLoop(Parser, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
+ }
break;
+ case TOK_RWD_WHILE:
+ {
+ tAST_Node *code, *cond;
+ GetToken(Parser); // Eat 'while'
+ SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
+ cond = Parse_DoExpr0(Parser);
+ SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
+ code = Parse_DoCodeBlock(Parser);
+ ret = AST_NewLoop(Parser, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
+ }
+ return ret;
// Define Variables
case TOKEN_GROUP_TYPES:
{
int type;
-
- switch(GetToken(Parser))
- {
- case TOK_RWD_INTEGER: type = SS_DATATYPE_INTEGER; break;
- case TOK_RWD_OBJECT: type = SS_DATATYPE_OBJECT; break;
- case TOK_RWD_REAL: type = SS_DATATYPE_REAL; break;
- case TOK_RWD_STRING: type = SS_DATATYPE_STRING; break;
- }
+ GetToken(Parser);
+ TOKEN_GET_DATATYPE(type, Parser->Token);
SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
case TOK_GT:
ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
break;
+ case TOK_LTE:
+ ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, Parse_DoExpr2(Parser));
+ break;
+ case TOK_GTE:
+ ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, Parse_DoExpr2(Parser));
+ break;
default:
PutBack(Parser);
break;
// --------------------
tAST_Node *Parse_DoExpr6(tParser *Parser)
{
- tAST_Node *ret = Parse_DoParen(Parser);
+ tAST_Node *ret = Parse_DoExpr7(Parser);
switch(GetToken(Parser))
{
return ret;
}
+// Right Unary Operations
+tAST_Node *Parse_DoExpr7(tParser *Parser)
+{
+ tAST_Node *ret = Parse_DoExpr8(Parser);
+
+ switch(GetToken(Parser))
+ {
+ case TOK_INCREMENT:
+ ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
+ break;
+ case TOK_DECREMENT:
+ ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
+ break;
+ default:
+ PutBack(Parser);
+ break;
+ }
+ return ret;
+}
+
+// Left Unary Operations
+tAST_Node *Parse_DoExpr8(tParser *Parser)
+{
+ switch(GetToken(Parser))
+ {
+ case TOK_INCREMENT:
+ return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
+ case TOK_DECREMENT:
+ return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
+ case TOK_MINUS:
+ return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
+ case TOK_LOGICNOT:
+ return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
+ case TOK_BWNOT:
+ return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
+ default:
+ PutBack(Parser);
+ return Parse_DoParen(Parser);
+ }
+}
// --------------------
// 2nd Last Expression - Parens
{
case TOK_STR: return Parse_GetString(Parser);
case TOK_INTEGER: return Parse_GetNumeric(Parser);
+ case TOK_REAL:
+ GetToken(Parser);
+ return AST_NewReal( Parser, atof(Parser->TokenStr) );
+
case TOK_IDENT: return Parse_GetIdent(Parser, 0);
case TOK_VARIABLE: return Parse_GetVariable(Parser);
case TOK_RWD_NEW:
{
uint64_t value = 0;
char *pos;
- GetToken( Parser );
+ SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
pos = Parser->TokenStr;
//printf("pos = %p, *pos = %c\n", pos, *pos);
// Primitives
TOK_STR,
TOK_INTEGER,
+ TOK_REAL,
TOK_VARIABLE,
TOK_IDENT,
TOK_GT, TOK_GTE,
// Operations
+ TOK_BWNOT, TOK_LOGICNOT,
TOK_DIV, TOK_MUL,
TOK_PLUS, TOK_MINUS,
TOK_SHL, TOK_SHR,
case TOK_RWD_OBJECT: _type = SS_DATATYPE_OBJECT; break;\
case TOK_RWD_REAL: _type = SS_DATATYPE_REAL; break;\
case TOK_RWD_STRING: _type = SS_DATATYPE_STRING; break;\
- default:fprintf(stderr,\
+ default:_type=SS_DATATYPE_UNDEF;fprintf(stderr,\
"ERROR: Unexpected %s, expected "TOKEN_GROUP_TYPES_STR"\n",csaTOKEN_NAMES[Parser->Token]);\
break;\
} } while(0)
"TOK_STR",
"TOK_INTEGER",
+ "TOK_REAL",
"TOK_VARIABLE",
"TOK_IDENT",
"TOK_LT", "TOK_LTE",
"TOK_GT", "TOK_GTE",
+ "TOK_BWNOT", "TOK_LOGICNOT",
"TOK_DIV", "TOK_MUL",
"TOK_PLUS", "TOK_MINUS",
"TOK_SHL", "TOK_SHR",