#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;
}
/**
* \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 )
{
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 )
{
{
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;
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;
// === 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);
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include "common.h"
#include "ast.h"
#include "bytecode_gen.h"
#include "bytecode_ops.h"
/**
* \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;
}
struct sBC_Function
{
- const char *Name;
-
int LabelCount;
int LabelSpace;
tBC_Op **Labels;
// 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
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;
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;
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;
#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
{
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);
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)
{
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) {
_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);
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);
}
--- /dev/null
+/*
+ * 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
+
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include "common.h"
#include "ast.h"
#define TRACE_VAR_LOOKUPS 0
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
{
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
* 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"
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)
{
#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;
Bytecode_int_StackPush(Stack, &val1);
// Execute!
- op = Fcn->Operations;
+ op = Fcn->BCFcn->Operations;
while(op)
{
tBC_Op *nextop = op->Next;
{
// 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
#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);
// 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;
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);
*/
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);
}
#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);
/**
* \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);
parser.Filename += sizeof(int); // Move filename
parser.ErrorHit = 0;
- ret = AST_NewScript();
mainCode = AST_NewCodeBlock(&parser);
// Give us an error fallback
{
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!
// 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
// 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;
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;
}
/**