SpiderScript - Restructured to be able to keep bytecode and AST in memory at one...
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / ast.c
index 36568e6..78a54be 100644 (file)
@@ -5,60 +5,61 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#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,22 +115,32 @@ 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;
-       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;
 }
@@ -139,11 +150,13 @@ size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
  */
 size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node)
 {
-       size_t  ptr;
        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;
        }
        
@@ -181,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);
@@ -208,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
@@ -219,7 +234,11 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node)
        
        // Unary Operations
        case NODETYPE_RETURN:
-               ptr = Offset;
+       case NODETYPE_BWNOT:
+       case NODETYPE_LOGICALNOT:
+       case NODETYPE_NEGATE:
+       case NODETYPE_POSTINC:
+       case NODETYPE_POSTDEC:
                Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
                break;
        
@@ -237,8 +256,8 @@ 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:
+       case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL:
+       case NODETYPE_GREATERTHAN:      case NODETYPE_GREATERTHANEQUAL:
                Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left);
                Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right);
                break;
@@ -248,18 +267,20 @@ 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:
@@ -279,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
@@ -343,10 +369,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;
        
@@ -364,8 +396,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;
@@ -374,20 +406,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(tParser *Parser)
+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->File = Parser->Filename;   *(int*)(Parser->Filename - sizeof(int)) += 1;
        ret->Line = Parser->CurLine;
-       ret->Type = NODETYPE_BLOCK;
+       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;
        
@@ -396,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 )
        {
@@ -425,37 +480,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;
@@ -465,11 +525,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;
        
@@ -478,11 +535,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;
        
@@ -493,29 +547,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;
 }
@@ -523,13 +593,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;
 }
 
@@ -538,10 +619,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;
 }
@@ -551,13 +629,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;
 }
 
@@ -566,11 +645,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;
 }
 
@@ -580,42 +658,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 = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
+       tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_METHODCALL, strlen(Name) + 1 );
        
-       ret->NextSibling = NULL;
-       ret->Line = Parser->CurLine;
-       ret->Type = NODETYPE_METHODCALL;
        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 = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
+       tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_CREATEOBJECT, strlen(Name) + 1 );
        
-       ret->NextSibling = NULL;
-       ret->Line = Parser->CurLine;
-       ret->Type = NODETYPE_CREATEOBJECT;
        ret->FunctionCall.Object = NULL;
        ret->FunctionCall.FirstArg = NULL;
        ret->FunctionCall.LastArg = NULL;
+       ret->FunctionCall.NumArgs = 0;
        strcpy(ret->FunctionCall.Name, Name);
+       
        return ret;
 }
 
@@ -640,6 +715,7 @@ void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
                Node->FunctionCall.FirstArg = Arg;
                Node->FunctionCall.LastArg = Arg;
        }
+       Node->FunctionCall.NumArgs ++;
 }
 
 /**
@@ -647,11 +723,7 @@ void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
  */
 tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child)
 {
-       tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
-       
-       ret->NextSibling = NULL;
-       ret->Line = Parser->CurLine;
-       ret->Type = NODETYPE_SCOPE;
+       tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_SCOPE, strlen(Name) + 1 );
        ret->Scope.Element = Child;
        strcpy(ret->Scope.Name, Name);
        return ret;
@@ -662,11 +734,7 @@ tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node
  */
 tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name)
 {
-       tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
-       
-       ret->NextSibling = NULL;
-       ret->Line = Parser->CurLine;
-       ret->Type = NODETYPE_ELEMENT;
+       tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_ELEMENT, strlen(Name) + 1 );
        ret->Scope.Element = Object;
        strcpy(ret->Scope.Name, Name);
        return ret;

UCC git Repository :: git.ucc.asn.au