From: John Hodge Date: Sun, 18 Sep 2011 07:52:54 +0000 (+0800) Subject: SpiderScript - Cleaning and sorting X-Git-Tag: rel0.11~90 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=71b1271511ad01f042d2e51673dd57cce1b0fd9c;p=tpg%2Facess2.git SpiderScript - Cleaning and sorting - Broken now, because bytecode doesn't execute > Changed to compile on load, and perfer the bytecode version --- diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c index 3bad1588..ab294705 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c @@ -44,6 +44,17 @@ void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); // int giNextBlockIdent = 1; // === CODE === +int SpiderScript_BytecodeScript(tSpiderScript *Script) +{ + tScript_Function *fcn; + for(fcn = Script->Functions; fcn; fcn = fcn->Next) + { + if( Bytecode_ConvertFunction(fcn) == 0 ) + return -1; + } + return 0; +} + /** * \brief Convert a function into bytecode */ @@ -53,7 +64,7 @@ tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn) tAST_BlockInfo bi = {0}; // TODO: Return BCFcn instead? - if(Fcn->BCFcn) return NULL; + if(Fcn->BCFcn) return Fcn->BCFcn; ret = Bytecode_CreateFunction(Fcn); if(!ret) return NULL; diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c index e2b55475..5affbef0 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c @@ -18,7 +18,7 @@ // === GLOBALS === // === CODE === -int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile) +int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile) { tStringList strings = {0}; tScript_Function *fcn; @@ -57,7 +57,7 @@ int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile) { _put32( StringList_GetString(&strings, fcn->Name, strlen(fcn->Name)) ); _put32( 0 ); // Code offset - // TODO: + // TODO: Namespace _put8( fcn->ReturnType ); if(fcn->ArgumentCount > 255) { diff --git a/Usermode/Libraries/libspiderscript.so_src/exec.c b/Usermode/Libraries/libspiderscript.so_src/exec.c new file mode 100644 index 00000000..b073cbf0 --- /dev/null +++ b/Usermode/Libraries/libspiderscript.so_src/exec.c @@ -0,0 +1,342 @@ +/* +* SpiderScript Library +* by John Hodge (thePowersGang) +* +* bytecode_makefile.c +* - Generate a bytecode file +*/ +#include +#include "common.h" +#include "ast.h" +#include +#include +#include + +// === IMPORTS === +extern tSpiderFunction *gpExports_First; +extern tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments); +extern tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args); + +// === PROTOTYPES === +void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); +void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); + +// === CODE === +/** + * \brief Execute a script function + * \param Script Script context to execute in + * \param Namespace Namespace to search for the function + * \param Function Function name to execute + * \param NArguments Number of arguments to pass + * \param Arguments Arguments passed + */ +tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, + tSpiderNamespace *Namespace, const char *Function, + int NArguments, tSpiderValue **Arguments) +{ + int bFound = 0; // Used to keep nesting levels down + tSpiderValue *ret = ERRPTR; + + // First: Find the function in the script + { + tScript_Function *fcn; + for( fcn = Script->Functions; fcn; fcn = fcn->Next ) + { + if( strcmp(fcn->Name, Function) == 0 ) + break; + } + // Execute! + if(fcn) + { + if( fcn->BCFcn ) + ret = Bytecode_ExecuteFunction(Script, fcn, NArguments, Arguments); + else + ret = AST_ExecuteFunction(Script, fcn, NArguments, Arguments); + bFound = 1; + } + } + + // 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 + if( !fcn && Namespace ) + { + for( fcn = Namespace->Functions; fcn; fcn = fcn->Next ) + { + if( strcmp( fcn->Name, Function ) == 0 ) + break; + } + } + + // Third: Search the variant's global exports + if( !fcn ) + { + for( fcn = Script->Variant->Functions; fcn; fcn = fcn->Next ) + { + if( strcmp( fcn->Name, Function ) == 0 ) + break; + } + } + + // Fourth: Search language exports + if( !fcn ) + { + for( fcn = gpExports_First; fcn; fcn = fcn->Next ) + { + if( strcmp( fcn->Name, Function ) == 0 ) + break; + } + } + + // Execute! + if(fcn) + { + // TODO: Type Checking + ret = fcn->Handler( Script, NArguments, Arguments ); + bFound = 1; + } + } + + // Not found? + if(!bFound) + { + fprintf(stderr, "Undefined reference to function '%s' (ns='%s')\n", + Function, Namespace->Name); + return ERRPTR; + } + + return ret; +} + +/** + * \brief Execute an object method function + * \param Script Script context to execute in + * \param Object Object in which to find the method + * \param MethodName Name of method to call + * \param NArguments Number of arguments to pass + * \param Arguments Arguments passed + */ +tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, + tSpiderObject *Object, const char *MethodName, + int NArguments, tSpiderValue **Arguments) +{ + tSpiderFunction *fcn; + tSpiderValue this; + tSpiderValue *newargs[NArguments+1]; + int i; + + // TODO: Support program defined objects + + // Search for the function + for( fcn = Object->Type->Methods; fcn; fcn = fcn->Next ) + { + if( strcmp(fcn->Name, MethodName) == 0 ) + break; + } + // Error + if( !fcn ) + { + AST_RuntimeError(NULL, "Class '%s' does not have a method '%s'", + Object->Type->Name, MethodName); + return ERRPTR; + } + + // Create the "this" argument + this.Type = SS_DATATYPE_OBJECT; + this.ReferenceCount = 1; + this.Object = Object; + newargs[0] = &this; + memcpy(&newargs[1], Arguments, NArguments*sizeof(tSpiderValue*)); + + // Check the type of the arguments + for( i = 0; fcn->ArgTypes[i]; i ++ ) + { + if( i >= NArguments ) { + for( ; fcn->ArgTypes[i]; i ++ ) ; + AST_RuntimeError(NULL, "Argument count mismatch (%i passed, %i expected)", + NArguments, i); + return ERRPTR; + } + if( Arguments[i] && Arguments[i]->Type != fcn->ArgTypes[i] ) + { + AST_RuntimeError(NULL, "Argument type mismatch (%i, expected %i)", + Arguments[i]->Type, fcn->ArgTypes[i]); + return ERRPTR; + } + } + + // Call handler + return fcn->Handler(Script, NArguments+1, newargs); +} + +/** + * \brief Execute a script function + * \param Script Script context to execute in + * \param Function Function name to execute + * \param NArguments Number of arguments to pass + * \param Arguments Arguments passed + */ +tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, + tSpiderNamespace *Namespace, const char *ClassName, + int NArguments, tSpiderValue **Arguments) +{ + int bFound = 0; // Used to keep nesting levels down + tSpiderValue *ret = ERRPTR; + tSpiderObjectDef *class; + + // First: Find the function in the script + // TODO: Implement script-defined classes + #if 0 + { + tAST_Function *astClass; + for( astClass = Script->Script->Classes; astClass; astClass = astClass->Next ) + { + if( strcmp(astClass->Name, ClassName) == 0 ) + break; + } + // Execute! + if(astClass) + { + 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 ++; + + 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 + } + bFound = 1; + + while(bs.FirstVar) + { + tAST_Variable *nextVar = bs.FirstVar->Next; + Variable_Destroy( bs.FirstVar ); + bs.FirstVar = nextVar; + } + } + } + #endif + + // Didn't find it in script? + if(!bFound) + { + class = NULL; // Just to allow the below code to be neat + + //if( !Namespace ) + // Namespace = &Script->Variant->RootNamespace; + + // Second: Scan current namespace + if( !class && Namespace ) + { + for( class = Namespace->Classes; class; class = class->Next ) + { + if( strcmp( class->Name, ClassName ) == 0 ) + break; + } + } + + #if 0 + // Third: Search the variant's global exports + if( !class ) + { + for( class = Script->Variant->Classes; class; class = fcn->Next ) + { + if( strcmp( class->Name, Function ) == 0 ) + break; + } + } + #endif + + #if 0 + // Fourth: Search language exports + if( !class ) + { + for( class = gpExports_First; class; class = fcn->Next ) + { + if( strcmp( class->Name, ClassName ) == 0 ) + break; + } + } + #endif + + // Execute! + if(class) + { + tSpiderObject *obj; + // TODO: Type Checking + + // Call constructor + obj = class->Constructor( NArguments, Arguments ); + if( obj == NULL || obj == ERRPTR ) + return (void *)obj; + + // Creatue return object + ret = malloc( sizeof(tSpiderValue) ); + ret->Type = SS_DATATYPE_OBJECT; + ret->ReferenceCount = 1; + ret->Object = obj; + bFound = 1; + } + } + + // Not found? + if(!bFound) + { + fprintf(stderr, "Undefined reference to class '%s'\n", ClassName); + return ERRPTR; + } + + return ret; +} + +void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) +{ + va_list args; + + if(Node) { + fprintf(stderr, "%s:%i: ", Node->File, Node->Line); + } + fprintf(stderr, "%s: ", Type); + va_start(args, Format); + vfprintf(stderr, Format, args); + va_end(args); + fprintf(stderr, "\n"); +} +void AST_RuntimeError(tAST_Node *Node, const char *Format, ...) +{ + va_list args; + + if(Node) { + fprintf(stderr, "%s:%i: ", Node->File, Node->Line); + } + fprintf(stderr, "error: "); + va_start(args, Format); + vfprintf(stderr, Format, args); + va_end(args); + fprintf(stderr, "\n"); +} diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c index d4c7995f..3d3c76dd 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c @@ -14,7 +14,6 @@ #define TRACE_NODE_RETURNS 0 // === IMPORTS === -extern tSpiderFunction *gpExports_First; // === PROTOTYPES === // - Node Execution @@ -76,296 +75,6 @@ tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, return ret; } -/** - * \brief Execute a script function - * \param Script Script context to execute in - * \param Namespace Namespace to search for the function - * \param Function Function name to execute - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *Function, - int NArguments, tSpiderValue **Arguments) -{ - int bFound = 0; // Used to keep nesting levels down - tSpiderValue *ret = ERRPTR; - - // First: Find the function in the script - { - tScript_Function *fcn; - for( fcn = Script->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp(fcn->Name, Function) == 0 ) - break; - } - // Execute! - if(fcn) - { - ret = AST_ExecuteFunction(Script, fcn, NArguments, Arguments); - bFound = 1; - } - } - - // 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 - if( !fcn && Namespace ) - { - for( fcn = Namespace->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Third: Search the variant's global exports - if( !fcn ) - { - for( fcn = Script->Variant->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Fourth: Search language exports - if( !fcn ) - { - for( fcn = gpExports_First; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Execute! - if(fcn) - { - // TODO: Type Checking - ret = fcn->Handler( Script, NArguments, Arguments ); - bFound = 1; - } - } - - // Not found? - if(!bFound) - { - fprintf(stderr, "Undefined reference to function '%s' (ns='%s')\n", - Function, Namespace->Name); - return ERRPTR; - } - - return ret; -} - -/** - * \brief Execute an object method function - * \param Script Script context to execute in - * \param Object Object in which to find the method - * \param MethodName Name of method to call - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, - tSpiderObject *Object, const char *MethodName, - int NArguments, tSpiderValue **Arguments) -{ - tSpiderFunction *fcn; - tSpiderValue this; - tSpiderValue *newargs[NArguments+1]; - int i; - - // TODO: Support program defined objects - - // Search for the function - for( fcn = Object->Type->Methods; fcn; fcn = fcn->Next ) - { - if( strcmp(fcn->Name, MethodName) == 0 ) - break; - } - // Error - if( !fcn ) - { - AST_RuntimeError(NULL, "Class '%s' does not have a method '%s'", - Object->Type->Name, MethodName); - return ERRPTR; - } - - // Create the "this" argument - this.Type = SS_DATATYPE_OBJECT; - this.ReferenceCount = 1; - this.Object = Object; - newargs[0] = &this; - memcpy(&newargs[1], Arguments, NArguments*sizeof(tSpiderValue*)); - - // Check the type of the arguments - for( i = 0; fcn->ArgTypes[i]; i ++ ) - { - if( i >= NArguments ) { - for( ; fcn->ArgTypes[i]; i ++ ) ; - AST_RuntimeError(NULL, "Argument count mismatch (%i passed, %i expected)", - NArguments, i); - return ERRPTR; - } - if( Arguments[i] && Arguments[i]->Type != fcn->ArgTypes[i] ) - { - AST_RuntimeError(NULL, "Argument type mismatch (%i, expected %i)", - Arguments[i]->Type, fcn->ArgTypes[i]); - return ERRPTR; - } - } - - // Call handler - return fcn->Handler(Script, NArguments+1, newargs); -} - -/** - * \brief Execute a script function - * \param Script Script context to execute in - * \param Function Function name to execute - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *ClassName, - int NArguments, tSpiderValue **Arguments) -{ - int bFound = 0; // Used to keep nesting levels down - tSpiderValue *ret = ERRPTR; - tSpiderObjectDef *class; - - // First: Find the function in the script - // TODO: Implement script-defined classes - #if 0 - { - tAST_Function *astClass; - for( astClass = Script->Script->Classes; astClass; astClass = astClass->Next ) - { - if( strcmp(astClass->Name, ClassName) == 0 ) - break; - } - // Execute! - if(astClass) - { - 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 ++; - - 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 - } - bFound = 1; - - while(bs.FirstVar) - { - tAST_Variable *nextVar = bs.FirstVar->Next; - Variable_Destroy( bs.FirstVar ); - bs.FirstVar = nextVar; - } - } - } - #endif - - // Didn't find it in script? - if(!bFound) - { - class = NULL; // Just to allow the below code to be neat - - //if( !Namespace ) - // Namespace = &Script->Variant->RootNamespace; - - // Second: Scan current namespace - if( !class && Namespace ) - { - for( class = Namespace->Classes; class; class = class->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - - #if 0 - // Third: Search the variant's global exports - if( !class ) - { - for( class = Script->Variant->Classes; class; class = fcn->Next ) - { - if( strcmp( class->Name, Function ) == 0 ) - break; - } - } - #endif - - #if 0 - // Fourth: Search language exports - if( !class ) - { - for( class = gpExports_First; class; class = fcn->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - #endif - - // Execute! - if(class) - { - tSpiderObject *obj; - // TODO: Type Checking - - // Call constructor - obj = class->Constructor( NArguments, Arguments ); - if( obj == NULL || obj == ERRPTR ) - return (void *)obj; - - // Creatue return object - ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_OBJECT; - ret->ReferenceCount = 1; - ret->Object = obj; - bFound = 1; - } - } - - // Not found? - if(!bFound) - { - fprintf(stderr, "Undefined reference to class '%s'\n", ClassName); - return ERRPTR; - } - - return ret; -} - - /** * \brief Execute an AST node and return its value * \param Block Execution context @@ -1372,29 +1081,3 @@ void Variable_Destroy(tAST_Variable *Variable) free(Variable); } -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "%s: ", Type); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "error: "); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c index e2401160..64df3a0c 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -9,6 +9,7 @@ #include #include "common.h" #include "bytecode.h" +#include #include #include "ast.h" @@ -156,12 +157,15 @@ tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function * // Get return value Bytecode_int_StackPop(stack, &val); + free(stack); 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; } @@ -179,8 +183,10 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t // Pop off arguments if( ArgCount > Fcn->ArgumentCount ) return -1; - for( i = Fcn->ArgumentCount; --i != ArgCount; ) + printf("Fcn->ArgumentCount = %i\n", Fcn->ArgumentCount); + for( i = Fcn->ArgumentCount; i > ArgCount; ) { + i --; local_vars[i].Integer = 0; local_vars[i].Type = Fcn->Arguments[i].Type; } @@ -247,6 +253,7 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t default: // TODO: + printf("Unknown operation %i\n", op->Operation); break; } op = nextop; diff --git a/Usermode/Libraries/libspiderscript.so_src/lex.c b/Usermode/Libraries/libspiderscript.so_src/lex.c index bb86198d..2d16bcfb 100644 --- a/Usermode/Libraries/libspiderscript.so_src/lex.c +++ b/Usermode/Libraries/libspiderscript.so_src/lex.c @@ -377,7 +377,7 @@ int GetToken(tParser *File) break; } // Syntax Error - ret = TOK_INVAL; + File->Token = TOK_INVAL; fprintf(stderr, "Syntax Error: Unknown symbol '%c'\n", *File->CurPos); longjmp(File->JmpTarget, 1); diff --git a/Usermode/Libraries/libspiderscript.so_src/main.c b/Usermode/Libraries/libspiderscript.so_src/main.c index d6cd722e..e2f846a9 100644 --- a/Usermode/Libraries/libspiderscript.so_src/main.c +++ b/Usermode/Libraries/libspiderscript.so_src/main.c @@ -30,15 +30,11 @@ int SoMain() */ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filename) { - char cacheFilename[strlen(Filename)+6+1]; char *data; int fLen; FILE *fp; tSpiderScript *ret; - strcpy(cacheFilename, Filename); - strcat(cacheFilename, ".cache"); - fp = fopen(Filename, "r"); if( !fp ) { return NULL; @@ -77,29 +73,51 @@ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filen // HACK!! + // - Save AST to a file { - size_t size; - - printf("Total Size: "); fflush(stdout); - 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); - fwrite(data, size, 1, fp); - free(data); - fclose(fp); + char cacheFilename[strlen(Filename)+6+1]; + strcpy(cacheFilename, Filename); + strcat(cacheFilename, ".ast"); + + SpiderScript_SaveAST(ret, cacheFilename); + } + // - Save Bytecode too + { + char cacheFilename[strlen(Filename)+6+1]; + strcpy(cacheFilename, Filename); + strcat(cacheFilename, ".bc"); + + SpiderScript_SaveBytecode(ret, cacheFilename); } return ret; } -int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile) +int SpiderScript_SaveAST(tSpiderScript *Script, const char *Filename) { - return Bytecode_ConvertScript(Script, DestFile); + size_t size; + FILE *fp; + void *data; + printf("Total Size: "); + fflush(stdout); + size = AST_WriteScript(NULL, Script); + printf("0x%x bytes\n", (unsigned)size); + + fp = fopen(Filename, "wb"); + if(!fp) return 1; + + data = malloc(size); + if(!data) { + fclose(fp); + return -1; + } + + size = AST_WriteScript(data, Script); + fwrite(data, size, 1, fp); + free(data); + + fclose(fp); + return 0; } /**