b9186087677214625810654d8fb962f1843de0a5
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / exec_ast.c
1 /*
2  */
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include "ast.h"
7
8 // === PROTOTYPES ===
9 void    Object_Dereference(tSpiderValue *Object);
10 void    Object_Reference(tSpiderValue *Object);
11 tSpiderValue    *Object_CreateInteger(uint64_t Value);
12 tSpiderValue    *Object_CreateReal(double Value);
13 tSpiderValue    *Object_CreateString(int Length, const char *Data);
14 tSpiderValue    *Object_CastTo(int Type, tSpiderValue *Source);
15  int    Object_IsTrue(tSpiderValue *Value);
16
17 tSpiderValue    *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node);
18
19 tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name);
20 void    Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
21 tSpiderValue    *Variable_GetValue(tAST_BlockState *Block, const char *Name);
22 void    Variable_Destroy(tAST_Variable *Variable);
23
24 // === CODE ===
25 /**
26  * \brief Dereference a created object
27  */
28 void Object_Dereference(tSpiderValue *Object)
29 {
30         if(!Object)     return ;
31         Object->ReferenceCount --;
32         if( Object->ReferenceCount == 0 ) {
33                 switch( (enum eSpiderScript_DataTypes) Object->Type )
34                 {
35                 case SS_DATATYPE_OBJECT:
36                         Object->Object->Type->Destructor( Object->Object );
37                         break;
38                 case SS_DATATYPE_OPAQUE:
39                         Object->Opaque.Destroy( Object->Opaque.Data );
40                         break;
41                 default:
42                         break;
43                 }
44                 free(Object);
45         }
46 }
47
48 void Object_Reference(tSpiderValue *Object)
49 {
50         if(!Object)     return ;
51         Object->ReferenceCount ++;
52 }
53
54 /**
55  * \brief Create an integer object
56  */
57 tSpiderValue *Object_CreateInteger(uint64_t Value)
58 {
59         tSpiderValue    *ret = malloc( sizeof(tSpiderValue) );
60         ret->Type = SS_DATATYPE_INTEGER;
61         ret->ReferenceCount = 1;
62         ret->Integer = Value;
63         return ret;
64 }
65
66 /**
67  * \brief Create an real number object
68  */
69 tSpiderValue *Object_CreateReal(double Value)
70 {
71         tSpiderValue    *ret = malloc( sizeof(tSpiderValue) );
72         ret->Type = SS_DATATYPE_REAL;
73         ret->ReferenceCount = 1;
74         ret->Real = Value;
75         return ret;
76 }
77
78 /**
79  * \brief Create an string object
80  */
81 tSpiderValue *Object_CreateString(int Length, const char *Data)
82 {
83         tSpiderValue    *ret = malloc( sizeof(tSpiderValue) + Length + 1 );
84         ret->Type = SS_DATATYPE_STRING;
85         ret->ReferenceCount = 1;
86         ret->String.Length = Length;
87         memcpy(ret->String.Data, Data, Length);
88         ret->String.Data[Length] = '\0';
89         return ret;
90 }
91
92 /**
93  * \brief Concatenate two strings
94  */
95 tSpiderValue *Object_StringConcat(tSpiderValue *Str1, tSpiderValue *Str2)
96 {
97          int    newLen = 0;
98         tSpiderValue    *ret;
99         if(Str1)        newLen += Str1->String.Length;
100         if(Str2)        newLen += Str2->String.Length;
101         ret = malloc( sizeof(tSpiderValue) + newLen + 1 );
102         ret->Type = SS_DATATYPE_STRING;
103         ret->ReferenceCount = 1;
104         ret->String.Length = newLen;
105         if(Str1)
106                 memcpy(ret->String.Data, Str1->String.Data, Str1->String.Length);
107         if(Str2) {
108                 if(Str1)
109                         memcpy(ret->String.Data+Str1->String.Length, Str2->String.Data, Str2->String.Length);
110                 else
111                         memcpy(ret->String.Data, Str2->String.Data, Str2->String.Length);
112         }
113         ret->String.Data[ newLen ] = '\0';
114         return ret;
115 }
116
117 /**
118  * \brief Cast one object to another
119  * \brief Type  Destination type
120  * \brief Source        Input data
121  */
122 tSpiderValue *Object_CastTo(int Type, tSpiderValue *Source)
123 {
124         tSpiderValue    *ret = ERRPTR;
125         // Check if anything needs to be done
126         if( Source->Type == Type ) {
127                 Object_Reference(Source);
128                 return Source;
129         }
130         
131         switch( (enum eSpiderScript_DataTypes)Type )
132         {
133         case SS_DATATYPE_UNDEF:
134         case SS_DATATYPE_NULL:
135         case SS_DATATYPE_ARRAY:
136         case SS_DATATYPE_OPAQUE:
137                 fprintf(stderr, "Object_CastTo - Invalid cast to %i\n", Type);
138                 return ERRPTR;
139         
140         case SS_DATATYPE_INTEGER:
141                 ret = malloc(sizeof(tSpiderValue));
142                 ret->Type = SS_DATATYPE_INTEGER;
143                 ret->ReferenceCount = 1;
144                 switch(Source->Type)
145                 {
146                 case SS_DATATYPE_INTEGER:       break;  // Handled above
147                 case SS_DATATYPE_STRING:        ret->Integer = atoi(Source->String.Data);       break;
148                 case SS_DATATYPE_REAL:  ret->Integer = Source->Real;    break;
149                 default:
150                         fprintf(stderr, "Object_CastTo - Invalid cast from %i\n", Source->Type);
151                         free(ret);
152                         ret = ERRPTR;
153                         break;
154                 }
155                 break;
156         default:
157                 fprintf(stderr, "BUG REPORT: Unimplemented cast target\n");
158                 break;
159         }
160         
161         return ret;
162 }
163
164 /**
165  * \brief Condenses a value down to a boolean
166  */
167 int Object_IsTrue(tSpiderValue *Value)
168 {
169         if( Value == ERRPTR )   return 0;
170         if( Value == NULL )     return 0;
171         
172         switch( (enum eSpiderScript_DataTypes)Value->Type )
173         {
174         case SS_DATATYPE_UNDEF:
175         case SS_DATATYPE_NULL:
176                 return 0;
177         
178         case SS_DATATYPE_INTEGER:
179                 return !!Value->Integer;
180         
181         case SS_DATATYPE_REAL:
182                 return (-.5f < Value->Real && Value->Real < 0.5f);
183         
184         case SS_DATATYPE_STRING:
185                 return Value->String.Length > 0;
186         
187         case SS_DATATYPE_OBJECT:
188                 return Value->Object != NULL;
189         
190         case SS_DATATYPE_OPAQUE:
191                 return Value->Opaque.Data != NULL;
192         
193         case SS_DATATYPE_ARRAY:
194                 return Value->Array.Length > 0;
195         default:
196                 fprintf(stderr, "Spiderscript internal error: Unknown type %i in Object_IsTrue\n", Value->Type);
197                 return 0;
198         }
199         return 0;
200 }
201
202 /**
203  * \brief Execute an AST node and return its value
204  */
205 tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node)
206 {
207         tAST_Node       *node;
208         tSpiderValue    *ret = NULL, *tmpobj;
209         tSpiderValue    *op1, *op2;     // Binary operations
210          int    cmp;    // Used in comparisons
211         
212         switch(Node->Type)
213         {
214         // No Operation
215         case NODETYPE_NOP:      ret = NULL;     break;
216         
217         // Code block
218         case NODETYPE_BLOCK:
219                 {
220                         tAST_BlockState blockInfo;
221                         blockInfo.FirstVar = NULL;
222                         blockInfo.RetVal = NULL;
223                         blockInfo.Parent = Block;
224                         blockInfo.Script = Block->Script;
225                         ret = NULL;
226                         for(node = Node->Block.FirstChild; node && !blockInfo.RetVal; node = node->NextSibling )
227                         {
228                                 tmpobj = AST_ExecuteNode(&blockInfo, node);
229                                 if(tmpobj == ERRPTR) {  // Error check
230                                         ret = ERRPTR;
231                                         break ;
232                                 }
233                                 if(tmpobj)      Object_Dereference(tmpobj);     // Free unused value
234                         }
235                         // Clean up variables
236                         while(blockInfo.FirstVar)
237                         {
238                                 tAST_Variable   *nextVar = blockInfo.FirstVar->Next;
239                                 Variable_Destroy( blockInfo.FirstVar );
240                                 blockInfo.FirstVar = nextVar;
241                         }
242                         
243                         if( blockInfo.RetVal )
244                                 Block->RetVal = blockInfo.RetVal;
245                 }
246                 
247                 break;
248         
249         // Assignment
250         case NODETYPE_ASSIGN:
251                 if( Node->Assign.Dest->Type != NODETYPE_VARIABLE ) {
252                         fprintf(stderr, "Syntax error: LVALUE of assignment is not a variable\n");
253                         return ERRPTR;
254                 }
255                 ret = AST_ExecuteNode(Block, Node->Assign.Value);
256                 if(ret != ERRPTR)
257                         Variable_SetValue( Block, Node->Assign.Dest->Variable.Name, ret );
258                 break;
259         
260         // Function Call
261         case NODETYPE_FUNCTIONCALL:
262                 {
263                          int    nParams = 0;
264                         for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) {
265                                 nParams ++;
266                         }
267                         // Logical block (used to allocate `params`)
268                         {
269                                 tSpiderValue    *params[nParams];
270                                  int    i=0;
271                                 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) {
272                                         params[i] = AST_ExecuteNode(Block, node);
273                                         if( params[i] == ERRPTR ) {
274                                                 while(i--)      Object_Dereference(params[i]);
275                                                 ret = ERRPTR;
276                                                 goto _return;
277                                         }
278                                         i ++;
279                                 }
280                                 
281                                 // Call the function (SpiderScript_ExecuteMethod does the
282                                 // required namespace handling)
283                                 ret = SpiderScript_ExecuteMethod(Block->Script, Node->FunctionCall.Name, nParams, params);
284                                 
285                                 // Dereference parameters
286                                 while(i--)      Object_Dereference(params[i]);
287                                 
288                                 // falls out
289                         }
290                 }
291                 break;
292         
293         // Conditional
294         case NODETYPE_IF:
295                 ret = AST_ExecuteNode(Block, Node->If.Condition);
296                 if( Object_IsTrue(ret) ) {
297                         AST_ExecuteNode(Block, Node->If.True);
298                 }
299                 else {
300                         AST_ExecuteNode(Block, Node->If.False);
301                 }
302                 Object_Dereference(ret);
303                 break;
304         
305         // Loop
306         case NODETYPE_LOOP:
307                 ret = AST_ExecuteNode(Block, Node->For.Init);
308                 if( Node->For.bCheckAfter ) {
309                         do {
310                                 Object_Dereference(ret);
311                                 ret = AST_ExecuteNode(Block, Node->For.Code);
312                                 Object_Dereference(ret);
313                                 ret = AST_ExecuteNode(Block, Node->For.Condition);
314                         } while( Object_IsTrue(ret) );
315                 }
316                 else {
317                         Object_Dereference(ret);
318                         ret = AST_ExecuteNode(Block, Node->For.Condition);
319                         while( Object_IsTrue(ret) ) {
320                                 Object_Dereference(ret);
321                                 ret = AST_ExecuteNode(Block, Node->For.Code);
322                                 Object_Dereference(ret);
323                                 ret = AST_ExecuteNode(Block, Node->For.Condition);
324                         }
325                         Object_Dereference(ret);
326                 }
327                 break;
328         
329         // Return
330         case NODETYPE_RETURN:
331                 ret = AST_ExecuteNode(Block, Node->UniOp.Value);
332                 Block->RetVal = ret;    // Return value set
333                 break;
334         
335         // Define a variable
336         case NODETYPE_DEFVAR:
337                 ret = NULL;
338                 if( Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name) == ERRPTR )
339                         ret = ERRPTR;
340                 break;
341         
342         // Variable
343         case NODETYPE_VARIABLE:
344                 ret = Variable_GetValue( Block, Node->Variable.Name );
345                 break;
346
347         // Cast a value to another
348         case NODETYPE_CAST:
349                 ret = Object_CastTo(
350                         Node->Cast.DataType,
351                         AST_ExecuteNode(Block, Node->Cast.Value)
352                         );
353                 break;
354
355         // Index into an array
356         case NODETYPE_INDEX:
357                 fprintf(stderr, "TODO: Array indexing\n");
358                 ret = ERRPTR;
359                 break;
360
361         // TODO: Implement runtime constants
362         case NODETYPE_CONSTANT:
363                 fprintf(stderr, "TODO: Runtime Constants\n");
364                 ret = ERRPTR;
365                 break;
366         // Constant Values
367         case NODETYPE_STRING:   ret = Object_CreateString( Node->String.Length, Node->String.Data );    break;
368         case NODETYPE_INTEGER:  ret = Object_CreateInteger( Node->Integer );    break;
369         case NODETYPE_REAL:     ret = Object_CreateReal( Node->Real );  break;
370         
371         // --- Operations ---
372         // Boolean Operations
373         case NODETYPE_LOGICALAND:       // Logical AND (&&)
374         case NODETYPE_LOGICALOR:        // Logical OR (||)
375         case NODETYPE_LOGICALXOR:       // Logical XOR (^^)
376                 op1 = AST_ExecuteNode(Block, Node->BinOp.Left);
377                 if(op1 == ERRPTR)       return ERRPTR;
378                 op2 = AST_ExecuteNode(Block, Node->BinOp.Right);
379                 if(op2 == ERRPTR) {
380                         Object_Dereference(op1);
381                         return ERRPTR;
382                 }
383                 
384                 switch( Node->Type )
385                 {
386                 case NODETYPE_LOGICALAND:
387                         ret = Object_CreateInteger( Object_IsTrue(op1) && Object_IsTrue(op2) );
388                         break;
389                 case NODETYPE_LOGICALOR:
390                         ret = Object_CreateInteger( Object_IsTrue(op1) || Object_IsTrue(op2) );
391                         break;
392                 case NODETYPE_LOGICALXOR:
393                         ret = Object_CreateInteger( Object_IsTrue(op1) ^ Object_IsTrue(op2) );
394                         break;
395                 default:        break;
396                 }
397                 
398                 // Free intermediate objects
399                 Object_Dereference(op1);
400                 Object_Dereference(op2);
401                 break;
402         
403         // Comparisons
404         case NODETYPE_EQUALS:
405         case NODETYPE_LESSTHAN:
406         case NODETYPE_GREATERTHAN:
407                 op1 = AST_ExecuteNode(Block, Node->BinOp.Left);
408                 if(op1 == ERRPTR)       return ERRPTR;
409                 op2 = AST_ExecuteNode(Block, Node->BinOp.Right);
410                 if(op2 == ERRPTR) {
411                         Object_Dereference(op1);
412                         return ERRPTR;
413                 }
414                 
415                 // No conversion done for NULL
416                 // TODO: Determine if this will ever be needed
417                 if( op1->Type == SS_DATATYPE_NULL )
418                 {
419                         // NULLs always typecheck
420                         ret = Object_CreateInteger(op2->Type == SS_DATATYPE_NULL);
421                         break;
422                 }
423                 
424                 // Convert types
425                 if( op1->Type != op2->Type ) {
426                         // If dynamically typed, convert op2 to op1's type
427                         if(Block->Script->Variant->bDyamicTyped)
428                         {
429                                 tmpobj = op2;
430                                 op2 = Object_CastTo(op1->Type, op2);
431                                 Object_Dereference(tmpobj);
432                                 if(op2 == ERRPTR) {
433                                         Object_Dereference(op1);
434                                         return ERRPTR;
435                                 }
436                         }
437                         // If statically typed, this should never happen, but catch it anyway
438                         else {
439                                 fprintf(stderr, "PARSER ERROR: Statically typed implicit cast\n");
440                                 ret = ERRPTR;
441                                 break;
442                         }
443                 }
444                 // Do operation
445                 switch(op1->Type)
446                 {
447                 // - NULL
448                 case SS_DATATYPE_NULL:  break;
449                 // - String Compare (does a strcmp, well memcmp)
450                 case SS_DATATYPE_STRING:
451                         // Call memcmp to do most of the work
452                         cmp = memcmp(
453                                 op1->String.Data, op2->String.Data,
454                                 (op1->String.Length < op2->String.Length) ? op1->String.Length : op2->String.Length
455                                 );
456                         // Handle reaching the end of the string
457                         if( cmp == 0 ) {
458                                 if( op1->String.Length == op2->String.Length )
459                                         cmp = 0;
460                                 else if( op1->String.Length < op2->String.Length )
461                                         cmp = 1;
462                                 else
463                                         cmp = -1;
464                         }
465                         break;
466                 default:
467                         fprintf(stderr, "SpiderScript internal error: TODO: Comparison of type %i\n", op1->Type);
468                         ret = ERRPTR;
469                         break;
470                 }
471                 
472                 // Free intermediate objects
473                 Object_Dereference(op1);
474                 Object_Dereference(op2);
475                 
476                 // Error check
477                 if( ret == ERRPTR )
478                         break;
479                 
480                 // Create return
481                 switch(Node->Type)
482                 {
483                 case NODETYPE_EQUALS:   ret = Object_CreateInteger(cmp == 0);   break;
484                 case NODETYPE_LESSTHAN: ret = Object_CreateInteger(cmp < 0);    break;
485                 case NODETYPE_GREATERTHAN:      ret = Object_CreateInteger(cmp > 0);    break;
486                 default:
487                         fprintf(stderr, "SpiderScript internal error: Exec,CmpOp unknown op %i", Node->Type);
488                         ret = ERRPTR;
489                         break;
490                 }
491                 break;
492         
493         // General Binary Operations
494         case NODETYPE_ADD:
495         case NODETYPE_SUBTRACT:
496         case NODETYPE_MULTIPLY:
497         case NODETYPE_DIVIDE:
498         case NODETYPE_MODULO:
499         case NODETYPE_BWAND:
500         case NODETYPE_BWOR:
501         case NODETYPE_BWXOR:
502         case NODETYPE_BITSHIFTLEFT:
503         case NODETYPE_BITSHIFTRIGHT:
504         case NODETYPE_BITROTATELEFT:
505                 // Get operands
506                 op1 = AST_ExecuteNode(Block, Node->BinOp.Left);
507                 if(op1 == ERRPTR)       return ERRPTR;
508                 op2 = AST_ExecuteNode(Block, Node->BinOp.Right);
509                 if(op2 == ERRPTR) {
510                         Object_Dereference(op1);
511                         return ERRPTR;
512                 }
513                 
514                 // Convert types
515                 if( op1 && op2 && op1->Type != op2->Type ) {
516                         // If dynamically typed, convert op2 to op1's type
517                         if(Block->Script->Variant->bDyamicTyped)
518                         {
519                                 tmpobj = op2;
520                                 op2 = Object_CastTo(op1->Type, op2);
521                                 Object_Dereference(tmpobj);
522                                 if(op2 == ERRPTR) {
523                                         Object_Dereference(op1);
524                                         return ERRPTR;
525                                 }
526                         }
527                         // If statically typed, this should never happen, but catch it anyway
528                         else {
529                                 fprintf(stderr, "PARSER ERROR: Statically typed implicit cast\n");
530                                 ret = ERRPTR;
531                                 break;
532                         }
533                 }
534                 
535                 // Do operation
536                 switch(op1->Type)
537                 {
538                 case SS_DATATYPE_NULL:  break;
539                 // String Concatenation
540                 case SS_DATATYPE_STRING:
541                         switch(Node->Type)
542                         {
543                         case NODETYPE_ADD:      // Concatenate
544                                 ret = Object_StringConcat(op1, op2);
545                                 break;
546                         default:
547                                 fprintf(stderr, "SpiderScript internal error: Exec,BinOP,String unknown op %i\n", Node->Type);
548                                 ret = ERRPTR;
549                                 break;
550                         }
551                         break;
552                 // Integer Operations
553                 case SS_DATATYPE_INTEGER:
554                         switch(Node->Type)
555                         {
556                         case NODETYPE_ADD:      ret = Object_CreateInteger( op1->Integer + op2->Integer );      break;
557                         case NODETYPE_SUBTRACT: ret = Object_CreateInteger( op1->Integer - op2->Integer );      break;
558                         case NODETYPE_MULTIPLY: ret = Object_CreateInteger( op1->Integer * op2->Integer );      break;
559                         case NODETYPE_DIVIDE:   ret = Object_CreateInteger( op1->Integer / op2->Integer );      break;
560                         case NODETYPE_MODULO:   ret = Object_CreateInteger( op1->Integer % op2->Integer );      break;
561                         case NODETYPE_BWAND:    ret = Object_CreateInteger( op1->Integer & op2->Integer );      break;
562                         case NODETYPE_BWOR:     ret = Object_CreateInteger( op1->Integer | op2->Integer );      break;
563                         case NODETYPE_BWXOR:    ret = Object_CreateInteger( op1->Integer ^ op2->Integer );      break;
564                         case NODETYPE_BITSHIFTLEFT:     ret = Object_CreateInteger( op1->Integer << op2->Integer );     break;
565                         case NODETYPE_BITSHIFTRIGHT:ret = Object_CreateInteger( op1->Integer >> op2->Integer ); break;
566                         case NODETYPE_BITROTATELEFT:
567                                 ret = Object_CreateInteger( (op1->Integer << op2->Integer) | (op1->Integer >> (64-op2->Integer)) );
568                                 break;
569                         default:
570                                 fprintf(stderr, "SpiderScript internal error: Exec,BinOP,Integer unknown op %i\n", Node->Type);
571                                 ret = ERRPTR;
572                                 break;
573                         }
574                         break;
575                 
576                 // Real Numbers
577                 case SS_DATATYPE_REAL:
578                         switch(Node->Type)
579                         {
580                         default:
581                                 fprintf(stderr, "SpiderScript internal error: Exec,BinOP,Real unknown op %i\n", Node->Type);
582                                 ret = ERRPTR;
583                                 break;
584                         }
585                         break;
586                 
587                 default:
588                         fprintf(stderr, "SpiderScript error: Invalid operation (%i) on type (%i)\n", Node->Type, op1->Type);
589                         ret = ERRPTR;
590                         break;
591                 }
592                 
593                 // Free intermediate objects
594                 Object_Dereference(op1);
595                 Object_Dereference(op2);
596                 break;
597         
598         //default:
599         //      ret = NULL;
600         //      fprintf(stderr, "ERROR: SpiderScript AST_ExecuteNode Unimplemented %i\n", Node->Type);
601         //      break;
602         }
603 _return:
604         return ret;
605 }
606
607 /**
608  * \brief Define a variable
609  * \param Block Current block state
610  * \param Type  Type of the variable
611  * \param Name  Name of the variable
612  * \return Boolean Failure
613  */
614 tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name)
615 {
616         tAST_Variable   *var, *prev = NULL;
617         
618         for( var = Block->FirstVar; var; prev = var, var = var->Next )
619         {
620                 if( strcmp(var->Name, Name) == 0 ) {
621                         fprintf(stderr, "ERROR: Redefinition of variable '%s'\n", Name);
622                         return ERRPTR;
623                 }
624         }
625         
626         var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 );
627         var->Next = NULL;
628         var->Type = Type;
629         var->Object = NULL;
630         strcpy(var->Name, Name);
631         
632         if(prev)        prev->Next = var;
633         else    Block->FirstVar = var;
634         
635         //printf("Defined variable %s (%i)\n", Name, Type);
636         
637         return var;
638 }
639
640 /**
641  * \brief Set the value of a variable
642  */
643 void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value)
644 {
645         tAST_Variable   *var;
646         tAST_BlockState *bs;
647         
648         for( bs = Block; bs; bs = bs->Parent )
649         {
650                 for( var = bs->FirstVar; var; var = var->Next )
651                 {
652                         if( strcmp(var->Name, Name) == 0 ) {
653                                 if( !Block->Script->Variant->bDyamicTyped
654                                  && (Value && var->Type != Value->Type) ) {
655                                         fprintf(stderr, "ERROR: Type mismatch assigning to '%s'\n", Name);
656                                         return ;
657                                 }
658                                 Object_Reference(Value);
659                                 Object_Dereference(var->Object);
660                                 var->Object = Value;
661                                 return ;
662                         }
663                 }
664         }
665         
666         if( Block->Script->Variant->bDyamicTyped )
667         {
668                 // Define variable
669                 var = Variable_Define(Block, Value->Type, Name);
670                 Object_Reference(Value);
671                 var->Object = Value;
672         }
673         else
674         {
675                 fprintf(stderr, "ERROR: Variable '%s' set while undefined\n", Name);
676         }
677 }
678
679 /**
680  * \brief Get the value of a variable
681  */
682 tSpiderValue *Variable_GetValue(tAST_BlockState *Block, const char *Name)
683 {
684         tAST_Variable   *var;
685         tAST_BlockState *bs;
686         
687         for( bs = Block; bs; bs = bs->Parent )
688         {
689                 for( var = bs->FirstVar; var; var = var->Next )
690                 {
691                         if( strcmp(var->Name, Name) == 0 ) {
692                                 Object_Reference(var->Object);
693                                 return var->Object;
694                         }
695                 }
696         }
697         
698         fprintf(stderr, "ERROR: Variable '%s' used undefined\n", Name);
699         
700         return ERRPTR;
701 }
702
703 /**
704  * \brief Destorys a variable
705  */
706 void Variable_Destroy(tAST_Variable *Variable)
707 {
708         Object_Dereference(Variable->Object);
709         free(Variable);
710 }

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