Usermode/SpiderScript - Added compile-time type checking and smarter variable typing
authorJohn Hodge <[email protected]>
Tue, 17 Apr 2012 02:44:02 +0000 (10:44 +0800)
committerJohn Hodge <[email protected]>
Tue, 17 Apr 2012 02:44:02 +0000 (10:44 +0800)
Usermode/Libraries/libspiderscript.so_src/Makefile
Usermode/Libraries/libspiderscript.so_src/ast.h
Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c
Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c
Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c
Usermode/Libraries/libspiderscript.so_src/exec.c
Usermode/Libraries/libspiderscript.so_src/exec_ast.c
Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c
Usermode/Libraries/libspiderscript.so_src/parse.c
Usermode/Libraries/libspiderscript.so_src/tokens.h
Usermode/include/spiderscript.h

index 28382ca..8988c01 100644 (file)
@@ -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
index 6548ad7..39a78fd 100644 (file)
@@ -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
index d1b62ff..66437bc 100644 (file)
@@ -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;
                }
index e2b1683..e4e62ab 100644 (file)
@@ -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);
index f90fb33..3c0347b 100644 (file)
@@ -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);
index 5379357..f124497 100644 (file)
@@ -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;
                }
        }
        
index 78e6740..b6448d3 100644 (file)
@@ -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
 
index 50dfec4..afc63bf 100644 (file)
@@ -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;
index fdd5474..5be878d 100644 (file)
@@ -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);
index 0139fc6..4b2acb2 100644 (file)
@@ -32,6 +32,8 @@ typedef struct
        
        jmp_buf JmpTarget;
         int    ErrorHit;
+       
+       struct sSpiderVariant   *Variant;
 }      tParser;
 
 // === FUNCTIONS ===
index e1dc507..92e6c13 100644 (file)
@@ -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,
        /**

UCC git Repository :: git.ucc.asn.au