From 92f8ce7927ee2ea3feb4b80a45f54f6fe8056c52 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 17 Apr 2012 10:44:02 +0800 Subject: [PATCH] Usermode/SpiderScript - Added compile-time type checking and smarter variable typing --- .../Libraries/libspiderscript.so_src/Makefile | 4 +- .../Libraries/libspiderscript.so_src/ast.h | 6 + .../libspiderscript.so_src/ast_to_bytecode.c | 260 ++++++++++-------- .../libspiderscript.so_src/bytecode_gen.c | 2 +- .../bytecode_makefile.c | 8 +- .../Libraries/libspiderscript.so_src/exec.c | 4 +- .../libspiderscript.so_src/exec_ast.c | 5 + .../libspiderscript.so_src/exec_bytecode.c | 5 +- .../Libraries/libspiderscript.so_src/parse.c | 14 + .../Libraries/libspiderscript.so_src/tokens.h | 2 + Usermode/include/spiderscript.h | 2 +- 11 files changed, 182 insertions(+), 130 deletions(-) diff --git a/Usermode/Libraries/libspiderscript.so_src/Makefile b/Usermode/Libraries/libspiderscript.so_src/Makefile index 28382cad..8988c01a 100644 --- a/Usermode/Libraries/libspiderscript.so_src/Makefile +++ b/Usermode/Libraries/libspiderscript.so_src/Makefile @@ -7,7 +7,9 @@ CPPFLAGS += CFLAGS += -Wall LDFLAGS += -lc -lgcc -soname libspiderscript.so --no-allow-shlib-undefined -OBJ = main.o lex.o parse.o ast.o exec_ast.o exports.o +OBJ = main.o lex.o parse.o ast.o exports.o values.o +OBJ += ast_to_bytecode.o bytecode_gen.o bytecode_makefile.o +OBJ += exec.o exec_bytecode.o BIN = libspiderscript.so include ../Makefile.tpl diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.h b/Usermode/Libraries/libspiderscript.so_src/ast.h index 6548ad72..39a78fd4 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ b/Usermode/Libraries/libspiderscript.so_src/ast.h @@ -22,17 +22,20 @@ enum eAST_NodeTypes NODETYPE_BLOCK, //!< Node Block + // 2 NODETYPE_VARIABLE, //!< Variable NODETYPE_CONSTANT, //!< Runtime Constant NODETYPE_STRING, //!< String Constant NODETYPE_INTEGER, //!< Integer Constant NODETYPE_REAL, //!< Real Constant + // 7 NODETYPE_DEFVAR, //!< Define a variable (Variable) NODETYPE_SCOPE, //!< Dereference a Namespace/Class static NODETYPE_ELEMENT, //!< Reference a class attribute NODETYPE_CAST, //!< Cast a value to another (Uniop) + // 11 NODETYPE_RETURN, //!< Return from a function (reserved word) NODETYPE_BREAK, //!< Break out of a loop NODETYPE_CONTINUE, //!< Next loop iteration @@ -43,11 +46,14 @@ enum eAST_NodeTypes NODETYPE_METHODCALL, //!< Call a class method NODETYPE_CREATEOBJECT, //!< Create an object + // 20 NODETYPE_IF, //!< Conditional NODETYPE_LOOP, //!< Looping Construct + // 22 NODETYPE_INDEX, //!< Index into an array + // 23 NODETYPE_LOGICALNOT, //!< Logical NOT operator NODETYPE_LOGICALAND, //!< Logical AND operator NODETYPE_LOGICALOR, //!< Logical OR operator diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c index d1b62ffc..66437bc8 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c @@ -13,7 +13,7 @@ #include "bytecode_ops.h" #define TRACE_VAR_LOOKUPS 0 -#define TRACE_NODE_RETURNS 0 +#define TRACE_TYPE_STACK 0 #define MAX_NAMESPACE_DEPTH 10 #define MAX_STACK_DEPTH 10 // This is for one function, so shouldn't need more @@ -34,7 +34,9 @@ typedef struct sAST_BlockInfo const char *CurNamespaceStack[MAX_NAMESPACE_DEPTH]; int StackDepth; - char Stack[MAX_STACK_DEPTH]; // Stores types of stack values + int Stack[MAX_STACK_DEPTH]; // Stores types of stack values + + tAST_Variable *FirstVar; } tAST_BlockInfo; // === PROTOTYPES === @@ -84,6 +86,7 @@ tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn) bi.Handle = ret; if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) ) { + AST_RuntimeError(Fcn->ASTFcn, "Error in converting function"); Bytecode_DeleteFunction(ret); return NULL; } @@ -133,7 +136,11 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) node; node = node->NextSibling ) { - AST_ConvertNode(Block, node, 0); + ret = AST_ConvertNode(Block, node, 0); + if(ret) return ret; + if( blockInfo.StackDepth != 0 ) { + AST_RuntimeError(node, "Stack not reset at end of node"); + } } } Bytecode_AppendLeaveContext(Block->Handle); // Leave this context @@ -148,13 +155,14 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) ret = AST_ConvertNode(Block, Node->Assign.Dest, 1); if(ret) return ret; + t1 = _StackPop(Block, Node, SS_DATATYPE_UNDEF); + if(t1 < 0) return -1; + ret = AST_ConvertNode(Block, Node->Assign.Value, 1); if(ret) return ret; + t2 = _StackPop(Block, Node, SS_DATATYPE_UNDEF); + if(t2 < 0) return -1; - t1 = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(t1 < 0) return ret; - t2 = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(t1 < 0) return ret; switch(Node->Assign.Operation) { @@ -177,7 +185,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) } // printf("assign, op = %i\n", op); ret = _StackPush(Block, Node, t1); - if(ret < 0) return ret; + if(ret < 0) return -1; Bytecode_AppendBinOp(Block->Handle, op); } else @@ -188,15 +196,16 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) if( bKeepValue ) { ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return ret; + if(ret < 0) return -1; ret = _StackPush(Block, Node, ret); - if(ret < 0) return ret; + if(ret < 0) return -1; ret = _StackPush(Block, Node, ret); - if(ret < 0) return ret; + if(ret < 0) return -1; Bytecode_AppendDuplicate(Block->Handle); } ret = BC_SaveValue(Block, Node->Assign.Dest); + if(ret) return ret; break; // Post increment/decrement @@ -210,7 +219,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) Bytecode_AppendConstInt(Block->Handle, 1); ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER); - if(ret < 0) return ret; + if(ret < 0) return -1; ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); if(ret) return ret; @@ -221,8 +230,9 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD); ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER); // TODO: Check for objects too - if(ret < 0) return ret; + if(ret < 0) return -1; ret = BC_SaveValue(Block, Node->UniOp.Value); + if(ret) return ret; break; // Function Call @@ -241,14 +251,15 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) // TODO: Check arguments? Need to get the types somehow ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return ret; + if(ret < 0) return -1; } ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT); - if(ret < 0) return ret; + if(ret < 0) return -1; Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs); - ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); + ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; CHECK_IF_NEEDED(0); // Don't warn // TODO: Implement warn_unused_ret @@ -285,8 +296,8 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) nargs ++; // TODO: Check arguments? Need to get the types somehow - ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return ret; + ret = _StackPop(Block, node, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; } // Call the function @@ -300,7 +311,8 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) } // TODO: Get return type - ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); + ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; CHECK_IF_NEEDED(0); // Don't warn // TODO: Implement warn_unused_ret @@ -311,6 +323,9 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) int if_end; ret = AST_ConvertNode(Block, Node->If.Condition, 1); if(ret) return ret; + // TODO: Should be boolean/integer, but meh + ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; if_end = Bytecode_AllocateLabel(Block->Handle); @@ -318,9 +333,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) { int if_true = Bytecode_AllocateLabel(Block->Handle); - // TODO: Should be boolean, but do I care realy? - ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); - if(ret < 0) return ret; Bytecode_AppendCondJump(Block->Handle, if_true); // False @@ -331,9 +343,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) } else { - // TODO: Should really be boolean, but meh - ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); - if(ret < 0) return ret; Bytecode_AppendCondJumpNot(Block->Handle, if_end); } @@ -374,7 +383,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) if(ret) return ret; Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT); ret = _StackPop(Block, Node->For.Condition, SS_DATATYPE_UNDEF); // Boolean? - if(ret < 0) return ret; + if(ret < 0) return -1; Bytecode_AppendCondJump(Block->Handle, loop_end); } @@ -386,7 +395,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) ret = AST_ConvertNode(Block, Node->For.Increment, 0); if(ret) return ret; // ret = _StackPop(Block, Node->For.Increment, SS_DATATYPE_UNDEF); // TODO: Check if needed -// if(ret < 0) return ret; +// if(ret < 0) return -1; // Tail check if( Node->For.bCheckAfter ) @@ -415,6 +424,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) if(ret) return ret; Bytecode_AppendReturn(Block->Handle); ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); // + if(ret < 0) return -1; break; case NODETYPE_BREAK: @@ -441,7 +451,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1); if(ret) return ret; ret = _StackPop(Block, Node->DefVar.InitialValue, Node->DefVar.DataType); - if(ret < 0) return ret; + if(ret < 0) return -1; Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name); } break; @@ -455,17 +465,18 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) Block->CurNamespaceStack[ Block->NamespaceDepth ] = Node->Scope.Name; Block->NamespaceDepth ++; ret = AST_ConvertNode(Block, Node->Scope.Element, bKeepValue); + if(ret) return ret; if( Block->NamespaceDepth != 0 ) { AST_RuntimeError(Node, "Namespace scope used but no element at the end"); } bAddedValue = 0; - CHECK_IF_NEEDED(0); // No warning? break; // Variable case NODETYPE_VARIABLE: ret = BC_Variable_GetValue( Block, Node ); CHECK_IF_NEEDED(1); + if(ret) return ret; break; // Element of an Object @@ -473,12 +484,12 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) ret = AST_ConvertNode( Block, Node->Scope.Element, 1 ); if(ret) return ret; - ret = _StackPop(Block, Node->Scope.Element, SS_DATATYPE_OBJECT); - if(ret < 0) return ret; + ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT); + if(ret < 0) return -1; Bytecode_AppendElement(Block->Handle, Node->Scope.Name); ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); - if(ret<0) return ret; + if(ret < 0) return -1; CHECK_IF_NEEDED(1); break; @@ -486,30 +497,45 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) case NODETYPE_CAST: ret = AST_ConvertNode(Block, Node->Cast.Value, 1); if(ret) return ret; - ret = _StackPop(Block, Node->Cast.Value, SS_DATATYPE_UNDEF); - if(ret<0) return ret; + ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; Bytecode_AppendCast(Block->Handle, Node->Cast.DataType); ret = _StackPush(Block, Node, Node->Cast.DataType); - if(ret<0) return ret; + if(ret < 0) return -1; CHECK_IF_NEEDED(1); break; // Index into an array case NODETYPE_INDEX: - ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); // Array + // - Array + ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); if(ret) return ret; - ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); // Offset + // > Type check + ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; + if(ret != SS_DATATYPE_ARRAY && (ret >> 16) == 0) { + AST_RuntimeError(Node, "Type mismatch, Expected an array, got %i", + ret); + return -2; + } + i = ret; // Hackily save the datatype + + // - Offset + ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); if(ret) return ret; - - ret = _StackPop(Block, Node->BinOp.Right, SS_DATATYPE_ARRAY); - if(ret<0) return ret; - ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_INTEGER); - if(ret<0) return ret; + ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER); + if(ret < 0) return -1; Bytecode_AppendIndex(Block->Handle); - ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); // TODO: Get array datatype? - if(ret<0) return ret; + + // Update the array depth + if( i != SS_DATATYPE_ARRAY ) { + i -= 0x10000; // Decrease the array level + } + ret = _StackPush(Block, Node, i); + if(ret < 0) return -1; + CHECK_IF_NEEDED(1); break; @@ -525,19 +551,19 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) case NODETYPE_STRING: Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length); ret = _StackPush(Block, Node, SS_DATATYPE_STRING); - if(ret<0) return ret; + if(ret < 0) return -1; CHECK_IF_NEEDED(1); break; case NODETYPE_INTEGER: Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer); ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER); - if(ret<0) return ret; + if(ret < 0) return -1; CHECK_IF_NEEDED(1); break; case NODETYPE_REAL: Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real); ret = _StackPush(Block, Node, SS_DATATYPE_REAL); - if(ret<0) return ret; + if(ret < 0) return -1; CHECK_IF_NEEDED(1); break; @@ -552,11 +578,11 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); if(ret) return ret; ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Undef - if(ret<0) return ret; + if(ret < 0) return -1; Bytecode_AppendUniOp(Block->Handle, op); ret = _StackPush(Block, Node, ret); // TODO: Logic = _INTEGER, Neg = No change - if(ret<0) return ret; + if(ret < 0) return -1; CHECK_IF_NEEDED(1); break; @@ -586,35 +612,25 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) case NODETYPE_BITROTATELEFT: if(!op) op = BC_OP_BITROTATELEFT; ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); if(ret) return ret; + ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object + if(ret < 0) return -1; + ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); if(ret) return ret; - ret = _StackPop(Block, Node->BinOp.Right, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object - if(ret<0) return ret; - ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object - if(ret<0) return ret; - + if(ret < 0) return -1; + Bytecode_AppendBinOp(Block->Handle, op); _StackPush(Block, Node, ret); CHECK_IF_NEEDED(1); break; default: - ret = -1; AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type); - break; - } - - #if TRACE_NODE_RETURNS - if(ret && ret != ERRPTR) { - AST_RuntimeError(Node, "Ret type of %p %i is %i", Node, Node->Type, ret->Type); - } - else { - AST_RuntimeError(Node, "Ret type of %p %i is %p", Node, Node->Type, ret); + return -1; } - #endif - return ret; + return 0; } int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode) @@ -630,14 +646,28 @@ int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode) case NODETYPE_INDEX: ret = AST_ConvertNode(Block, DestNode->BinOp.Left, 1); // Array if(ret) return ret; + ret = _StackPop(Block, DestNode->BinOp.Left, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; + if(ret != SS_DATATYPE_ARRAY && (ret >> 16) == 0) { + AST_RuntimeError(DestNode, "Type mismatch, Expected an array, got %i", + ret); + return -2; + } + ret = AST_ConvertNode(Block, DestNode->BinOp.Right, 1); // Offset if(ret) return ret; + ret = _StackPop(Block, DestNode->BinOp.Right, SS_DATATYPE_INTEGER); + if(ret < 0) return -1; + Bytecode_AppendSetIndex( Block->Handle ); break; // Object element case NODETYPE_ELEMENT: ret = AST_ConvertNode(Block, DestNode->Scope.Element, 1); if(ret) return ret; + ret = _StackPop(Block, DestNode->Scope.Element, SS_DATATYPE_OBJECT); + if(ret < 0) return -1; + Bytecode_AppendSetElement( Block->Handle, DestNode->Scope.Name ); break; // Anything else @@ -646,7 +676,7 @@ int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode) AST_RuntimeError(DestNode, "Assignment target is not a LValue"); return -1; } - return ret; + return 0; } /** @@ -658,14 +688,13 @@ int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode) */ int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name) { - #if 0 tAST_Variable *var, *prev = NULL; for( var = Block->FirstVar; var; prev = var, var = var->Next ) { if( strcmp(var->Name, Name) == 0 ) { AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name); - return ERRPTR; + return -1; } } @@ -677,69 +706,44 @@ int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name) if(prev) prev->Next = var; else Block->FirstVar = var; - return var; - #else Bytecode_AppendDefineVar(Block->Handle, Name, Type); return 0; - #endif } tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType) { - #if 0 tAST_Variable *var = NULL; + tAST_BlockInfo *bs; - // Speed hack - if( VarNode->BlockState == Block && VarNode->BlockIdent == Block->Ident ) { - var = VarNode->ValueCache; - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Fast var fetch on '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - VarNode->BlockState, VarNode->BlockIdent - ); - #endif - } - else + for( bs = Block; bs; bs = bs->Parent ) { - tAST_BlockInfo *bs; - for( bs = Block; bs; bs = bs->Parent ) + for( var = bs->FirstVar; var; var = var->Next ) { - for( var = bs->FirstVar; var; var = var->Next ) - { - if( strcmp(var->Name, VarNode->Variable.Name) == 0 ) - break; - } - if(var) break; - } - - if( !var ) - { - if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) { - // Define variable - var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL); - } - else - { - AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name); - return NULL; - } + if( strcmp(var->Name, VarNode->Variable.Name) == 0 ) + break; } - - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Saved variable lookup of '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - Block, Block->Ident); - #endif - - VarNode->ValueCache = var; - VarNode->BlockState = Block; - VarNode->BlockIdent = Block->Ident; + if(var) break; } - return var; - #else - return (void*)1; + if( !var ) + { +// if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) { +// // Define variable +// var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL); +// } +// else +// { + AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name); + return NULL; +// } + } + + #if TRACE_VAR_LOOKUPS + AST_RuntimeMessage(VarNode, "debug", "Variable lookup of '%s' %p type %i", + VarNode->Variable.Name, var, var->Type); #endif + + return var; } /** @@ -750,11 +754,13 @@ int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) { tAST_Variable *var; + // TODO: Implicit definition type var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF); if(!var) return -1; // TODO: Check types + _StackPop(Block, VarNode, var->Type); Bytecode_AppendSaveVar(Block->Handle, VarNode->Variable.Name); return 0; } @@ -769,6 +775,7 @@ int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) var = BC_Variable_Lookup(Block, VarNode, 0); if(!var) return -1; + _StackPush(Block, VarNode, var->Type); Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name); return 0; } @@ -805,10 +812,14 @@ void AST_RuntimeError(tAST_Node *Node, const char *Format, ...) int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type) { if(Block->StackDepth == MAX_STACK_DEPTH - 1) { - AST_RuntimeError(Node, "BUG - Stack overflow in AST-Bytecode conversion"); + AST_RuntimeError(Node, "BUG - Stack overflow in AST-Bytecode conversion (node=%i)", + Node->Type); return -1; } - + + #if TRACE_TYPE_STACK + AST_RuntimeMessage(Node, "_StackPush", "%x - NT%i", Type, Node->Type); + #endif Block->Stack[ ++Block->StackDepth ] = Type; return Type; } @@ -816,12 +827,19 @@ int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type) int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType) { if(Block->StackDepth == 0) { - AST_RuntimeError(Node, "BUG - Stack underflow in AST-Bytecode conversion"); + AST_RuntimeError(Node, "BUG - Stack underflow in AST-Bytecode conversion (node=%i)", + Node->Type); return -1; } + #if TRACE_TYPE_STACK + AST_RuntimeMessage(Node, "_StackPop", "%x(?==%x) - NT%i", + Block->Stack[ Block->StackDepth ], WantedType, Node->Type); + #endif if(WantedType != SS_DATATYPE_UNDEF && Block->Stack[ Block->StackDepth ] != SS_DATATYPE_UNDEF) { if( Block->Stack[ Block->StackDepth ] != WantedType ) { + AST_RuntimeError(Node, "AST-Bytecode - Type mismatch (wanted %x got %x)", + WantedType, Block->Stack[ Block->StackDepth ]); // TODO: Message? return -2; } diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c index e2b1683d..e4e62ab5 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c @@ -226,7 +226,7 @@ int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *Labe break; // Special case for inline values case BC_OP_LOADINT: - _put_index(op->Content.Integer); + _put_qword(op->Content.Integer); break; case BC_OP_LOADREAL: _put_double(op->Content.Real); diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c index f90fb333..3c0347bd 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c @@ -88,7 +88,13 @@ int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile) fcn_hdr_offset += 4+4+1+1+(4+1)*fcn->ArgumentCount; // Write code - if( !fcn->BCFcn ) Bytecode_ConvertFunction(fcn); + if( !fcn->BCFcn ) + Bytecode_ConvertFunction(fcn); + if( !fcn->BCFcn ) + { + fclose(fp); + return 1; + } code = Bytecode_SerialiseFunction(fcn->BCFcn, &len, &strings); fwrite(code, len, 1, fp); free(code); diff --git a/Usermode/Libraries/libspiderscript.so_src/exec.c b/Usermode/Libraries/libspiderscript.so_src/exec.c index 53793578..f1244974 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec.c @@ -38,6 +38,7 @@ tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, tSpiderValue *ret = ERRPTR; // First: Find the function in the script + if( !Namespace ) { tScript_Function *fcn; for( fcn = Script->Functions; fcn; fcn = fcn->Next ) @@ -48,13 +49,12 @@ tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, // Execute! if(fcn) { - #if 1 if( fcn->BCFcn ) ret = Bytecode_ExecuteFunction(Script, fcn, NArguments, Arguments); else - #endif ret = AST_ExecuteFunction(Script, fcn, NArguments, Arguments); bFound = 1; + return ret; } } diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c index 78e6740c..b6448d3b 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c @@ -10,6 +10,7 @@ #include "common.h" #include "ast.h" +#define USE_AST_EXEC 1 #define TRACE_VAR_LOOKUPS 0 #define TRACE_NODE_RETURNS 0 @@ -33,6 +34,7 @@ void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); int giNextBlockIdent = 1; // === CODE === +#if USE_AST_EXEC tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments) { tAST_BlockState bs; @@ -646,6 +648,7 @@ _return: return ret; } +#endif tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value) { @@ -938,6 +941,7 @@ tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int return ret; } +#if USE_AST_EXEC /** * \brief Define a variable * \param Block Current block state @@ -1074,4 +1078,5 @@ void Variable_Destroy(tAST_Variable *Variable) SpiderScript_DereferenceValue(Variable->Object); free(Variable); } +#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c index 50dfec45..afc63bf0 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -410,7 +410,7 @@ int Bytecode_int_LocalBinOp_Integer(int Operation, tBC_StackEnt *Val1, tBC_Stack case BC_OP_BITOR: Val1->Integer = Val1->Integer | Val2->Integer; break; case BC_OP_BITXOR: Val1->Integer = Val1->Integer ^ Val2->Integer; break; case BC_OP_MODULO: Val1->Integer = Val1->Integer % Val2->Integer; break; - default: AST_RuntimeError(NULL, "Invalid operation on datatype %i", Val1->Type); return -1; + default: AST_RuntimeError(NULL, "Invalid operation on datatype Integer"); return -1; } return 0; } @@ -431,7 +431,7 @@ int Bytecode_int_LocalBinOp_Real(int Operation, tBC_StackEnt *Val1, tBC_StackEnt case BC_OP_GREATERTHAN: Val1->Integer = (Val1->Real > Val2->Real); break; case BC_OP_GREATERTHANOREQUAL: Val1->Integer = (Val1->Real >= Val2->Real); break; - default: AST_RuntimeError(NULL, "Invalid operation on datatype %i", Val1->Type); return -1; + default: AST_RuntimeError(NULL, "Invalid operation on datatype Real"); return -1; } Val1->Type = SS_DATATYPE_INTEGER; // Becomes logical return 0; @@ -494,7 +494,6 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t // Jumps case BC_OP_JUMP: STATE_HDR(); - // NOTE: Evil, all jumps are off by -1, so fix that jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next; DEBUG_F("JUMP #%i %p\n", OP_INDX(op), jmp_target); nextop = jmp_target; diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c index fdd54746..5be878df 100644 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ b/Usermode/Libraries/libspiderscript.so_src/parse.c @@ -85,6 +85,7 @@ int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename *(int*)(parser.Filename) = 0; // Set reference count parser.Filename += sizeof(int); // Move filename parser.ErrorHit = 0; + parser.Variant = Script->Variant; mainCode = AST_NewCodeBlock(&parser); @@ -455,15 +456,18 @@ tAST_Node *Parse_GetVarDef(tParser *Parser, int Type) { char name[Parser->TokenLen]; tAST_Node *ret; + int level; SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE); // copy the name (trimming the $) memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1); name[Parser->TokenLen-1] = 0; + // Define the variable ret = AST_NewDefineVar(Parser, Type, name); // Handle arrays + level = 0; while( LookAhead(Parser) == TOK_SQUARE_OPEN ) { tAST_Node *node; @@ -475,8 +479,18 @@ tAST_Node *Parse_GetVarDef(tParser *Parser, int Type) } AST_AppendNode(ret, node); SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE); + level ++; } + // Maul the type to denote the dereference level + if( Parser->Variant->bDyamicTyped ) { + ret->DefVar.DataType = SS_DATATYPE_ARRAY; + } + else { + ret->DefVar.DataType |= (level << 16); + } + + // Initial value if( LookAhead(Parser) == TOK_ASSIGN ) { GetToken(Parser); diff --git a/Usermode/Libraries/libspiderscript.so_src/tokens.h b/Usermode/Libraries/libspiderscript.so_src/tokens.h index 0139fc6c..4b2acb20 100644 --- a/Usermode/Libraries/libspiderscript.so_src/tokens.h +++ b/Usermode/Libraries/libspiderscript.so_src/tokens.h @@ -32,6 +32,8 @@ typedef struct jmp_buf JmpTarget; int ErrorHit; + + struct sSpiderVariant *Variant; } tParser; // === FUNCTIONS === diff --git a/Usermode/include/spiderscript.h b/Usermode/include/spiderscript.h index e1dc5078..92e6c139 100644 --- a/Usermode/include/spiderscript.h +++ b/Usermode/include/spiderscript.h @@ -51,7 +51,7 @@ enum eSpiderScript_DataTypes */ SS_DATATYPE_OBJECT, /** - * \brief Array data type + * \brief Array data type (invalid when using static typing) */ SS_DATATYPE_ARRAY, /** -- 2.20.1