X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=sidebyside;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fast.c;h=78a54bed7707b3fa3b5478b6e51e15b99e270dfb;hb=239f2374299c1471a40b1087725b32f3f163d9b3;hp=1ea7e3e5ad9a5a4f8718aafef547b755e15909e3;hpb=0f81e4f273cdf1032e9bca55b4185ca9113596cc;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.c b/Usermode/Libraries/libspiderscript.so_src/ast.c index 1ea7e3e5..78a54bed 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast.c @@ -5,60 +5,61 @@ #include #include #include +#include "common.h" #include "ast.h" -// === CODE === -tAST_Script *AST_NewScript(void) -{ - tAST_Script *ret = malloc( sizeof(tAST_Script) ); - - ret->Functions = NULL; - ret->LastFunction = NULL; - - return ret; -} +// === IMPORTS === +extern void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...); +// === CODE === /** * \brief Append a function to a script */ -tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name) +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 ); - ret->Next = NULL; - strcpy(ret->Name, Name); - ret->Code = NULL; - ret->Arguments = NULL; - - 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; } -} - -/** - * \brief Set the code for a function - */ -void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root) -{ - Function->Code = Root; + + return 0; } /** @@ -114,19 +115,26 @@ 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 ) { +// printf("fcn = %p, fcn->Name = %p\n", fcn, fcn->Name); 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 ) { @@ -145,7 +153,10 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) size_t baseOfs = Offset; if(!Node) { - fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n"); + //fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n"); + WRITE_32(Buffer, Offset, 0); + WRITE_16(Buffer, Offset, NODETYPE_NOP); + WRITE_16(Buffer, Offset, 0); // Line (0) return 0; } @@ -183,7 +194,8 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) // Looping Construct (For loop node) case NODETYPE_LOOP: WRITE_8(Buffer, Offset, Node->For.bCheckAfter); - +// printf("Node %p, Loop Tag %p\n", Node, Node->For.Tag); + WRITE_STR(Buffer, Offset, Node->For.Tag); Offset += AST_WriteNode(Buffer, Offset, Node->For.Init); Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition); Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment); @@ -210,6 +222,7 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) WRITE_STR(Buffer, Offset, Node->DefVar.Name); WRITE_NODELIST(Buffer, Offset, Node->DefVar.LevelSizes); + Offset += AST_WriteNode(Buffer, Offset, Node->DefVar.InitialValue); break; // Scope Reference @@ -254,6 +267,8 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) break; case NODETYPE_VARIABLE: case NODETYPE_CONSTANT: + case NODETYPE_BREAK: + case NODETYPE_CONTINUE: // TODO: De-Duplicate the strings WRITE_STR(Buffer, Offset, Node->Variable.Name); break; @@ -285,6 +300,11 @@ void AST_FreeNode(tAST_Node *Node) if(!Node) return ; + // Referenced counted file name + (*(int*)(Node->File - sizeof(int))) -= 1; + if( *(int*)(Node->File - sizeof(int)) == 0 ) + free( (void*)(Node->File - sizeof(int)) ); + switch(Node->Type) { // Block of code @@ -349,6 +369,7 @@ void AST_FreeNode(tAST_Node *Node) AST_FreeNode(node); node = savedNext; } + AST_FreeNode(Node->DefVar.InitialValue); break; // Unary Operations @@ -385,12 +406,14 @@ void AST_FreeNode(tAST_Node *Node) case NODETYPE_NOP: break; case NODETYPE_VARIABLE: break; case NODETYPE_CONSTANT: break; + case NODETYPE_BREAK: + case NODETYPE_CONTINUE: break; case NODETYPE_STRING: case NODETYPE_INTEGER: case NODETYPE_REAL: if( Node->ValueCache ) - Object_Dereference(Node->ValueCache); + SpiderScript_DereferenceValue(Node->ValueCache); Node->ValueCache = NULL; break; } @@ -401,7 +424,7 @@ tAST_Node *AST_int_AllocateNode(tParser *Parser, int Type, int ExtraSize) { tAST_Node *ret = malloc( sizeof(tAST_Node) + ExtraSize ); ret->NextSibling = NULL; - ret->File = ""; + ret->File = Parser->Filename; *(int*)(Parser->Filename - sizeof(int)) += 1; ret->Line = Parser->CurLine; ret->Type = Type; @@ -425,6 +448,9 @@ tAST_Node *AST_NewCodeBlock(tParser *Parser) void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child) { + // Ignore NULL children + if( !Child ) return ; + Child->NextSibling = NULL; switch( Parent->Type ) { @@ -461,14 +487,19 @@ tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAS return ret; } -tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code) +tAST_Node *AST_NewLoop(tParser *Parser, const char *Tag, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code) { - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_LOOP, 0); + tAST_Node *ret; + if(!Tag) Tag = ""; + // 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; ret->For.Increment = Increment; ret->For.Code = Code; + strcpy(ret->For.Tag, Tag); return ret; } @@ -476,6 +507,15 @@ tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_N { tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_ASSIGN, 0); + if( Dest->Type != NODETYPE_VARIABLE && Dest->Type != NODETYPE_ELEMENT ) { + free(ret); + SyntaxError(Parser, 1, "Assign target is not a variable or attribute (instead %i)", + Dest->Type); + AST_FreeNode(Dest); + AST_FreeNode(Value); + return NULL; + } + ret->Assign.Operation = Operation; ret->Assign.Dest = Dest; ret->Assign.Value = Value; @@ -514,6 +554,19 @@ tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value) return ret; } +tAST_Node *AST_NewBreakout(tParser *Parser, int Type, const char *DestTag) +{ + int len = (DestTag ? strlen(DestTag) : 0); + tAST_Node *ret = AST_int_AllocateNode(Parser, Type, len + 1); + + if( DestTag ) + strcpy(ret->Variable.Name, DestTag); + else + ret->Variable.Name[0] = '\0'; + + return ret; +} + tAST_Node *AST_NewNop(tParser *Parser) { tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_NOP, 0); @@ -580,6 +633,8 @@ tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name) ret->DefVar.DataType = Type; ret->DefVar.LevelSizes = NULL; + ret->DefVar.LevelSizes_Last = NULL; + ret->DefVar.InitialValue = NULL; strcpy(ret->DefVar.Name, Name); return ret;