X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fast.c;h=12f9f775ce37b72cc53f300257fe4527ff128406;hb=f9c581641afeb556188e84428febd4011e61edc2;hp=1453a9267e38bc97d135a89cdf6ca73e0e084e7a;hpb=ec4d050568da0f3f18a20969bd118b5c67f03ee2;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.c b/Usermode/Libraries/libspiderscript.so_src/ast.c index 1453a926..12f9f775 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast.c @@ -5,191 +5,67 @@ #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; } /** * \name Node Manipulation * \{ */ -/** - * \brief Get the in-memory size of a node - */ -size_t AST_GetNodeSize(tAST_Node *Node) -{ - size_t ret; - tAST_Node *node; - - if(!Node) - return 0; - - ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType) - + sizeof(const char *) + sizeof(int); - - switch(Node->Type) - { - // Block of code - case NODETYPE_BLOCK: - ret += sizeof(Node->Block); - for( node = Node->Block.FirstChild; node; ) - { - ret += AST_GetNodeSize(node); - node = node->NextSibling; - } - break; - - // Function Call - case NODETYPE_FUNCTIONCALL: - ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1; - for( node = Node->FunctionCall.FirstArg; node; ) - { - ret += AST_GetNodeSize(node); - node = node->NextSibling; - } - break; - - // If node - case NODETYPE_IF: - ret += sizeof(Node->If); - ret += AST_GetNodeSize(Node->If.Condition); - ret += AST_GetNodeSize(Node->If.True); - ret += AST_GetNodeSize(Node->If.False); - break; - - // Looping Construct (For loop node) - case NODETYPE_LOOP: - ret += sizeof(Node->For); - ret += AST_GetNodeSize(Node->For.Init); - ret += AST_GetNodeSize(Node->For.Condition); - ret += AST_GetNodeSize(Node->For.Increment); - ret += AST_GetNodeSize(Node->For.Code); - break; - - // Asignment - case NODETYPE_ASSIGN: - ret += sizeof(Node->Assign); - ret += AST_GetNodeSize(Node->Assign.Dest); - ret += AST_GetNodeSize(Node->Assign.Value); - break; - - // Casting - case NODETYPE_CAST: - ret += sizeof(Node->Cast); - ret += AST_GetNodeSize(Node->Cast.Value); - break; - - // Define a variable - case NODETYPE_DEFVAR: - ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1; - for( node = Node->DefVar.LevelSizes; node; ) - { - ret += AST_GetNodeSize(node); - node = node->NextSibling; - } - break; - - // Unary Operations - case NODETYPE_RETURN: - ret += sizeof(Node->UniOp); - ret += AST_GetNodeSize(Node->UniOp.Value); - break; - - // Binary Operations - case NODETYPE_INDEX: - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_BWAND: case NODETYPE_LOGICALAND: - case NODETYPE_BWOR: case NODETYPE_LOGICALOR: - case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: - case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: - ret += sizeof(Node->BinOp); - ret += AST_GetNodeSize( Node->BinOp.Left ); - ret += AST_GetNodeSize( Node->BinOp.Right ); - break; - - // Node types with no children - case NODETYPE_NOP: - break; - case NODETYPE_VARIABLE: - case NODETYPE_CONSTANT: - ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1; - break; - case NODETYPE_STRING: - ret += sizeof(Node->String) + Node->String.Length; - break; - case NODETYPE_INTEGER: - ret += sizeof(Node->Integer); - break; - case NODETYPE_REAL: - ret += sizeof(Node->Real); - break; - } - return ret; -} - -#if 1 - #define WRITE_N(_buffer, _offset, _len, _dataptr) do { \ if(_buffer) memcpy((char*)_buffer + _offset, _dataptr, _len);\ _offset += _len; \ @@ -220,6 +96,8 @@ size_t AST_GetNodeSize(tAST_Node *Node) int len = strlen(_string);\ WRITE_16(_buffer, _offset, len);\ WRITE_N(_buffer, _offset, len, _string);\ + if((_offset & 1) == 1)WRITE_8(_buffer, _offset, 0); \ + if((_offset & 3) == 2)WRITE_16(_buffer, _offset, 0); \ } while(0) #define WRITE_NODELIST(_buffer, _offset, _listHead) do {\ tAST_Node *node; \ @@ -237,22 +115,32 @@ size_t AST_GetNodeSize(tAST_Node *Node) * \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; - size_t ret = 0, ptr; + 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 ) + { + ptr -= 4; + WRITE_32(Buffer, ptr, 0); // Clear next for final } - ptr -= 4; - WRITE_32(Buffer, ptr, 0); // Clear next for final return ret; } @@ -262,18 +150,22 @@ size_t AST_WriteScript(void *Buffer, tAST_Script *Script) */ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) { - off_t ptr; - typeof(Offset) baseOfs = Offset; + 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; } WRITE_32(Buffer, Offset, 0); // Next - WRITE_8(Buffer, Offset, Node->Type); - //WRITE_32(Buffer, Offset, 0); // File + WRITE_16(Buffer, Offset, Node->Type); + // TODO: Scan the buffer for the location of the filename (with NULL byte) + // else, write the string at the end of the node WRITE_16(Buffer, Offset, Node->Line); // Line + //WRITE_32(Buffer, Offset, 0); // File switch(Node->Type) { @@ -283,83 +175,70 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) break; // Function Call + case NODETYPE_METHODCALL: + Offset += AST_WriteNode(Buffer, Offset, Node->FunctionCall.Object); case NODETYPE_FUNCTIONCALL: + case NODETYPE_CREATEOBJECT: + // TODO: Search for the same function name and add a pointer WRITE_STR(Buffer, Offset, Node->FunctionCall.Name); WRITE_NODELIST(Buffer, Offset, Node->FunctionCall.FirstArg); break; // If node case NODETYPE_IF: - ptr = Offset; - WRITE_32(Buffer, Offset, 0); // Condition - WRITE_32(Buffer, Offset, 0); // True - WRITE_32(Buffer, Offset, 0); // False - Offset += AST_WriteNode(Buffer, Offset, Node->If.Condition); - WRITE_32(Buffer, ptr, Offset); Offset += AST_WriteNode(Buffer, Offset, Node->If.True); - WRITE_32(Buffer, ptr, Offset); Offset += AST_WriteNode(Buffer, Offset, Node->If.False); - WRITE_32(Buffer, ptr, Offset); break; // Looping Construct (For loop node) case NODETYPE_LOOP: WRITE_8(Buffer, Offset, Node->For.bCheckAfter); - ptr = Offset; - WRITE_32(Buffer, Offset, 0); // Init - WRITE_32(Buffer, Offset, 0); // Condition - WRITE_32(Buffer, Offset, 0); // Increment - WRITE_32(Buffer, Offset, 0); // Code - + WRITE_STR(Buffer, Offset, Node->For.Tag); Offset += AST_WriteNode(Buffer, Offset, Node->For.Init); - WRITE_32(Buffer, ptr, Offset); Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition); - WRITE_32(Buffer, ptr, Offset); Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment); - WRITE_32(Buffer, ptr, Offset); Offset += AST_WriteNode(Buffer, Offset, Node->For.Code); - WRITE_32(Buffer, ptr, Offset); break; // Asignment case NODETYPE_ASSIGN: WRITE_8(Buffer, Offset, Node->Assign.Operation); - ptr = Offset; - WRITE_32(Buffer, Offset, 0); // Dest - WRITE_32(Buffer, Offset, 0); // Value - Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Dest); - WRITE_32(Buffer, ptr, Offset); Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Value); - WRITE_32(Buffer, ptr, Offset); break; // Casting case NODETYPE_CAST: WRITE_8(Buffer, Offset, Node->Cast.DataType); - ptr = Offset; - WRITE_32(Buffer, Offset, 0); - Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value); - WRITE_32(Buffer, ptr, Offset); break; // Define a variable case NODETYPE_DEFVAR: WRITE_8(Buffer, Offset, Node->DefVar.DataType); - WRITE_8(Buffer, Offset, Node->DefVar.Depth); + // TODO: Duplicate compress the strings 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 + case NODETYPE_SCOPE: + case NODETYPE_ELEMENT: + WRITE_STR(Buffer, Offset, Node->Scope.Name); + Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value); break; // Unary Operations case NODETYPE_RETURN: - ptr = Offset; - WRITE_32(Buffer, Offset, 0); + case NODETYPE_BWNOT: + case NODETYPE_LOGICALNOT: + case NODETYPE_NEGATE: + case NODETYPE_POSTINC: + case NODETYPE_POSTDEC: Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value); - WRITE_32(Buffer, ptr, Offset); break; // Binary Operations @@ -376,15 +255,10 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) case NODETYPE_BWOR: case NODETYPE_LOGICALOR: case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: - ptr = Offset; - WRITE_32(Buffer, Offset, 0); // Left - WRITE_32(Buffer, Offset, 0); // Right + case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: + case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left); - WRITE_32(Buffer, ptr, Offset); Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right); - WRITE_32(Buffer, ptr, Offset); break; // Node types with no children @@ -392,156 +266,29 @@ 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; case NODETYPE_STRING: - WRITE_32(Buffer, Offset, Node->String.Length); - WRITE_N(Buffer, Offset, Node->String.Length, Node->String.Data); + WRITE_32(Buffer, Offset, Node->Constant.String.Length); + WRITE_N(Buffer, Offset, Node->Constant.String.Length, Node->Constant.String.Data); break; case NODETYPE_INTEGER: - WRITE_64(Buffer, Offset, Node->Integer); + WRITE_64(Buffer, Offset, Node->Constant.Integer); break; case NODETYPE_REAL: - WRITE_REAL(Buffer, Offset, Node->Real); + WRITE_REAL(Buffer, Offset, Node->Constant.Real); break; - default: - fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type); - break; + //default: + // fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type); + // break; } return Offset - baseOfs; } -#elif 0 -/** - * \brief Write a node to a file - */ -void AST_WriteNode(FILE *FP, tAST_Node *Node) -{ - tAST_Node *node; - intptr_t ptr; - int ret; - - if(!Node) return ; - - ptr = ftell(FP) + AST_GetNodeSize(Node); - fwrite(&ptr, sizeof(ptr), 1, FP); - fwrite(&Node->Type, sizeof(Node->Type), 1, FP); - ptr = 0; fwrite(&ptr, sizeof(ptr), 1, FP); // File - fwrite(&Node->Line, sizeof(Node->Line), 1, FP); - - ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType) - + sizeof(const char *) + sizeof(int); - - switch(Node->Type) - { - // Block of code - case NODETYPE_BLOCK: - ret += sizeof(Node->Block); - for( node = Node->Block.FirstChild; node; ) - { - ret += AST_GetNodeSize(node); - node = node->NextSibling; - } - break; - - // Function Call - case NODETYPE_FUNCTIONCALL: - ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1; - for( node = Node->FunctionCall.FirstArg; node; ) - { - ret += AST_GetNodeSize(node); - node = node->NextSibling; - } - break; - - // If node - case NODETYPE_IF: - ret += sizeof(Node->If); - ret += AST_GetNodeSize(Node->If.Condition); - ret += AST_GetNodeSize(Node->If.True); - ret += AST_GetNodeSize(Node->If.False); - break; - - // Looping Construct (For loop node) - case NODETYPE_LOOP: - ret += sizeof(Node->For); - ret += AST_GetNodeSize(Node->For.Init); - ret += AST_GetNodeSize(Node->For.Condition); - ret += AST_GetNodeSize(Node->For.Increment); - ret += AST_GetNodeSize(Node->For.Code); - break; - - // Asignment - case NODETYPE_ASSIGN: - ret += sizeof(Node->Assign); - ret += AST_GetNodeSize(Node->Assign.Dest); - ret += AST_GetNodeSize(Node->Assign.Value); - break; - - // Casting - case NODETYPE_CAST: - ret += sizeof(Node->Cast); - ret += AST_GetNodeSize(Node->Cast.Value); - break; - - // Define a variable - case NODETYPE_DEFVAR: - ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1; - for( node = Node->DefVar.LevelSizes; node; ) - { - ret += AST_GetNodeSize(node); - node = node->NextSibling; - } - break; - - // Unary Operations - case NODETYPE_RETURN: - ret += sizeof(Node->UniOp); - ret += AST_GetNodeSize(Node->UniOp.Value); - break; - - // Binary Operations - case NODETYPE_INDEX: - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_BWAND: case NODETYPE_LOGICALAND: - case NODETYPE_BWOR: case NODETYPE_LOGICALOR: - case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: - case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: - ret += sizeof(Node->BinOp); - ret += AST_GetNodeSize( Node->BinOp.Left ); - ret += AST_GetNodeSize( Node->BinOp.Right ); - break; - - // Node types with no children - case NODETYPE_NOP: - break; - case NODETYPE_VARIABLE: - case NODETYPE_CONSTANT: - ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1; - break; - case NODETYPE_STRING: - ret += sizeof(Node->String) + Node->String.Length; - break; - case NODETYPE_INTEGER: - ret += sizeof(Node->Integer); - break; - case NODETYPE_REAL: - ret += sizeof(Node->Real); - break; - } - return ret; -} -#endif /** * \brief Free a node and all subnodes @@ -552,6 +299,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 @@ -565,7 +317,10 @@ void AST_FreeNode(tAST_Node *Node) break; // Function Call + case NODETYPE_METHODCALL: + AST_FreeNode(Node->FunctionCall.Object); case NODETYPE_FUNCTIONCALL: + case NODETYPE_CREATEOBJECT: for( node = Node->FunctionCall.FirstArg; node; ) { tAST_Node *savedNext = node->NextSibling; @@ -600,6 +355,11 @@ void AST_FreeNode(tAST_Node *Node) AST_FreeNode(Node->Cast.Value); break; + case NODETYPE_SCOPE: + case NODETYPE_ELEMENT: + AST_FreeNode(Node->Scope.Element); + break; + // Define a variable case NODETYPE_DEFVAR: for( node = Node->DefVar.LevelSizes; node; ) @@ -608,10 +368,16 @@ void AST_FreeNode(tAST_Node *Node) AST_FreeNode(node); node = savedNext; } + AST_FreeNode(Node->DefVar.InitialValue); break; // Unary Operations case NODETYPE_RETURN: + case NODETYPE_BWNOT: + case NODETYPE_LOGICALNOT: + case NODETYPE_NEGATE: + case NODETYPE_POSTINC: + case NODETYPE_POSTDEC: AST_FreeNode(Node->UniOp.Value); break; @@ -629,8 +395,8 @@ void AST_FreeNode(tAST_Node *Node) case NODETYPE_BWOR: case NODETYPE_LOGICALOR: case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: + case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: + case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: AST_FreeNode( Node->BinOp.Left ); AST_FreeNode( Node->BinOp.Right ); break; @@ -639,20 +405,40 @@ void AST_FreeNode(tAST_Node *Node) case NODETYPE_NOP: break; case NODETYPE_VARIABLE: break; case NODETYPE_CONSTANT: break; - case NODETYPE_STRING: break; - case NODETYPE_INTEGER: break; - case NODETYPE_REAL: break; + case NODETYPE_BREAK: + case NODETYPE_CONTINUE: break; + + case NODETYPE_STRING: + case NODETYPE_INTEGER: + case NODETYPE_REAL: + if( Node->ValueCache ) + SpiderScript_DereferenceValue(Node->ValueCache); + Node->ValueCache = NULL; + break; } free( Node ); } -tAST_Node *AST_NewCodeBlock(void) +tAST_Node *AST_int_AllocateNode(tParser *Parser, int Type, int ExtraSize) { - tAST_Node *ret = malloc( sizeof(tAST_Node) ); - + tAST_Node *ret = malloc( sizeof(tAST_Node) + ExtraSize ); ret->NextSibling = NULL; - //ret->Line = Parser->CurLine; - ret->Type = NODETYPE_BLOCK; + ret->File = Parser->Filename; *(int*)(Parser->Filename - sizeof(int)) += 1; + ret->Line = Parser->CurLine; + ret->Type = Type; + + // Runtime Caching + ret->BlockState = NULL; + ret->BlockIdent = 0; + ret->ValueCache = NULL; + + return ret; +} + +tAST_Node *AST_NewCodeBlock(tParser *Parser) +{ + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_BLOCK, 0 ); + ret->Block.FirstChild = NULL; ret->Block.LastChild = NULL; @@ -661,6 +447,9 @@ tAST_Node *AST_NewCodeBlock(void) void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child) { + // Ignore NULL children + if( !Child ) return ; + Child->NextSibling = NULL; switch( Parent->Type ) { @@ -690,37 +479,42 @@ void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child) tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False) { - tAST_Node *ret = malloc( sizeof(tAST_Node) ); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_IF; + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_IF, 0); ret->If.Condition = Condition; ret->If.True = True; ret->If.False = False; 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 = malloc( sizeof(tAST_Node) ); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_LOOP; + 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; } tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value) { - tAST_Node *ret = malloc( sizeof(tAST_Node) ); + 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->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_ASSIGN; ret->Assign.Operation = Operation; ret->Assign.Dest = Dest; ret->Assign.Value = Value; @@ -730,11 +524,8 @@ tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_N tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value) { - tAST_Node *ret = malloc( sizeof(tAST_Node) ); + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CAST, 0); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_CAST; ret->Cast.DataType = Target; ret->Cast.Value = Value; @@ -743,11 +534,8 @@ tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value) tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right) { - tAST_Node *ret = malloc( sizeof(tAST_Node) ); + tAST_Node *ret = AST_int_AllocateNode(Parser, Operation, 0); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = Operation; ret->BinOp.Left = Left; ret->BinOp.Right = Right; @@ -758,29 +546,45 @@ tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_No */ tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value) { - tAST_Node *ret = malloc( sizeof(tAST_Node) ); + tAST_Node *ret = AST_int_AllocateNode(Parser, Operation, 0); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = Operation; ret->UniOp.Value = 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); + + return ret; +} + /** * \brief Create a new string node */ tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length) { - tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 ); + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_STRING, Length + 1); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_STRING; - ret->String.Length = Length; - memcpy(ret->String.Data, String, Length); - ret->String.Data[Length] = '\0'; + ret->Constant.Type = SS_DATATYPE_STRING; + ret->Constant.ReferenceCount = 1; + ret->Constant.String.Length = Length; + memcpy(ret->Constant.String.Data, String, Length); + ret->Constant.String.Data[Length] = '\0'; return ret; } @@ -788,13 +592,24 @@ tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length) /** * \brief Create a new integer node */ -tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value) +tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value) { - tAST_Node *ret = malloc( sizeof(tAST_Node) ); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_INTEGER; - ret->Integer = Value; + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_INTEGER, 0); + ret->Constant.Type = SS_DATATYPE_INTEGER; + ret->Constant.ReferenceCount = 1; + ret->Constant.Integer = Value; + return ret; +} + +/** + * \brief Create a new real number node + */ +tAST_Node *AST_NewReal(tParser *Parser, double Value) +{ + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_REAL, 0); + ret->Constant.Type = SS_DATATYPE_REAL; + ret->Constant.ReferenceCount = 1; + ret->Constant.Real = Value; return ret; } @@ -803,10 +618,7 @@ tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value) */ tAST_Node *AST_NewVariable(tParser *Parser, const char *Name) { - tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_VARIABLE; + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_VARIABLE, strlen(Name) + 1 ); strcpy(ret->Variable.Name, Name); return ret; } @@ -816,13 +628,14 @@ tAST_Node *AST_NewVariable(tParser *Parser, const char *Name) */ tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name) { - tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_DEFVAR; + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_DEFVAR, strlen(Name) + 1 ); + ret->DefVar.DataType = Type; ret->DefVar.LevelSizes = NULL; + ret->DefVar.LevelSizes_Last = NULL; + ret->DefVar.InitialValue = NULL; strcpy(ret->DefVar.Name, Name); + return ret; } @@ -831,11 +644,10 @@ tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name) */ tAST_Node *AST_NewConstant(tParser *Parser, const char *Name) { - tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_CONSTANT; + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CONSTANT, strlen(Name) + 1 ); + strcpy(ret->Variable.Name, Name); + return ret; } @@ -845,14 +657,39 @@ tAST_Node *AST_NewConstant(tParser *Parser, const char *Name) */ tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name) { - tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_FUNCTIONCALL, strlen(Name) + 1 ); - ret->NextSibling = NULL; - ret->Line = Parser->CurLine; - ret->Type = NODETYPE_FUNCTIONCALL; + ret->FunctionCall.Object = NULL; + ret->FunctionCall.FirstArg = NULL; + ret->FunctionCall.LastArg = NULL; + ret->FunctionCall.NumArgs = 0; + strcpy(ret->FunctionCall.Name, Name); + + return ret; +} +tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name) +{ + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_METHODCALL, strlen(Name) + 1 ); + + ret->FunctionCall.Object = Object; + ret->FunctionCall.FirstArg = NULL; + ret->FunctionCall.LastArg = NULL; + ret->FunctionCall.NumArgs = 0; + strcpy(ret->FunctionCall.Name, Name); + + return ret; +} + +tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name) +{ + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CREATEOBJECT, strlen(Name) + 1 ); + + ret->FunctionCall.Object = NULL; ret->FunctionCall.FirstArg = NULL; ret->FunctionCall.LastArg = NULL; + ret->FunctionCall.NumArgs = 0; strcpy(ret->FunctionCall.Name, Name); + return ret; } @@ -861,7 +698,13 @@ tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name) */ void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg) { - if( Node->Type != NODETYPE_FUNCTIONCALL ) return ; + if( Node->Type != NODETYPE_FUNCTIONCALL + && Node->Type != NODETYPE_CREATEOBJECT + && Node->Type != NODETYPE_METHODCALL) + { + fprintf(stderr, "BUG REPORT: AST_AppendFunctionCallArg on an invalid node type (%i)\n", Node->Type); + return ; + } if(Node->FunctionCall.LastArg) { Node->FunctionCall.LastArg->NextSibling = Arg; @@ -871,6 +714,29 @@ void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg) Node->FunctionCall.FirstArg = Arg; Node->FunctionCall.LastArg = Arg; } + Node->FunctionCall.NumArgs ++; +} + +/** + * \brief Add a scope node + */ +tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child) +{ + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_SCOPE, strlen(Name) + 1 ); + ret->Scope.Element = Child; + strcpy(ret->Scope.Name, Name); + return ret; +} + +/** + * \brief Add a scope node + */ +tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name) +{ + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_ELEMENT, strlen(Name) + 1 ); + ret->Scope.Element = Object; + strcpy(ret->Scope.Name, Name); + return ret; } /**