SpiderScript - Fixes, SpiderWeb's print_test.sw works
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / ast_to_bytecode.c
1 /*
2  * SpiderScript Library
3  *
4  * AST to Bytecode Conversion
5  */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include "common.h"
11 #include "ast.h"
12 #include "bytecode_gen.h"
13 #include "bytecode_ops.h"
14
15 #define TRACE_VAR_LOOKUPS       0
16 #define TRACE_NODE_RETURNS      0
17 #define MAX_NAMESPACE_DEPTH     10
18
19 // === IMPORTS ===
20 extern tSpiderFunction  *gpExports_First;
21
22 // === TYPES ===
23 typedef struct sAST_BlockInfo
24 {
25         struct sAST_BlockInfo   *Parent;
26         void    *Handle;
27         const char      *Tag;
28
29          int    BreakTarget;
30          int    ContinueTarget;
31         
32         const char      *CurNamespaceStack[MAX_NAMESPACE_DEPTH];
33 } tAST_BlockInfo;
34
35 // === PROTOTYPES ===
36 // Node Traversal
37  int    AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue);
38 // Variables
39  int    BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name);
40  int    BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
41  int    BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
42 // - Errors
43 void    AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...);
44 void    AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
45
46 // === GLOBALS ===
47 // int  giNextBlockIdent = 1;
48
49 // === CODE ===
50 int SpiderScript_BytecodeScript(tSpiderScript *Script)
51 {
52         tScript_Function        *fcn;
53         for(fcn = Script->Functions; fcn; fcn = fcn->Next)
54         {
55                 if( Bytecode_ConvertFunction(fcn) == 0 )
56                         return -1;
57         }
58         return 0;
59 }
60
61 /**
62  * \brief Convert a function into bytecode
63  */
64 tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn)
65 {
66         tBC_Function    *ret;
67         tAST_BlockInfo bi = {0};
68
69         // TODO: Return BCFcn instead?
70         if(Fcn->BCFcn)  return Fcn->BCFcn;
71         
72         ret = Bytecode_CreateFunction(Fcn);
73         if(!ret)        return NULL;
74         
75         bi.Handle = ret;
76         if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) )
77         {
78                 Bytecode_DeleteFunction(ret);
79                 return NULL;
80         }
81
82         Bytecode_AppendConstInt(ret, 0);        // TODO: NULL
83         Bytecode_AppendReturn(ret);
84         Fcn->BCFcn = ret;
85
86         return ret;
87 }
88
89 // Indepotent operation
90 #define CHECK_IF_NEEDED(b_warn) do { if(!bKeepValue) {\
91         if(b_warn)AST_RuntimeMessage(Node, "Bytecode", "Operation without saving");\
92         Bytecode_AppendDelete(Block->Handle);\
93 } } while(0)
94
95 /**
96  * \brief Convert a node into bytecode
97  * \param Block Execution context
98  * \param Node  Node to execute
99  */
100 int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
101 {
102         tAST_Node       *node;
103          int    ret = 0;
104          int    i, op = 0;
105          int    bAddedValue = 1;        // Used to tell if the value needs to be deleted
106         
107         switch(Node->Type)
108         {
109         // No Operation
110         case NODETYPE_NOP:
111                 bAddedValue = 0;
112                 break;
113         
114         // Code block
115         case NODETYPE_BLOCK:
116                 Bytecode_AppendEnterContext(Block->Handle);     // Create a new block
117                 {
118                         tAST_BlockInfo  blockInfo = {0};
119                         blockInfo.Parent = Block;
120                         blockInfo.Handle = Block->Handle;
121                         // Loop over all nodes, or until the return value is set
122                         for(node = Node->Block.FirstChild;
123                                 node;
124                                 node = node->NextSibling )
125                         {
126                                 AST_ConvertNode(Block, node, 0);
127                         }
128                 }
129                 Bytecode_AppendLeaveContext(Block->Handle);     // Leave this context
130                 break;
131         
132         // Assignment
133         case NODETYPE_ASSIGN:
134                 // TODO: Support assigning to object attributes
135                 if( Node->Assign.Dest->Type != NODETYPE_VARIABLE ) {
136                         AST_RuntimeError(Node, "LVALUE of assignment is not a variable");
137                         return -1;
138                 }
139                 
140                 // Perform assignment operation
141                 if( Node->Assign.Operation != NODETYPE_NOP )
142                 {
143                         
144                         ret = BC_Variable_GetValue(Block, Node->Assign.Dest);
145                         if(ret) return ret;
146                         ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
147                         if(ret) return ret;
148                         switch(Node->Assign.Operation)
149                         {
150                         // General Binary Operations
151                         case NODETYPE_ADD:      op = BC_OP_ADD; break;
152                         case NODETYPE_SUBTRACT: op = BC_OP_SUBTRACT;    break;
153                         case NODETYPE_MULTIPLY: op = BC_OP_MULTIPLY;    break;
154                         case NODETYPE_DIVIDE:   op = BC_OP_DIVIDE;      break;
155                         case NODETYPE_MODULO:   op = BC_OP_MODULO;      break;
156                         case NODETYPE_BWAND:    op = BC_OP_BITAND;      break;
157                         case NODETYPE_BWOR:     op = BC_OP_BITOR;       break;
158                         case NODETYPE_BWXOR:    op = BC_OP_BITXOR;      break;
159                         case NODETYPE_BITSHIFTLEFT:     op = BC_OP_BITSHIFTLEFT;        break;
160                         case NODETYPE_BITSHIFTRIGHT:    op = BC_OP_BITSHIFTRIGHT;       break;
161                         case NODETYPE_BITROTATELEFT:    op = BC_OP_BITROTATELEFT;       break;
162
163                         default:
164                                 AST_RuntimeError(Node, "Unknown operation in ASSIGN %i", Node->Assign.Operation);
165                                 break;
166                         }
167                         printf("assign, op = %i\n", op);
168                         Bytecode_AppendBinOp(Block->Handle, op);
169                 }
170                 else
171                 {
172                         ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
173                         if(ret) return ret;
174                 }
175                 
176                 if( bKeepValue )
177                         Bytecode_AppendDuplicate(Block->Handle);
178                 // Set the variable value
179                 ret = BC_Variable_SetValue( Block, Node->Assign.Dest );
180                 break;
181         
182         // Post increment/decrement
183         case NODETYPE_POSTINC:
184         case NODETYPE_POSTDEC:
185                 // TODO: Support assigning to object attributes
186                 if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) {
187                         AST_RuntimeError(Node, "LVALUE of assignment is not a variable");
188                         return -1;
189                 }
190
191                 // Save original value if requested
192                 if(bKeepValue) {
193                         ret = BC_Variable_GetValue(Block, Node->UniOp.Value);
194                         if(ret) return ret;
195                 }
196                 
197                 Bytecode_AppendConstInt(Block->Handle, 1);
198                 
199                 ret = BC_Variable_GetValue(Block, Node->UniOp.Value);
200                 if(ret) return ret;
201
202                 if( Node->Type == NODETYPE_POSTDEC )
203                         Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT);
204                 else
205                         Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD);
206                 if(ret) return ret;
207
208
209                 ret = BC_Variable_SetValue(Block, Node->UniOp.Value);
210                 if(ret) return ret;
211                 // Doesn't push unless needed
212                 break;
213         
214         // Function Call
215         case NODETYPE_METHODCALL:
216         case NODETYPE_FUNCTIONCALL:
217         case NODETYPE_CREATEOBJECT: {
218                  int    nargs = 0;
219
220                 // Put the object earlier on the stack to the arguments (for exec)
221                 if( Node->Type == NODETYPE_METHODCALL ) {
222                         ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1);
223                         if(ret) return ret;
224                 }               
225
226                 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
227                 {
228                         ret = AST_ConvertNode(Block, node, 1);
229                         if(ret) return ret;
230                         nargs ++;
231                 }
232                 
233                 // Call the function
234                 if( Node->Type == NODETYPE_METHODCALL )
235                 {
236                         // TODO: Sanity check stack top
237                         Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs);
238                 }
239                 else
240                 {
241                          int    newnamelen = 0;
242                         char    *manglename;
243                         for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ )
244                                 newnamelen = strlen(Block->CurNamespaceStack[i]) + 1;
245                         newnamelen += strlen(Node->FunctionCall.Name) + 1;
246                         manglename = alloca(newnamelen);
247                         manglename[0] = 0;
248                         for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ) {
249                                  int    pos;
250                                 strcat(manglename, Block->CurNamespaceStack[i]);
251                                 pos = strlen(manglename);
252                                 manglename[pos] = BC_NS_SEPARATOR;
253                                 manglename[pos+1] = '\0';
254                         }
255                         strcat(manglename, Node->FunctionCall.Name);
256                                 
257                         if( Node->Type == NODETYPE_CREATEOBJECT )
258                         {
259                                 // TODO: Sanity check stack top
260                                 Bytecode_AppendCreateObj(Block->Handle, manglename, nargs);
261                         }
262                         else
263                         {
264                                 Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs);
265                         }
266                 }
267                 CHECK_IF_NEEDED(0);     // Don't warn
268                 // TODO: Implement warn_unused_ret
269                 } break;
270         
271         // Conditional
272         case NODETYPE_IF: {
273                  int    if_end;
274                 ret = AST_ConvertNode(Block, Node->If.Condition, 1);
275                 if(ret) return ret;
276                 
277                 if_end = Bytecode_AllocateLabel(Block->Handle);
278
279                 if( Node->If.False->Type != NODETYPE_NOP )
280                 {
281                          int    if_true = Bytecode_AllocateLabel(Block->Handle);
282                         
283                         Bytecode_AppendCondJump(Block->Handle, if_true);
284         
285                         // False
286                         ret = AST_ConvertNode(Block, Node->If.False, 0);
287                         if(ret) return ret;
288                         Bytecode_AppendJump(Block->Handle, if_end);
289                         Bytecode_SetLabel(Block->Handle, if_true);
290                 }
291                 else
292                 {
293                         Bytecode_AppendCondJumpNot(Block->Handle, if_end);
294                 }
295                 
296                 // True
297                 ret = AST_ConvertNode(Block, Node->If.True, 0);
298                 if(ret) return ret;
299
300                 // End
301                 Bytecode_SetLabel(Block->Handle, if_end);
302                 } break;
303         
304         // Loop
305         case NODETYPE_LOOP: {
306                  int    loop_start, loop_end;
307                  int    saved_break, saved_continue;
308                 const char      *saved_tag;
309
310                 // Initialise
311                 ret = AST_ConvertNode(Block, Node->For.Init, 0);
312                 if(ret) return ret;
313                 
314                 loop_start = Bytecode_AllocateLabel(Block->Handle);
315                 loop_end = Bytecode_AllocateLabel(Block->Handle);
316
317                 saved_break = Block->BreakTarget;
318                 saved_continue = Block->ContinueTarget;
319                 saved_tag = Block->Tag;
320                 Block->BreakTarget = loop_end;
321                 Block->ContinueTarget = loop_end;
322                 Block->Tag = Node->For.Tag;
323
324                 Bytecode_SetLabel(Block->Handle, loop_start);
325
326                 // Check initial condition
327                 if( !Node->For.bCheckAfter )
328                 {
329                         ret = AST_ConvertNode(Block, Node->For.Condition, 1);
330                         if(ret) return ret;
331                         Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT);
332                         Bytecode_AppendCondJump(Block->Handle, loop_end);
333                 }
334         
335                 // Code
336                 ret = AST_ConvertNode(Block, Node->For.Code, 0);
337                 if(ret) return ret;
338                 
339                 // Increment
340                 ret = AST_ConvertNode(Block, Node->For.Increment, 0);
341                 if(ret) return ret;
342
343                 // Tail check
344                 if( Node->For.bCheckAfter )
345                 {
346                         ret = AST_ConvertNode(Block, Node->For.Condition, 1);
347                         if(ret) return ret;
348                         Bytecode_AppendCondJump(Block->Handle, loop_start);
349                 }
350                 else
351                 {
352                         Bytecode_AppendJump(Block->Handle, loop_start);
353                 }
354
355                 Bytecode_SetLabel(Block->Handle, loop_end);
356
357                 Block->BreakTarget = saved_break;
358                 Block->ContinueTarget = saved_continue;
359                 Block->Tag = saved_tag;
360                 } break;
361         
362         // Return
363         case NODETYPE_RETURN:
364                 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
365                 if(ret) return ret;
366                 Bytecode_AppendReturn(Block->Handle);
367                 break;
368         
369         case NODETYPE_BREAK:
370         case NODETYPE_CONTINUE: {
371                 tAST_BlockInfo  *bi = Block;
372                 if( Node->Variable.Name[0] ) {
373                         while(bi && strcmp(bi->Tag, Node->Variable.Name) == 0)  bi = bi->Parent;
374                 }
375                 if( !bi )       return 1;
376                 // TODO: Check if BreakTarget/ContinueTarget are valid
377                 if( Node->Type == NODETYPE_BREAK )
378                         Bytecode_AppendJump(Block->Handle, bi->BreakTarget);
379                 else
380                         Bytecode_AppendJump(Block->Handle, bi->ContinueTarget);
381                 } break;
382         
383         // Define a variable
384         case NODETYPE_DEFVAR:
385                 ret = BC_Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name);
386                 if(ret) return ret;
387                 
388                 if( Node->DefVar.InitialValue )
389                 {
390                         ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1);
391                         if(ret) return ret;
392                         Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name);
393                 }
394                 break;
395         
396         // Scope
397         case NODETYPE_SCOPE:
398                 for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ );
399                 if( i == MAX_NAMESPACE_DEPTH ) {
400                         AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", i);
401                         return 2;
402                 }
403                 Block->CurNamespaceStack[i] = Node->Scope.Name;
404                 ret = AST_ConvertNode(Block, Node->Scope.Element, 2);
405                 Block->CurNamespaceStack[i] = NULL;
406                 CHECK_IF_NEEDED(0);     // No warning?
407                 // TODO: Will this collide with _CALLFUNCTION etc?
408                 break;
409         
410         // Variable
411         case NODETYPE_VARIABLE:
412                 ret = BC_Variable_GetValue( Block, Node );
413                 CHECK_IF_NEEDED(1);
414                 break;
415         
416         // Element of an Object
417         case NODETYPE_ELEMENT:
418                 ret = AST_ConvertNode( Block, Node->Scope.Element, 1 );
419                 if(ret) return ret;
420
421                 Bytecode_AppendElement(Block->Handle, Node->Scope.Name);
422                 CHECK_IF_NEEDED(1);
423                 break;
424
425         // Cast a value to another
426         case NODETYPE_CAST:
427                 ret = AST_ConvertNode(Block, Node->Cast.Value, 1);
428                 if(ret) return ret;
429                 Bytecode_AppendCast(Block->Handle, Node->Cast.DataType);
430                 CHECK_IF_NEEDED(1);
431                 break;
432
433         // Index into an array
434         case NODETYPE_INDEX:
435                 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1);      // Array
436                 if(ret) return ret;
437                 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1);     // Offset
438                 if(ret) return ret;
439                 
440                 Bytecode_AppendIndex(Block->Handle);
441                 CHECK_IF_NEEDED(1);
442                 break;
443
444         // TODO: Implement runtime constants
445         case NODETYPE_CONSTANT:
446                 // TODO: Scan namespace for constant name
447                 AST_RuntimeError(Node, "TODO - Runtime Constants");
448                 ret = -1;
449                 break;
450         
451         // Constant Values
452         case NODETYPE_STRING:
453                 Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length);
454                 CHECK_IF_NEEDED(1);
455                 break;
456         case NODETYPE_INTEGER:
457                 Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer);
458                 CHECK_IF_NEEDED(1);
459                 break;
460         case NODETYPE_REAL:
461                 Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real);
462                 CHECK_IF_NEEDED(1);
463                 break;
464         
465         // --- Operations ---
466         // Boolean Operations
467         case NODETYPE_LOGICALNOT:       // Logical NOT (!)
468                 if(!op) op = BC_OP_LOGICNOT;
469         case NODETYPE_BWNOT:    // Bitwise NOT (~)
470                 if(!op) op = BC_OP_BITNOT;
471         case NODETYPE_NEGATE:   // Negation (-)
472                 if(!op) op = BC_OP_NEG;
473                 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
474                 if(ret) return ret;
475                 Bytecode_AppendUniOp(Block->Handle, op);
476                 CHECK_IF_NEEDED(1);
477                 break;
478
479         // Logic
480         case NODETYPE_LOGICALAND:       if(!op) op = BC_OP_LOGICAND;
481         case NODETYPE_LOGICALOR:        if(!op) op = BC_OP_LOGICOR;
482         case NODETYPE_LOGICALXOR:       if(!op) op = BC_OP_LOGICXOR;
483         // Comparisons
484         case NODETYPE_EQUALS:   if(!op) op = BC_OP_EQUALS;
485         case NODETYPE_LESSTHAN: if(!op) op = BC_OP_LESSTHAN;
486         case NODETYPE_GREATERTHAN:      if(!op) op = BC_OP_GREATERTHAN;
487         case NODETYPE_LESSTHANEQUAL:    if(!op) op = BC_OP_LESSTHANOREQUAL;
488         case NODETYPE_GREATERTHANEQUAL: if(!op) op = BC_OP_GREATERTHANOREQUAL;
489         // General Binary Operations
490         case NODETYPE_ADD:      if(!op) op = BC_OP_ADD;
491         case NODETYPE_SUBTRACT: if(!op) op = BC_OP_SUBTRACT;
492         case NODETYPE_MULTIPLY: if(!op) op = BC_OP_MULTIPLY;
493         case NODETYPE_DIVIDE:   if(!op) op = BC_OP_DIVIDE;
494         case NODETYPE_MODULO:   if(!op) op = BC_OP_MODULO;
495         case NODETYPE_BWAND:    if(!op) op = BC_OP_BITAND;
496         case NODETYPE_BWOR:     if(!op) op = BC_OP_BITOR;
497         case NODETYPE_BWXOR:    if(!op) op = BC_OP_BITXOR;
498         case NODETYPE_BITSHIFTLEFT:     if(!op) op = BC_OP_BITSHIFTLEFT;
499         case NODETYPE_BITSHIFTRIGHT:    if(!op) op = BC_OP_BITSHIFTRIGHT;
500         case NODETYPE_BITROTATELEFT:    if(!op) op = BC_OP_BITROTATELEFT;
501                 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1);
502                 if(ret) return ret;
503                 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1);
504                 if(ret) return ret;
505         
506                 Bytecode_AppendBinOp(Block->Handle, op);
507                 CHECK_IF_NEEDED(1);
508                 break;
509         
510         default:
511                 ret = -1;
512                 AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type);
513                 break;
514         }
515
516         #if TRACE_NODE_RETURNS
517         if(ret && ret != ERRPTR) {
518                 AST_RuntimeError(Node, "Ret type of %p %i is %i", Node, Node->Type, ret->Type);
519         }
520         else {
521                 AST_RuntimeError(Node, "Ret type of %p %i is %p", Node, Node->Type, ret);
522         }
523         #endif
524
525         return ret;
526 }
527
528 /**
529  * \brief Define a variable
530  * \param Block Current block state
531  * \param Type  Type of the variable
532  * \param Name  Name of the variable
533  * \return Boolean Failure
534  */
535 int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name)
536 {
537         #if 0
538         tAST_Variable   *var, *prev = NULL;
539         
540         for( var = Block->FirstVar; var; prev = var, var = var->Next )
541         {
542                 if( strcmp(var->Name, Name) == 0 ) {
543                         AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name);
544                         return ERRPTR;
545                 }
546         }
547         
548         var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 );
549         var->Next = NULL;
550         var->Type = Type;
551         strcpy(var->Name, Name);
552         
553         if(prev)        prev->Next = var;
554         else    Block->FirstVar = var;
555         
556         return var;
557         #else
558         Bytecode_AppendDefineVar(Block->Handle, Name, Type);
559         return 0;
560         #endif
561 }
562
563 tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType)
564 {
565         #if 0
566         tAST_Variable   *var = NULL;
567         
568         // Speed hack
569         if( VarNode->BlockState == Block && VarNode->BlockIdent == Block->Ident ) {
570                 var = VarNode->ValueCache;
571                 #if TRACE_VAR_LOOKUPS
572                 AST_RuntimeMessage(VarNode, "debug", "Fast var fetch on '%s' %p (%p:%i)",
573                         VarNode->Variable.Name, var,
574                         VarNode->BlockState, VarNode->BlockIdent
575                         );
576                 #endif
577         }
578         else
579         {
580                 tAST_BlockInfo  *bs;
581                 for( bs = Block; bs; bs = bs->Parent )
582                 {
583                         for( var = bs->FirstVar; var; var = var->Next )
584                         {
585                                 if( strcmp(var->Name, VarNode->Variable.Name) == 0 )
586                                         break;
587                         }
588                         if(var) break;
589                 }
590                 
591                 if( !var )
592                 {
593                         if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) {
594                                 // Define variable
595                                 var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL);
596                         }
597                         else
598                         {
599                                 AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name);
600                                 return NULL;
601                         }
602                 }
603                 
604                 #if TRACE_VAR_LOOKUPS
605                 AST_RuntimeMessage(VarNode, "debug", "Saved variable lookup of '%s' %p (%p:%i)",
606                         VarNode->Variable.Name, var,
607                         Block, Block->Ident);
608                 #endif
609                 
610                 VarNode->ValueCache = var;
611                 VarNode->BlockState = Block;
612                 VarNode->BlockIdent = Block->Ident;
613         }
614         
615         return var;
616         #else
617         return (void*)1;
618         #endif
619 }
620
621 /**
622  * \brief Set the value of a variable
623  * \return Boolean Failure
624  */
625 int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
626 {
627         tAST_Variable   *var;
628         
629         var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF);
630         if(!var)        return -1;
631
632         // TODO: Check types
633
634         Bytecode_AppendSaveVar(Block->Handle, VarNode->Variable.Name);
635         return 0;
636 }
637
638 /**
639  * \brief Get the value of a variable
640  */
641 int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
642 {
643         tAST_Variable   *var;
644
645         var = BC_Variable_Lookup(Block, VarNode, 0);    
646         if(!var)        return -1;
647         
648         Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name);
649         return 0;
650 }
651
652 #if 0
653 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...)
654 {
655         va_list args;
656         
657         if(Node) {
658                 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
659         }
660         fprintf(stderr, "%s: ", Type);
661         va_start(args, Format);
662         vfprintf(stderr, Format, args);
663         va_end(args);
664         fprintf(stderr, "\n");
665 }
666 void AST_RuntimeError(tAST_Node *Node, const char *Format, ...)
667 {
668         va_list args;
669         
670         if(Node) {
671                 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
672         }
673         fprintf(stderr, "error: ");
674         va_start(args, Format);
675         vfprintf(stderr, Format, args);
676         va_end(args);
677         fprintf(stderr, "\n");
678 }
679 #endif

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