#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, char *Buffer);
-extern const int giSpiderScript_NumExports;
-extern tSpiderFunction gaSpiderScript_Exports[];
+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, tSpiderObject *Value);
+extern void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
+extern void Variable_Destroy(tAST_Variable *Variable);
// === CODE ===
/**
return NULL;
}
- ret = malloc(sizeof(tSpiderScript));
- ret->Variant = Variant;
-
fseek(fp, 0, SEEK_END);
fLen = ftell(fp);
fseek(fp, 0, SEEK_SET);
// Allocate and read data
data = malloc(fLen + 1);
if(!data) return NULL;
- fread(data, fLen, 1, fp);
+ fLen = fread(data, 1, fLen, fp);
+ fclose(fp);
+ if( fLen < 0 ) {
+ free(data);
+ return NULL;
+ }
data[fLen] = '\0';
- fclose(fp);
+
+ // 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);
- if( ret->Script == NULL ) {
+ if( Parse_Buffer(ret, data, Filename) ) {
free(data);
free(ret);
return NULL;
free(data);
- return ret;
-}
-
-/**
- * \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
- */
-tSpiderObject *SpiderScript_ExecuteMethod(tSpiderScript *Script,
- const char *Function, int NArguments, tSpiderObject **Arguments)
-{
- char *trueName = NULL;
- int i;
- int bFound = 0; // Used to keep nesting levels down
- tSpiderObject *ret = ERRPTR;
-
- // Handle namespaces
- if( Function[0] == '.' ) {
- trueName = (char*)&Function[1];
- }
- else if( !Script->CurNamespace ) {
- trueName = (char*)Function;
- }
- else {
- int len = strlen(Script->CurNamespace) + 1 + strlen(Function);
- trueName = malloc( len + 1 );
- strcpy(trueName, Script->CurNamespace);
- strcat(trueName, ".");
- strcat(trueName, Function);
- }
- // First: Find the function in the script
+ // HACK!!
+ #if 1
+ // - Save AST to a file
{
- tAST_Function *fcn = Script->Script->Functions;
- for( ; fcn; fcn = fcn->Next ) {
- if( strcmp(fcn->Name, trueName) == 0 )
- break;
- }
- // Execute!
- if(fcn) {
- tAST_BlockState bs;
- bs.FirstVar = NULL; //< TODO: Parameters
- bs.Parent = NULL;
- bs.Script = Script;
- {
- tAST_Node *arg;
- int i = 0;
- for( arg = fcn->Arguments; arg; arg = arg->NextSibling, i++ )
- {
- // TODO: Type checks
- Variable_Define(&bs, arg->DefVar.DataType, arg->DefVar.Name);
- if( i >= NArguments ) break; // TODO: Return gracefully
- Variable_SetValue(&bs, arg->DefVar.Name, Arguments[i]);
- }
- }
- ret = AST_ExecuteNode(&bs, fcn->Code);
- bFound = 1;
- }
- }
-
- // Didn't find it in script?
- if(!bFound)
- {
- // Second: Search the variant's exports
- for( i = 0; i < Script->Variant->NFunctions; i ++ )
- {
- if( strcmp( Script->Variant->Functions[i].Name, trueName) == 0 )
- break;
- }
- // Execute!
- if(i < Script->Variant->NFunctions) {
- ret = Script->Variant->Functions[i].Handler( Script, NArguments, Arguments );
- bFound = 1;
- }
- }
+ char cacheFilename[strlen(Filename)+6+1];
+ strcpy(cacheFilename, Filename);
+ strcat(cacheFilename, ".ast");
- // Not in variant exports? Search the language internal ones
- if(!bFound)
- {
- for( i = 0; i < giSpiderScript_NumExports; i ++ )
- {
- if( strcmp( gaSpiderScript_Exports[i].Name, trueName ) == 0 )
- break;
- }
- // Execute!
- if(i < giSpiderScript_NumExports) {
- ret = gaSpiderScript_Exports[i].Handler( Script, NArguments, Arguments );
- bFound = 1;
- }
+ SpiderScript_SaveAST(ret, cacheFilename);
}
-
- // Not found?
- if(!bFound)
+ #endif
+ // - Save Bytecode too
{
- fprintf(stderr, "Undefined reference to '%s'\n", trueName);
- }
+ char cacheFilename[strlen(Filename)+6+1];
+ strcpy(cacheFilename, Filename);
+ strcat(cacheFilename, ".bc");
- if( trueName != Function && trueName != &Function[1] )
- free(trueName);
+ SpiderScript_SaveBytecode(ret, cacheFilename);
+ }
return ret;
+}
+
+int SpiderScript_SaveAST(tSpiderScript *Script, const char *Filename)
+{
+ size_t size;
+ FILE *fp;
+ void *data;
+
+ size = AST_WriteScript(NULL, Script);
+ 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;
}
/**
*/
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;
- }
-
+ while(fcn)
+ {
+ 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);
}