From 239f2374299c1471a40b1087725b32f3f163d9b3 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 18 Sep 2011 12:48:28 +0800 Subject: [PATCH] SpiderScript - Restructured to be able to keep bytecode and AST in memory at one time - Also removed the linked list of argument nodes in function def --- .../Libraries/libspiderscript.so_src/ast.c | 105 +++++++++--------- .../Libraries/libspiderscript.so_src/ast.h | 31 +----- .../libspiderscript.so_src/ast_to_bytecode.c | 28 ++--- .../libspiderscript.so_src/bytecode.h | 10 +- .../libspiderscript.so_src/bytecode_gen.c | 17 +-- .../libspiderscript.so_src/bytecode_gen.h | 6 +- .../bytecode_makefile.c | 22 ++-- .../Libraries/libspiderscript.so_src/common.h | 43 +++++++ .../libspiderscript.so_src/exec_ast.c | 91 ++++++++------- .../libspiderscript.so_src/exec_bytecode.c | 58 ++++++++-- .../Libraries/libspiderscript.so_src/main.c | 34 ++---- .../Libraries/libspiderscript.so_src/parse.c | 77 +++++++------ 12 files changed, 279 insertions(+), 243 deletions(-) create mode 100644 Usermode/Libraries/libspiderscript.so_src/common.h diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.c b/Usermode/Libraries/libspiderscript.so_src/ast.c index bafdd12c..78a54bed 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast.c @@ -5,68 +5,61 @@ #include #include #include +#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; diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.h b/Usermode/Libraries/libspiderscript.so_src/ast.h index 39c23b1f..39ea2947 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ b/Usermode/Libraries/libspiderscript.so_src/ast.h @@ -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); diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c index 7afd0c03..3bad1588 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c @@ -7,6 +7,7 @@ #include #include #include +#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; } diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode.h b/Usermode/Libraries/libspiderscript.so_src/bytecode.h index 045f896f..e00e2401 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode.h +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode.h @@ -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 diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c index 078f2df1..c718265e 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c @@ -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; diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h index 19d240c8..9ec6eb51 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h @@ -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); diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c index 033f8d72..e2b55475 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c @@ -21,11 +21,12 @@ 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 index 00000000..f2bb3e63 --- /dev/null +++ b/Usermode/Libraries/libspiderscript.so_src/common.h @@ -0,0 +1,43 @@ +/* + * SpiderScript + * - By John Hodge (thePowersGang) + */ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include + +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 + diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c index be2c1c50..d4c7995f 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c @@ -7,6 +7,7 @@ #include #include #include +#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 diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c index a88670ca..e2401160 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -2,12 +2,12 @@ * SpiderScript Library * by John Hodge (thePowersGang) * - * bytecode_makefile.c - * - Generate a bytecode file + * exec_bytecode.c + * - Execute bytecode */ #include #include -#include +#include "common.h" #include "bytecode.h" #include #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 diff --git a/Usermode/Libraries/libspiderscript.so_src/main.c b/Usermode/Libraries/libspiderscript.so_src/main.c index f26a40cd..d6cd722e 100644 --- a/Usermode/Libraries/libspiderscript.so_src/main.c +++ b/Usermode/Libraries/libspiderscript.so_src/main.c @@ -6,11 +6,12 @@ #include #include #include +#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); } diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c index 503379d8..e6d96942 100644 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ b/Usermode/Libraries/libspiderscript.so_src/parse.c @@ -10,13 +10,14 @@ #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; } /** -- 2.20.1