SpiderScript - Bugs, Documentation and a few language features
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / ast.c
index 45b8176..0c7e2df 100644 (file)
@@ -65,12 +65,231 @@ void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root)
  * \name Node Manipulation
  * \{
  */
+#define WRITE_N(_buffer, _offset, _len, _dataptr) do { \
+       if(_buffer)     memcpy((char*)_buffer + _offset, _dataptr, _len);\
+       _offset += _len; \
+} while(0)
+
+#define WRITE_8(_buffer, _offset, _val) do {\
+       uint8_t v = (_val);\
+       WRITE_N(_buffer, _offset, 1, &v);\
+} while(0)
+#define WRITE_16(_buffer, _offset, _val) do {\
+       uint16_t        v = (_val);\
+       WRITE_N(_buffer, _offset, 2, &v);\
+} while(0)
+#define WRITE_32(_buffer, _offset, _val) do {\
+       uint32_t        v = (_val);\
+       WRITE_N(_buffer, _offset, 4, &v);\
+} while(0)
+#define WRITE_64(_buffer, _offset, _val) do {\
+       uint64_t        v = (_val);\
+       WRITE_N(_buffer, _offset, 8, &v);\
+} while(0)
+#define WRITE_REAL(_buffer, _offset, _val) do {\
+       double  v = (_val);\
+       WRITE_N(_buffer, _offset, sizeof(double), &v);\
+} while(0)
+
+#define WRITE_STR(_buffer, _offset, _string) do {\
+       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; \
+       size_t ptr = -1;\
+       for(node=(_listHead); node; node = node->NextSibling) {\
+               ptr = _offset;\
+               _offset += AST_WriteNode(_buffer, _offset, node); \
+               WRITE_32(_buffer, ptr, ptr); \
+       } \
+       if(ptr != -1){ptr -= 4; WRITE_32(_buffer, ptr, 0);} \
+} while(0)
+
+/**
+ * \brief Writes a script dump to a buffer
+ * \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)
+{
+       tAST_Function   *fcn;
+       size_t  ret = 0, ptr = 0;
+       
+       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
+       }
+       if( ptr )
+       {
+               ptr -= 4;
+               WRITE_32(Buffer, ptr, 0);       // Clear next for final
+       }
+       
+       return ret;
+}
+
+/**
+ * \brief Write a node to a file
+ */
+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");
+               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_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)
+       {
+       // Block of code
+       case NODETYPE_BLOCK:
+               WRITE_NODELIST(Buffer, Offset, Node->Block.FirstChild);
+               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:
+               Offset += AST_WriteNode(Buffer, Offset, Node->If.Condition);
+               Offset += AST_WriteNode(Buffer, Offset, Node->If.True);
+               Offset += AST_WriteNode(Buffer, Offset, Node->If.False);
+               break;
+       
+       // Looping Construct (For loop node)
+       case NODETYPE_LOOP:
+               WRITE_8(Buffer, Offset, Node->For.bCheckAfter);
+               
+               Offset += AST_WriteNode(Buffer, Offset, Node->For.Init);
+               Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition);
+               Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment);
+               Offset += AST_WriteNode(Buffer, Offset, Node->For.Code);
+               break;
+       
+       // Asignment
+       case NODETYPE_ASSIGN:
+               WRITE_8(Buffer, Offset, Node->Assign.Operation);
+               Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Dest);
+               Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Value);
+               break;
+       
+       // Casting
+       case NODETYPE_CAST:
+               WRITE_8(Buffer, Offset, Node->Cast.DataType);
+               Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value);
+               break;
+       
+       // Define a variable
+       case NODETYPE_DEFVAR:
+               WRITE_8(Buffer, Offset, Node->DefVar.DataType);
+               // 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:
+       case NODETYPE_BWNOT:
+       case NODETYPE_LOGICALNOT:
+       case NODETYPE_NEGATE:
+       case NODETYPE_POSTINC:
+       case NODETYPE_POSTDEC:
+               Offset += AST_WriteNode(Buffer, Offset, 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_LESSTHANEQUAL:
+       case NODETYPE_GREATERTHAN:      case NODETYPE_GREATERTHANEQUAL:
+               Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left);
+               Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right);
+               break;
+       
+       // Node types with no children
+       case NODETYPE_NOP:
+               break;
+       case NODETYPE_VARIABLE:
+       case NODETYPE_CONSTANT:
+               // TODO: De-Duplicate the strings
+               WRITE_STR(Buffer, Offset, Node->Variable.Name);
+               break;
+       case NODETYPE_STRING:
+               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->Constant.Integer);
+               break;
+       case NODETYPE_REAL:
+               WRITE_REAL(Buffer, Offset, Node->Constant.Real);
+               break;
+       
+       //default:
+       //      fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type);
+       //      break;
+       }
+       
+       return Offset - baseOfs;
+}
+
 /**
  * \brief Free a node and all subnodes
  */
 void AST_FreeNode(tAST_Node *Node)
 {
        tAST_Node       *node;
+       
+       if(!Node)       return ;
+       
        switch(Node->Type)
        {
        // Block of code
@@ -84,7 +303,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;
@@ -93,6 +315,21 @@ void AST_FreeNode(tAST_Node *Node)
                }
                break;
        
+       // If node
+       case NODETYPE_IF:
+               AST_FreeNode(Node->If.Condition);
+               AST_FreeNode(Node->If.True);
+               AST_FreeNode(Node->If.False);
+               break;
+       
+       // Looping Construct (For loop node)
+       case NODETYPE_LOOP:
+               AST_FreeNode(Node->For.Init);
+               AST_FreeNode(Node->For.Condition);
+               AST_FreeNode(Node->For.Increment);
+               AST_FreeNode(Node->For.Code);
+               break;
+       
        // Asignment
        case NODETYPE_ASSIGN:
                AST_FreeNode(Node->Assign.Dest);
@@ -104,6 +341,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; )
@@ -112,10 +354,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;
        
@@ -133,8 +381,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;
@@ -143,19 +391,38 @@ 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_STRING:
+       case NODETYPE_INTEGER:
+       case NODETYPE_REAL:
+               if( Node->ValueCache )
+                       Object_Dereference(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->Type = NODETYPE_BLOCK;
+       ret->File = "<unk>";
+       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;
        
@@ -191,12 +458,30 @@ void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
        }
 }
 
-tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
+tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
+{
+       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       *ret = AST_int_AllocateNode(Parser, NODETYPE_LOOP, 0);
+       ret->For.Init = Init;
+       ret->For.bCheckAfter = !!bPostCheck;
+       ret->For.Condition = Condition;
+       ret->For.Increment = Increment;
+       ret->For.Code = Code;
+       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);
        
-       ret->NextSibling = NULL;
-       ret->Type = NODETYPE_ASSIGN;
        ret->Assign.Operation = Operation;
        ret->Assign.Dest = Dest;
        ret->Assign.Value = Value;
@@ -204,12 +489,20 @@ tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
        return ret;
 }
 
-tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
+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->Cast.DataType = Target;
+       ret->Cast.Value = Value;
+       
+       return ret;
+}
+
+tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
+{
+       tAST_Node       *ret = AST_int_AllocateNode(Parser, Operation, 0);
        
-       ret->NextSibling = NULL;
-       ret->Type = Operation;
        ret->BinOp.Left = Left;
        ret->BinOp.Right = Right;
        
@@ -218,29 +511,34 @@ tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
 
 /**
  */
-tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
+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->Type = Operation;
        ret->UniOp.Value = Value;
        
        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(const char *String, int Length)
+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->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;
 }
@@ -248,23 +546,33 @@ tAST_Node *AST_NewString(const char *String, int Length)
 /**
  * \brief Create a new integer node
  */
-tAST_Node *AST_NewInteger(uint64_t Value)
+tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value)
 {
-       tAST_Node       *ret = malloc( sizeof(tAST_Node) );
-       ret->NextSibling = NULL;
-       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;
 }
 
 /**
  * \brief Create a new variable reference node
  */
-tAST_Node *AST_NewVariable(const char *Name)
+tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
 {
-       tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
-       ret->NextSibling = NULL;
-       ret->Type = NODETYPE_VARIABLE;
+       tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_VARIABLE, strlen(Name) + 1 );
        strcpy(ret->Variable.Name, Name);
        return ret;
 }
@@ -272,26 +580,28 @@ tAST_Node *AST_NewVariable(const char *Name)
 /**
  * \brief Create a new variable definition node
  */
-tAST_Node *AST_NewDefineVar(int Type, 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->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;
 }
 
 /**
  * \brief Create a new runtime constant reference node
  */
-tAST_Node *AST_NewConstant(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->Type = NODETYPE_CONSTANT;
+       tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_CONSTANT, strlen(Name) + 1 );
+       
        strcpy(ret->Variable.Name, Name);
+       
        return ret;
 }
 
@@ -299,15 +609,41 @@ tAST_Node *AST_NewConstant(const char *Name)
  * \brief Create a function call node
  * \note Argument list is manipulated using AST_AppendFunctionCallArg
  */
-tAST_Node *AST_NewFunctionCall(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->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;
 }
 
@@ -316,7 +652,13 @@ tAST_Node *AST_NewFunctionCall(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;
@@ -326,6 +668,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;
 }
 
 /**

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