SpiderScript - Restructured to be able to keep bytecode and AST in memory at one...
authorJohn Hodge <[email protected]>
Sun, 18 Sep 2011 04:48:28 +0000 (12:48 +0800)
committerJohn Hodge <[email protected]>
Sun, 18 Sep 2011 04:48:28 +0000 (12:48 +0800)
- Also removed the linked list of argument nodes in function def

12 files changed:
Usermode/Libraries/libspiderscript.so_src/ast.c
Usermode/Libraries/libspiderscript.so_src/ast.h
Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c
Usermode/Libraries/libspiderscript.so_src/bytecode.h
Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c
Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h
Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c
Usermode/Libraries/libspiderscript.so_src/common.h [new file with mode: 0644]
Usermode/Libraries/libspiderscript.so_src/exec_ast.c
Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c
Usermode/Libraries/libspiderscript.so_src/main.c
Usermode/Libraries/libspiderscript.so_src/parse.c

index bafdd12..78a54be 100644 (file)
@@ -5,68 +5,61 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "common.h"
 #include "ast.h"
 
 // === IMPORTS ===
 extern void    SyntaxError(tParser *Parser, int bFatal, const char *Message, ...);
 
 // === CODE ===
-tAST_Script *AST_NewScript(void)
-{
-       tAST_Script     *ret = malloc( sizeof(tAST_Script) );
-       
-       ret->Functions = NULL;
-       ret->LastFunction = NULL;
-       
-       return ret;
-}
-
 /**
  * \brief Append a function to a script
  */
-tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name, int ReturnType)
+int AST_AppendFunction(tSpiderScript *Script, const char *Name, int ReturnType, tAST_Node *Args, tAST_Node *Code)
 {
-       tAST_Function   *ret;
-       
-       ret = malloc( sizeof(tAST_Function) + strlen(Name) + 1 );
-       if(!ret)        return NULL;
-       
-       ret->Next = NULL;
-       strcpy(ret->Name, Name);
-       ret->Code = NULL;
-       ret->Arguments = NULL;
-       ret->ArgumentCount = 0;
-       ret->ReturnType = ReturnType;
-       
-       if(Script->LastFunction == NULL) {
-               Script->Functions = Script->LastFunction = ret;
+       tScript_Function        *fcn;
+        int    arg_count = 0, arg_bytes = 0;
+       tAST_Node       *arg;
+
+       // Count and size arguments
+       for(arg = Args; arg; arg = arg->NextSibling)
+       {
+               arg_count ++;
+               arg_bytes += sizeof(fcn->Arguments[0]) + strlen(Args->DefVar.Name) + 1;
        }
-       else {
-               Script->LastFunction->Next = ret;
-               Script->LastFunction = ret;
+
+       // Allocate information
+       fcn = malloc( sizeof(tScript_Function) + arg_bytes + strlen(Name) + 1 );
+       if(!fcn)        return -1;
+       fcn->Next = NULL;
+       fcn->Name = (char*)&fcn->Arguments[arg_count];
+       strcpy(fcn->Name, Name);
+       fcn->ReturnType = ReturnType;
+       fcn->ArgumentCount = arg_count;
+       fcn->ASTFcn = Code;
+       fcn->BCFcn = NULL;
+       
+       // Set arguments
+       arg_bytes = strlen(Name) + 1;   // Used as an offset into fcn->Name
+       arg_count = 0;
+       for(arg = Args; arg; arg = arg->NextSibling)
+       {
+               fcn->Arguments[arg_count].Name = fcn->Name + arg_bytes;
+               strcpy(fcn->Arguments[arg_count].Name, arg->DefVar.Name);
+               fcn->Arguments[arg_count].Type = arg->DefVar.DataType;
+               arg_bytes += strlen(arg->DefVar.Name) + 1;
+               arg_count ++;
        }
        
-       return ret;
-}
-
-void AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Node)
-{
-       if( !Function->Arguments ) {
-               Function->Arguments_Last = Function->Arguments = Node;
+       if(Script->LastFunction == NULL) {
+               Script->Functions = Script->LastFunction = fcn;
        }
        else {
-               Function->Arguments_Last->NextSibling = Node;
-               Function->Arguments_Last = Node;
+               Script->LastFunction->Next = fcn;
+               Script->LastFunction = fcn;
        }
-       Function->ArgumentCount ++;
-}
-
-/**
- * \brief Set the code for a function
- */
-void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root)
-{
-       Function->Code = Root;
+       
+       return 0;
 }
 
 /**
@@ -122,10 +115,11 @@ void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root)
  * \return Size of encoded data
  * \note If \a Buffer is NULL, no write is done, but the size is still returned
  */
-size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
+size_t AST_WriteScript(void *Buffer, tSpiderScript *Script)
 {
-       tAST_Function   *fcn;
+       tScript_Function        *fcn;
        size_t  ret = 0, ptr = 0;
+        int    i;
        
        for( fcn = Script->Functions; fcn; fcn = fcn->Next )
        {
@@ -133,9 +127,14 @@ size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
                ptr = ret;
                WRITE_32(Buffer, ret, 0);       // Next
                WRITE_STR(Buffer, ret, fcn->Name);
-               WRITE_NODELIST(Buffer, ret, fcn->Arguments);    // TODO: Cheaper way
-               ret += AST_WriteNode(Buffer, ret, fcn->Code);
-               WRITE_32(Buffer, ptr, ret);     // Actually set next
+               WRITE_32(Buffer, ret, fcn->ArgumentCount);
+               for( i = 0; i < fcn->ArgumentCount; i ++ )
+               {
+                       WRITE_16(Buffer, ret, fcn->Arguments[i].Type);
+                       WRITE_STR(Buffer, ret, fcn->Arguments[i].Name);
+               }
+               ret += AST_WriteNode(Buffer, ret, fcn->ASTFcn);
+               WRITE_32(Buffer, ptr, ret);     // Actually set `Next`
        }
        if( ptr )
        {
@@ -492,7 +491,9 @@ tAST_Node *AST_NewLoop(tParser *Parser, const char *Tag, tAST_Node *Init, int bP
 {
        tAST_Node       *ret;
        if(!Tag)        Tag = "";
-       ret = AST_int_AllocateNode(Parser, NODETYPE_LOOP, strlen(Tag) + 1);
+       // NOTE: The +3) & ~3 is to align the size to 4 bytes, and shut valgrind up
+       // - GCC sometimes inlines strlen as a loop of dword reads, triggering valgrind
+       ret = AST_int_AllocateNode(Parser, NODETYPE_LOOP, (strlen(Tag) + 1 + 3) & ~3);
        ret->For.Init = Init;
        ret->For.bCheckAfter = !!bPostCheck;
        ret->For.Condition = Condition;
index 39c23b1..39ea294 100644 (file)
@@ -76,31 +76,6 @@ enum eAST_NodeTypes
        NODETYPE_MODULO,        //!< Modulus
 };
 
-struct sSpiderScript
-{
-       tSpiderVariant  *Variant;
-       tAST_Script     *Script;
-       char    *CurNamespace;  //!< Current namespace prefix (NULL = Root) - No trailing .
-};
-
-struct sAST_Script
-{
-       // TODO: Namespaces and Classes
-       tAST_Function   *Functions;
-       tAST_Function   *LastFunction;
-};
-
-struct sAST_Function
-{
-       tAST_Function   *Next;  //!< Next function in list
-        int    ReturnType;
-       tAST_Node       *Code;  //!< Function Code
-       tAST_Node       *Arguments;     // HACKJOB (Only NODETYPE_DEFVAR is allowed)
-       tAST_Node       *Arguments_Last;
-        int    ArgumentCount;
-       char    Name[]; //!< Function Name
-};
-
 struct sAST_Node
 {
        tAST_Node       *NextSibling;
@@ -215,12 +190,10 @@ struct sAST_Variable
 
 // === FUNCTIONS ===
 extern tAST_Script     *AST_NewScript(void);
-extern size_t  AST_WriteScript(void *Buffer, tAST_Script *Script);
+extern size_t  AST_WriteScript(void *Buffer, tSpiderScript *Script);
 extern size_t  AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node);
 
-extern tAST_Function   *AST_AppendFunction(tAST_Script *Script, const char *Name, int ReturnType);
-extern void    AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Arg);
-extern void    AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root);
+extern int     AST_AppendFunction(tSpiderScript *Script, const char *Name, int ReturnType, tAST_Node *FirstArg, tAST_Node *Code);
 
 extern tAST_Node       *AST_NewNop(tParser *Parser);
 
index 7afd0c0..3bad158 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
+#include "common.h"
 #include "ast.h"
 #include "bytecode_gen.h"
 #include "bytecode_ops.h"
@@ -46,33 +47,26 @@ void        AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
 /**
  * \brief Convert a function into bytecode
  */
-tBC_Function *Bytecode_ConvertFunction(tAST_Function *ASTFcn)
+tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn)
 {
        tBC_Function    *ret;
        tAST_BlockInfo bi = {0};
-       
-       {
-               tAST_Node *arg;
-                int    i;
-               char    *arg_names[ASTFcn->ArgumentCount];
-                int    arg_types[ASTFcn->ArgumentCount];
-               
-               for(arg = ASTFcn->Arguments, i = 0; arg; arg = arg->NextSibling, i ++)
-               {
-                       arg_names[i] = arg->DefVar.Name;
-                       arg_types[i] = arg->DefVar.DataType;
-               }
 
-               ret = Bytecode_CreateFunction(ASTFcn->Name, ASTFcn->ArgumentCount, arg_names, arg_types);
-               if(!ret)        return NULL;
-       }
+       // TODO: Return BCFcn instead?
+       if(Fcn->BCFcn)  return NULL;
+       
+       ret = Bytecode_CreateFunction(Fcn);
+       if(!ret)        return NULL;
        
        bi.Handle = ret;
-       if( AST_ConvertNode(&bi, ASTFcn->Code) )
+       if( AST_ConvertNode(&bi, Fcn->ASTFcn) )
        {
                Bytecode_DeleteFunction(ret);
                return NULL;
        }
+
+       Fcn->BCFcn = ret;
+
        return ret;
 }
 
index 045f896..e00e240 100644 (file)
@@ -28,8 +28,6 @@ struct sBC_Op
 
 struct sBC_Function
 {
-       const char      *Name;
-       
         int    LabelCount;
         int    LabelSpace;
        tBC_Op  **Labels;
@@ -38,18 +36,12 @@ struct sBC_Function
        // NOTE: These fields are invalid after compilation
         int    VariableCount;
         int    VariableSpace;
-       const char      **VariableNames;        // Only type needs to be stored
+       const char      **VariableNames;
         int    CurContextDepth;        // Used to get the real var count
 
         int    OperationCount;
        tBC_Op  *Operations;
        tBC_Op  *OperationsEnd;
-
-        int    ArgumentCount;
-       struct {
-               char    *Name;
-                int    Type;
-       }       Arguments[];
 };
 
 #endif
index 078f2df..c718265 100644 (file)
@@ -38,15 +38,14 @@ tBC_Op *Bytecode_int_AllocateOp(int Operation)
        return ret;
 }
 
-tBC_Function *Bytecode_CreateFunction(const char *Name, int ArgCount, char **ArgNames, int *ArgTypes)
+tBC_Function *Bytecode_CreateFunction(tScript_Function *Fcn)
 {
        tBC_Function *ret;
         int    i;
 
-       ret = malloc(sizeof(tBC_Function) + ArgCount*sizeof(ret->Arguments[0]));
+       ret = malloc(sizeof(tBC_Function));
        if(!ret)        return NULL;
        
-       ret->Name = Name;
        ret->LabelSpace = ret->LabelCount = 0;
        ret->Labels = NULL;
 
@@ -59,12 +58,9 @@ tBC_Function *Bytecode_CreateFunction(const char *Name, int ArgCount, char **Arg
        ret->Operations = NULL;
        ret->OperationsEnd = (void*)&ret->Operations;
 
-       ret->ArgumentCount = ArgCount;
-       for( i = 0; i < ArgCount; i ++ )
+       for( i = 0; i < Fcn->ArgumentCount; i ++ )
        {
-               ret->Arguments[i].Name = strdup(ArgNames[i]);
-               ret->Arguments[i].Type = ArgTypes[i];
-               Bytecode_int_AddVariable(ret, ret->Arguments[i].Name);
+               Bytecode_int_AddVariable(ret, Fcn->Arguments[i].Name);
        }
 
        return ret;
@@ -73,11 +69,6 @@ tBC_Function *Bytecode_CreateFunction(const char *Name, int ArgCount, char **Arg
 void Bytecode_DeleteFunction(tBC_Function *Fcn)
 {
        tBC_Op  *op;
-        int    i;
-       for( i = 0; i < Fcn->ArgumentCount; i ++ )
-       {
-               free(Fcn->Arguments[i].Name);
-       }
        for( op = Fcn->Operations; op; )
        {
                tBC_Op  *nextop = op->Next;
index 19d240c..9ec6eb5 100644 (file)
@@ -8,12 +8,12 @@
 #ifndef _BYTECODE_GEN_H_
 #define _BYTECODE_GEN_H_
 
+#include "common.h"
 #include "ast.h"
 #include "bytecode.h"
 
 typedef struct sStringList     tStringList;
 typedef struct sString tString;
-//typedef struct sAST_Function tAST_Function;
 
 struct sString
 {
@@ -32,13 +32,13 @@ struct sStringList
 
 
 extern int     Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile);
-extern tBC_Function    *Bytecode_ConvertFunction(tAST_Function *ASTFcn);
+extern tBC_Function    *Bytecode_ConvertFunction(tScript_Function *Fcn);
 extern tBC_Function    *Bytecode_NewBlankFunction(void);
 extern void    Bytecode_DeleteFunction(tBC_Function *Fcn);
 
 extern char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStringList *Strings);
 extern int     StringList_GetString(tStringList *List, const char *String, int Length);
-extern tBC_Function    *Bytecode_CreateFunction(const char *Name, int ArgCount, char **ArgNames, int *ArgTypes);
+extern tBC_Function    *Bytecode_CreateFunction(tScript_Function *Fcn);
 
 extern int     Bytecode_AllocateLabel(tBC_Function *Handle);
 extern void    Bytecode_SetLabel(tBC_Function *Handle, int Label);
index 033f8d7..e2b5547 100644 (file)
 int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile)
 {
        tStringList     strings = {0};
-       tAST_Function   *fcn;
+       tScript_Function        *fcn;
        FILE    *fp;
         int    fcn_hdr_offset = 0;
         int    fcn_count = 0;
         int    strtab_ofs;
+        int    i;
 
        void _put8(uint8_t val)
        {
@@ -52,12 +53,11 @@ int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile)
        fcn_hdr_offset = ftell(fp);
 
        // Create function descriptors
-       for(fcn = Script->Script->Functions; fcn; fcn = fcn->Next, fcn_count ++)
+       for(fcn = Script->Functions; fcn; fcn = fcn->Next, fcn_count ++)
        {
-               tAST_Node *arg;
-
                _put32( StringList_GetString(&strings, fcn->Name, strlen(fcn->Name)) );
                _put32( 0 );    // Code offset
+               // TODO: 
                _put8( fcn->ReturnType );
                
                if(fcn->ArgumentCount > 255) {
@@ -67,19 +67,18 @@ int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile)
                _put8( fcn->ArgumentCount );
 
                // Argument types?
-               for(arg = fcn->Arguments; arg; arg = arg->NextSibling)
+               for( i = 0; i < fcn->ArgumentCount; i ++ )
                {
-                       _put32( StringList_GetString(&strings, arg->DefVar.Name, strlen(arg->DefVar.Name)) );
-                       _put8( arg->DefVar.DataType );
+                       _put32( StringList_GetString(&strings, fcn->Arguments[i].Name, strlen(fcn->Arguments[i].Name)) );
+                       _put8( fcn->Arguments[i].Type );
                }
        }
 
        // Put function code in
-       for(fcn = Script->Script->Functions; fcn; fcn = fcn->Next)
+       for(fcn = Script->Functions; fcn; fcn = fcn->Next)
        {
                char    *code;
                 int    len, code_pos;
-               tBC_Function    *bc_fcn;
        
                // Fix header   
                code_pos = ftell(fp);
@@ -90,9 +89,8 @@ int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile)
                fcn_hdr_offset += 4+4+1+1+(4+1)*fcn->ArgumentCount;
                
                // Write code
-               bc_fcn = Bytecode_ConvertFunction(fcn);
-               code = Bytecode_SerialiseFunction(bc_fcn, &len, &strings);
-               Bytecode_DeleteFunction(bc_fcn);
+               if( !fcn->BCFcn )       Bytecode_ConvertFunction(fcn);
+               code = Bytecode_SerialiseFunction(fcn->BCFcn, &len, &strings);
                fwrite(code, len, 1, fp);
                free(code);
        }
diff --git a/Usermode/Libraries/libspiderscript.so_src/common.h b/Usermode/Libraries/libspiderscript.so_src/common.h
new file mode 100644 (file)
index 0000000..f2bb3e6
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SpiderScript
+ * - By John Hodge (thePowersGang)
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <spiderscript.h>
+
+typedef struct sScript_Function        tScript_Function;
+typedef struct sScript_Arg     tScript_Arg;
+
+struct sSpiderScript
+{
+       tSpiderVariant  *Variant;
+       tScript_Function        *Functions;
+       tScript_Function        *LastFunction;
+       char    *CurNamespace;  //!< Current namespace prefix (NULL = Root) - No trailing .
+};
+
+struct sScript_Arg
+{
+        int    Type;
+       char    *Name;
+};
+
+struct sScript_Function
+{
+       tScript_Function        *Next;
+       // char *Namespace;
+       char    *Name;
+
+        int    ReturnType;
+       
+       struct sAST_Node        *ASTFcn;
+       struct sBC_Function     *BCFcn;
+
+        int    ArgumentCount;
+       tScript_Arg     Arguments[];
+};
+
+#endif
+
index be2c1c5..d4c7995 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
+#include "common.h"
 #include "ast.h"
 
 #define TRACE_VAR_LOOKUPS      0
@@ -33,6 +34,48 @@ void AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
  int   giNextBlockIdent = 1;
 
 // === CODE ===
+tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments)
+{
+       tAST_BlockState bs;
+       tSpiderValue    *ret;
+        int    i = 0;
+       
+       // Build a block State
+       bs.FirstVar = NULL;
+       bs.RetVal = NULL;
+       bs.Parent = NULL;
+       bs.BaseNamespace = &Script->Variant->RootNamespace;
+       bs.CurNamespace = NULL;
+       bs.Script = Script;
+       bs.Ident = giNextBlockIdent ++;
+       
+       // Parse arguments
+       for( i = 0; i < Fcn->ArgumentCount; i ++ )
+       {
+               if( i >= NArguments )   break;  // TODO: Return gracefully
+               // TODO: Type checks
+               Variable_Define(&bs,
+                       Fcn->Arguments[i].Type, Fcn->Arguments[i].Name,
+                       Arguments[i]);
+       }
+                       
+       // Execute function
+       ret = AST_ExecuteNode(&bs, Fcn->ASTFcn);
+       if(ret != ERRPTR)
+       {
+               SpiderScript_DereferenceValue(ret);     // Dereference output of last block statement
+               ret = bs.RetVal;        // Set to return value of block
+       }
+                       
+       while(bs.FirstVar)
+       {
+               tAST_Variable   *nextVar = bs.FirstVar->Next;
+               Variable_Destroy( bs.FirstVar );
+               bs.FirstVar = nextVar;
+       }
+       return ret;
+}
+
 /**
  * \brief Execute a script function
  * \param Script       Script context to execute in
@@ -47,63 +90,27 @@ tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script,
 {
         int    bFound = 0;     // Used to keep nesting levels down
        tSpiderValue    *ret = ERRPTR;
-       tSpiderFunction *fcn;
        
        // First: Find the function in the script
        {
-               tAST_Function   *astFcn;
-               for( astFcn = Script->Script->Functions; astFcn; astFcn = astFcn->Next )
+               tScript_Function        *fcn;
+               for( fcn = Script->Functions; fcn; fcn = fcn->Next )
                {
-                       if( strcmp(astFcn->Name, Function) == 0 )
+                       if( strcmp(fcn->Name, Function) == 0 )
                                break;
                }
                // Execute!
-               if(astFcn)
+               if(fcn)
                {
-                       tAST_BlockState bs;
-                       tAST_Node       *arg;
-                        int    i = 0;
-                       
-                       // Build a block State
-                       bs.FirstVar = NULL;
-                       bs.RetVal = NULL;
-                       bs.Parent = NULL;
-                       bs.BaseNamespace = &Script->Variant->RootNamespace;
-                       bs.CurNamespace = NULL;
-                       bs.Script = Script;
-                       bs.Ident = giNextBlockIdent ++;
-                       
-                       // Parse arguments
-                       for( arg = astFcn->Arguments; arg; arg = arg->NextSibling, i++ )
-                       {
-                               if( i >= NArguments )   break;  // TODO: Return gracefully
-                               // TODO: Type checks
-                               Variable_Define(&bs,
-                                       arg->DefVar.DataType, arg->DefVar.Name,
-                                       Arguments[i]);
-                       }
-                       
-                       // Execute function
-                       ret = AST_ExecuteNode(&bs, astFcn->Code);
-                       if(ret != ERRPTR)
-                       {
-                               SpiderScript_DereferenceValue(ret);     // Dereference output of last block statement
-                               ret = bs.RetVal;        // Set to return value of block
-                       }
+                       ret = AST_ExecuteFunction(Script, fcn, NArguments, Arguments);
                        bFound = 1;
-                       
-                       while(bs.FirstVar)
-                       {
-                               tAST_Variable   *nextVar = bs.FirstVar->Next;
-                               Variable_Destroy( bs.FirstVar );
-                               bs.FirstVar = nextVar;
-                       }
                }
        }
        
        // Didn't find it in script?
        if(!bFound)
        {
+               tSpiderFunction *fcn;
                fcn = NULL;     // Just to allow the below code to be neat
                
                // Second: Scan current namespace
index a88670c..e240116 100644 (file)
@@ -2,12 +2,12 @@
  * SpiderScript Library
  * by John Hodge (thePowersGang)
  * 
- * bytecode_makefile.c
- * - Generate a bytecode file
+ * exec_bytecode.c
+ * - Execute bytecode
  */
 #include <stdlib.h>
 #include <stdint.h>
-#include <spiderscript.h>
+#include "common.h"
 #include "bytecode.h"
 #include <string.h>
 #include "ast.h"
@@ -41,6 +41,10 @@ struct sBC_Stack
        tBC_StackEnt    Entries[];
 };
 
+// === PROTOTYPES ===
+tSpiderValue   *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args);
+ int   Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount);
+
 // === CODE ===
 int Bytecode_int_StackPop(tBC_Stack *Stack, tBC_StackEnt *Dest)
 {
@@ -128,12 +132,48 @@ void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value)
 #define OP_INDX(op_ptr)        ((op_ptr)->Content.StringInt.Integer)
 #define OP_STRING(op_ptr)      ((op_ptr)->Content.StringInt.String)
 
-int Bytecode_ExecuteFunction(tSpiderScript *Script, tBC_Function *Fcn, tBC_Stack *Stack, int ArgCount)
+tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args)
+{
+       const int       stack_size = 100;
+       tSpiderValue    *ret, tmpsval;
+       tBC_Stack       *stack;
+       tBC_StackEnt    val;
+        int    i;
+       
+       stack = malloc(sizeof(tBC_Stack) + stack_size*sizeof(tBC_StackEnt));
+       stack->EntrySpace = stack_size;
+       stack->EntryCount = 0;
+
+       // Push arguments in order (so top is last arg)
+       for( i = 0; i < NArguments; i ++ )
+       {
+               Bytecode_int_SetSpiderValue(&val, Args[i]);
+               Bytecode_int_StackPush(stack, &val);
+       }
+
+       // Call
+       Bytecode_int_ExecuteFunction(Script, Fcn, stack, NArguments);
+
+       // Get return value
+       Bytecode_int_StackPop(stack, &val);
+       ret = Bytecode_int_GetSpiderValue(&val, &tmpsval);
+       // Ensure it's a heap value
+       if(ret == &tmpsval) {
+               ret = malloc(sizeof(tSpiderValue));
+               memcpy(ret, &tmpsval, sizeof(tSpiderValue));
+       }
+       return ret;
+}
+
+/**
+ * \brief Execute a bytecode function with a stack
+ */
+int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount)
 {
         int    ret, ast_op, i;
        tBC_Op  *op;
        tBC_StackEnt    val1, val2;
-       tBC_StackEnt    local_vars[Fcn->MaxVariableCount];      // Includes arguments
+       tBC_StackEnt    local_vars[Fcn->BCFcn->MaxVariableCount];       // Includes arguments
        tSpiderValue    tmpVal1, tmpVal2;       // temp storage
        tSpiderValue    *pval1, *pval2, *ret_val;
        
@@ -156,7 +196,7 @@ int Bytecode_ExecuteFunction(tSpiderScript *Script, tBC_Function *Fcn, tBC_Stack
        Bytecode_int_StackPush(Stack, &val1);
 
        // Execute!
-       op = Fcn->Operations;
+       op = Fcn->BCFcn->Operations;
        while(op)
        {
                tBC_Op  *nextop = op->Next;
@@ -165,17 +205,17 @@ int Bytecode_ExecuteFunction(tSpiderScript *Script, tBC_Function *Fcn, tBC_Stack
                {
                // Jumps
                case BC_OP_JUMP:
-                       nextop = Fcn->Labels[ OP_INDX(op) ];
+                       nextop = Fcn->BCFcn->Labels[ OP_INDX(op) ];
                        break;
                case BC_OP_JUMPIF:
                        GET_STACKVAL(val1);
                        if( Bytecode_int_IsStackEntTrue(&val1) )
-                               nextop = Fcn->Labels[op->Content.StringInt.Integer];
+                               nextop = Fcn->BCFcn->Labels[ OP_INDX(op) ];
                        break;
                case BC_OP_JUMPIFNOT:
                        GET_STACKVAL(val1);
                        if( !Bytecode_int_IsStackEntTrue(&val1) )
-                               nextop = Fcn->Labels[op->Content.StringInt.Integer];
+                               nextop = Fcn->BCFcn->Labels[ OP_INDX(op) ];
                        break;
                
                // Define variables
index f26a40c..d6cd722 100644 (file)
@@ -6,11 +6,12 @@
 #include <stdio.h>
 #include <string.h>
 #include <spiderscript.h>
+#include "common.h"
 #include "ast.h"
 #include "bytecode_gen.h"
 
 // === IMPORTS ===
-extern tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const char *Filename);
+extern  int    Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename);
 extern tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name);
 extern void    Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
 extern void    Variable_Destroy(tAST_Variable *Variable);
@@ -62,10 +63,11 @@ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filen
        // Create the script
        ret = malloc(sizeof(tSpiderScript));
        ret->Variant = Variant;
+       ret->Functions = NULL;
+       ret->LastFunction = NULL;
        
        ret->CurNamespace = NULL;
-       ret->Script = Parse_Buffer(Variant, data, Filename);
-       if( ret->Script == NULL ) {
+       if( Parse_Buffer(ret, data, Filename) ) {
                free(data);
                free(ret);
                return NULL;
@@ -79,14 +81,14 @@ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filen
                size_t  size;
                
                printf("Total Size: "); fflush(stdout);
-               size = AST_WriteScript(NULL, ret->Script);
+               size = AST_WriteScript(NULL, ret);
                printf("0x%x bytes\n", (unsigned)size);
                
                fp = fopen(cacheFilename, "wb");
                if(!fp) return ret;
                
                data = malloc(size);
-               size = AST_WriteScript(data, ret->Script);
+               size = AST_WriteScript(data, ret);
                fwrite(data, size, 1, fp);
                free(data);
                fclose(fp);
@@ -105,31 +107,19 @@ int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile)
  */
 void SpiderScript_Free(tSpiderScript *Script)
 {
-       tAST_Function   *fcn = Script->Script->Functions;
-       tAST_Function   *nextFcn;
-       tAST_Node       *var, *nextVar;
+       tScript_Function        *fcn = Script->Functions;
+       tScript_Function        *nextFcn;
        
        // Free functions
        while(fcn)
        {
-               
-               AST_FreeNode( fcn->Code );
-               
-               var = fcn->Arguments;
-               while(var)
-               {
-                       nextVar = var->NextSibling;
-                       AST_FreeNode( var );
-                       var = nextVar;
-               }
-               
+               if(fcn->ASTFcn) AST_FreeNode( fcn->ASTFcn );
+               if(fcn->BCFcn)  Bytecode_DeleteFunction( fcn->BCFcn );
+
                nextFcn = fcn->Next;
                free( fcn );
                fcn = nextFcn;
        }
        
-       // TODO: Pass this off to AST for a proper cleanup
-       free(Script->Script);
-       
        free(Script);
 }
index 503379d..e6d9694 100644 (file)
 #define WANT_TOKEN_STRINGS     1
 #include "tokens.h"
 #include "ast.h"
+#include "common.h"
 
 #define DEBUG  0
 #define        SUPPORT_BREAK_TAGS      1
 
 // === PROTOTYPES ===
-tAST_Script    *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const char *Filename);
-void   *Parse_FunctionDefinition(tAST_Script *Script, tSpiderVariant *Variant, tParser *Parser, int Type);
+ int   Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename);
+void   *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type);
 tAST_Node      *Parse_DoCodeBlock(tParser *Parser);
 tAST_Node      *Parse_DoBlockLine(tParser *Parser);
 tAST_Node      *Parse_GetVarDef(tParser *Parser, int Type);
@@ -60,14 +61,13 @@ void        SyntaxError(tParser *Parser, int bFatal, const char *Message, ...);
 /**
  * \brief Parse a buffer into a syntax tree
  */
-tAST_Script    *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const char *Filename)
+int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename)
 {
        tParser parser = {0};
        tParser *Parser = &parser;      //< Keeps code consistent
-       tAST_Script     *ret;
        tAST_Node       *mainCode, *node;
         int    type;
-       tAST_Function   *fcn;
+       tScript_Function        *fcn;
        
        #if DEBUG >= 2
        printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
@@ -86,7 +86,6 @@ tAST_Script   *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const cha
        parser.Filename += sizeof(int); // Move filename
        parser.ErrorHit = 0;
        
-       ret = AST_NewScript();
        mainCode = AST_NewCodeBlock(&parser);
        
        // Give us an error fallback
@@ -94,24 +93,17 @@ tAST_Script *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const cha
        {
                AST_FreeNode( mainCode );
                
-               for(fcn = ret->Functions; fcn; )
+               for(fcn = Script->Functions; fcn; )
                {
-                       tAST_Node       *var;
-                       tAST_Function   *nextFcn;
-                       AST_FreeNode( fcn->Code );
-                       for(var = fcn->Arguments; var;)
-                       {
-                               tAST_Node       *nextVar = var->NextSibling;
-                               AST_FreeNode( var );
-                               var = nextVar;
-                       }
+                       tScript_Function        *nextFcn;
+                       
+                       AST_FreeNode( fcn->ASTFcn );
                        
                        nextFcn = fcn->Next;
                        free( fcn );
                        fcn = nextFcn;
                }
-               free(ret);
-               return NULL;
+               return -1;
        }
        
        // Parse the file!
@@ -131,7 +123,7 @@ tAST_Script *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const cha
                        // Define a function (pass on to the other function definition code)
                        case TOK_IDENT:
                                PutBack(Parser);
-                               if( Parse_FunctionDefinition(ret, Variant, Parser, type) == NULL )
+                               if( Parse_FunctionDefinition(Script, Parser, type) == NULL )
                                        longjmp(Parser->JmpTarget, -1);
                                break ;
                        // Define a variable
@@ -156,14 +148,14 @@ tAST_Script       *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const cha
                
                // Define a function
                case TOK_RWD_FUNCTION:
-                       if( !Variant->bDyamicTyped ) {
+                       if( !Script->Variant->bDyamicTyped ) {
                                SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode");
                                longjmp(Parser->JmpTarget, -1);
                        }
                        
                        type = SS_DATATYPE_DYNAMIC;
                
-                       if( Parse_FunctionDefinition(ret, Variant, Parser, SS_DATATYPE_DYNAMIC) == NULL )
+                       if( Parse_FunctionDefinition(Script, Parser, SS_DATATYPE_DYNAMIC) == NULL )
                                longjmp(Parser->JmpTarget, -1);
                
                        break;
@@ -182,51 +174,66 @@ tAST_Script       *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const cha
                        longjmp(Parser->JmpTarget, -1);
        }
        
-       fcn = AST_AppendFunction( ret, "", SS_DATATYPE_INTEGER );
-       AST_SetFunctionCode( fcn, mainCode );
+       AST_AppendFunction( Script, "", SS_DATATYPE_INTEGER, NULL, mainCode );
        
        //printf("---- %p parsed as SpiderScript ----\n", Buffer);
        
-       return ret;
+       return 0;
 }
 
-void *Parse_FunctionDefinition(tAST_Script *Script, tSpiderVariant *Variant, tParser *Parser, int Type)
+void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type)
 {
-       tAST_Function   *fcn;
        char    *name;
-        int    type;
+        int    rv;
+       tAST_Node       *first_arg, *last_arg, *code;
+       
+       last_arg = (void*)&first_arg;   // HACK
        
        SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
        
        name = strndup( Parser->TokenStr, Parser->TokenLen );
-       fcn = AST_AppendFunction( Script, name, Type );
        #if DEBUG
        printf("DefFCN %s\n", name);
        #endif
-       free(name);
        
        // Get arguments
        SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
        if( LookAhead(Parser) != TOK_PAREN_CLOSE )
        {
                do {
-                       type = SS_DATATYPE_DYNAMIC;
+                        int    type = SS_DATATYPE_DYNAMIC;
                        GetToken(Parser);
                        // Non dynamic typed variants must use data types
-                       if( !Variant->bDyamicTyped ) {
+                       if( !Script->Variant->bDyamicTyped ) {
                                TOKEN_GET_DATATYPE(type, Parser->Token);
                                GetToken(Parser);
                        }
-                       AST_AppendFunctionArg(fcn, Parse_GetVarDef(Parser, type)); 
+                       last_arg->NextSibling = Parse_GetVarDef(Parser, type);
+                       last_arg = last_arg->NextSibling;
+                       last_arg->NextSibling = NULL;
                }       while(GetToken(Parser) == TOK_COMMA);
        }
        else
                GetToken(Parser);
        SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
+
+       code = Parse_DoCodeBlock(Parser);
+
+       rv = AST_AppendFunction( Script, name, Type, first_arg, code );
+
+       // Clean up argument definition nodes
+       {
+               tAST_Node       *nextarg;
+               for( ; first_arg; first_arg = nextarg )
+               {
+                       nextarg = first_arg->NextSibling;
+                       AST_FreeNode(first_arg);
+               }
+       }
+
+       free(name);
        
-       AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
-       
-       return fcn;
+       return rv == 0 ? (void*)1 : NULL;
 }
 
 /**

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