4 * AST to Bytecode Conversion
12 #include "bytecode_gen.h"
13 #include "bytecode_ops.h"
15 #define TRACE_VAR_LOOKUPS 0
16 #define TRACE_TYPE_STACK 0
17 #define MAX_NAMESPACE_DEPTH 10
18 #define MAX_STACK_DEPTH 10 // This is for one function, so shouldn't need more
21 extern tSpiderFunction *gpExports_First;
24 typedef struct sAST_BlockInfo
26 struct sAST_BlockInfo *Parent;
34 const char *CurNamespaceStack[MAX_NAMESPACE_DEPTH];
37 int Stack[MAX_STACK_DEPTH]; // Stores types of stack values
39 tAST_Variable *FirstVar;
44 int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue);
45 int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode);
47 int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name);
48 int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
49 int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
50 void BC_Variable_Clear(tAST_BlockInfo *Block);
52 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...);
53 void AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
55 int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type);
56 int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType);
59 // int giNextBlockIdent = 1;
62 int SpiderScript_BytecodeScript(tSpiderScript *Script)
64 tScript_Function *fcn;
65 for(fcn = Script->Functions; fcn; fcn = fcn->Next)
67 if( Bytecode_ConvertFunction(fcn) == 0 )
74 * \brief Convert a function into bytecode
76 tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn)
79 tAST_BlockInfo bi = {0};
82 // TODO: Return BCFcn instead?
83 if(Fcn->BCFcn) return Fcn->BCFcn;
85 ret = Bytecode_CreateFunction(Fcn);
91 for( i = 0; i < Fcn->ArgumentCount; i ++ )
93 BC_Variable_Define(&bi, Fcn->Arguments[i].Type, Fcn->Arguments[i].Name);
96 if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) )
98 AST_RuntimeError(Fcn->ASTFcn, "Error in converting function");
99 Bytecode_DeleteFunction(ret);
100 BC_Variable_Clear(&bi);
103 BC_Variable_Clear(&bi);
106 Bytecode_AppendConstInt(ret, 0); // TODO: NULL
107 Bytecode_AppendReturn(ret);
113 // Indepotent operation
114 #define CHECK_IF_NEEDED(b_warn) do { if(!bKeepValue) {\
115 if(b_warn)AST_RuntimeMessage(Node, "Bytecode", "Operation without saving");\
116 Bytecode_AppendDelete(Block->Handle);\
117 _StackPop(Block, Node, SS_DATATYPE_UNDEF);\
121 * \brief Convert a node into bytecode
122 * \param Block Execution context
123 * \param Node Node to execute
125 int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
130 int bAddedValue = 1; // Used to tell if the value needs to be deleted
141 Bytecode_AppendEnterContext(Block->Handle); // Create a new block
143 tAST_BlockInfo blockInfo = {0};
144 blockInfo.Parent = Block;
145 blockInfo.Handle = Block->Handle;
146 // Loop over all nodes, or until the return value is set
147 for(node = Node->Block.FirstChild;
149 node = node->NextSibling )
151 ret = AST_ConvertNode(&blockInfo, node, 0);
153 if( blockInfo.StackDepth != 0 ) {
154 AST_RuntimeError(node, "Stack not reset at end of node");
155 blockInfo.StackDepth = 0;
159 BC_Variable_Clear(&blockInfo);
161 Bytecode_AppendLeaveContext(Block->Handle); // Leave this context
165 case NODETYPE_ASSIGN:
166 // Perform assignment operation
167 if( Node->Assign.Operation != NODETYPE_NOP )
171 ret = AST_ConvertNode(Block, Node->Assign.Dest, 1);
173 t1 = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
174 if(t1 < 0) return -1;
176 ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
178 t2 = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
179 if(t2 < 0) return -1;
182 switch(Node->Assign.Operation)
184 // General Binary Operations
185 case NODETYPE_ADD: op = BC_OP_ADD; break;
186 case NODETYPE_SUBTRACT: op = BC_OP_SUBTRACT; break;
187 case NODETYPE_MULTIPLY: op = BC_OP_MULTIPLY; break;
188 case NODETYPE_DIVIDE: op = BC_OP_DIVIDE; break;
189 case NODETYPE_MODULO: op = BC_OP_MODULO; break;
190 case NODETYPE_BWAND: op = BC_OP_BITAND; break;
191 case NODETYPE_BWOR: op = BC_OP_BITOR; break;
192 case NODETYPE_BWXOR: op = BC_OP_BITXOR; break;
193 case NODETYPE_BITSHIFTLEFT: op = BC_OP_BITSHIFTLEFT; break;
194 case NODETYPE_BITSHIFTRIGHT: op = BC_OP_BITSHIFTRIGHT; break;
195 case NODETYPE_BITROTATELEFT: op = BC_OP_BITROTATELEFT; break;
198 AST_RuntimeError(Node, "Unknown operation in ASSIGN %i", Node->Assign.Operation);
201 // printf("assign, op = %i\n", op);
202 ret = _StackPush(Block, Node, t1);
203 if(ret < 0) return -1;
204 Bytecode_AppendBinOp(Block->Handle, op);
208 ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
213 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
214 if(ret < 0) return -1;
215 ret = _StackPush(Block, Node, ret);
216 if(ret < 0) return -1;
217 ret = _StackPush(Block, Node, ret);
218 if(ret < 0) return -1;
219 Bytecode_AppendDuplicate(Block->Handle);
222 ret = BC_SaveValue(Block, Node->Assign.Dest);
226 // Post increment/decrement
227 case NODETYPE_POSTINC:
228 case NODETYPE_POSTDEC:
229 // Save original value if requested
231 ret = BC_Variable_GetValue(Block, Node->UniOp.Value);
235 Bytecode_AppendConstInt(Block->Handle, 1);
236 ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER);
237 if(ret < 0) return -1;
239 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
242 if( Node->Type == NODETYPE_POSTDEC )
243 Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT);
245 Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD);
247 ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER); // TODO: Check for objects too
248 if(ret < 0) return -1;
249 ret = BC_SaveValue(Block, Node->UniOp.Value);
254 case NODETYPE_METHODCALL: {
257 ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1);
260 // Push arguments to the stack
261 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
263 ret = AST_ConvertNode(Block, node, 1);
267 // TODO: Check arguments? Need to get the types somehow
268 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
269 if(ret < 0) return -1;
272 ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT);
273 if(ret < 0) return -1;
274 Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs);
276 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
277 if(ret < 0) return -1;
279 CHECK_IF_NEEDED(0); // Don't warn
280 // TODO: Implement warn_unused_ret
283 case NODETYPE_FUNCTIONCALL:
284 case NODETYPE_CREATEOBJECT: {
287 // Get name (mangled into a single string)
290 for( i = 0; i < Block->NamespaceDepth; i ++ )
291 newnamelen += strlen(Block->CurNamespaceStack[i]) + 1;
292 newnamelen += strlen(Node->FunctionCall.Name) + 1;
295 manglename = alloca(newnamelen);
297 for( i = 0; i < Block->NamespaceDepth; i ++ ) {
298 strcpy(manglename+newnamelen, Block->CurNamespaceStack[i]);
299 newnamelen += strlen(Block->CurNamespaceStack[i]) + 1;
300 manglename[ newnamelen - 1 ] = BC_NS_SEPARATOR;
302 strcpy(manglename + newnamelen, Node->FunctionCall.Name);
303 newnamelen += strlen(Node->FunctionCall.Name) + 1;
304 // manglename[ newnamelen ] = '\0'; // Zero length terminator
305 Block->NamespaceDepth = 0;
307 // Push arguments to the stack
308 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
310 // TODO: Type Checking
311 ret = AST_ConvertNode(Block, node, 1);
315 // TODO: Check arguments? Need to get the types somehow
316 ret = _StackPop(Block, node, SS_DATATYPE_UNDEF);
317 if(ret < 0) return -1;
321 if( Node->Type == NODETYPE_CREATEOBJECT )
323 Bytecode_AppendCreateObj(Block->Handle, manglename, nargs);
327 Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs);
330 // TODO: Get return type
331 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
332 if(ret < 0) return -1;
334 CHECK_IF_NEEDED(0); // Don't warn
335 // TODO: Implement warn_unused_ret
341 ret = AST_ConvertNode(Block, Node->If.Condition, 1);
343 // TODO: Should be boolean/integer, but meh
344 ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF);
345 if(ret < 0) return -1;
347 if_end = Bytecode_AllocateLabel(Block->Handle);
349 if( Node->If.False->Type != NODETYPE_NOP )
351 int if_true = Bytecode_AllocateLabel(Block->Handle);
353 Bytecode_AppendCondJump(Block->Handle, if_true);
356 ret = AST_ConvertNode(Block, Node->If.False, 0);
358 Bytecode_AppendJump(Block->Handle, if_end);
359 Bytecode_SetLabel(Block->Handle, if_true);
363 Bytecode_AppendCondJumpNot(Block->Handle, if_end);
367 ret = AST_ConvertNode(Block, Node->If.True, 0);
371 Bytecode_SetLabel(Block->Handle, if_end);
375 case NODETYPE_LOOP: {
376 int loop_start, loop_end, code_end;
377 int saved_break, saved_continue;
378 const char *saved_tag;
381 ret = AST_ConvertNode(Block, Node->For.Init, 0);
384 loop_start = Bytecode_AllocateLabel(Block->Handle);
385 code_end = Bytecode_AllocateLabel(Block->Handle);
386 loop_end = Bytecode_AllocateLabel(Block->Handle);
388 saved_break = Block->BreakTarget;
389 saved_continue = Block->ContinueTarget;
390 saved_tag = Block->Tag;
391 Block->BreakTarget = loop_end;
392 Block->ContinueTarget = code_end;
393 Block->Tag = Node->For.Tag;
395 Bytecode_SetLabel(Block->Handle, loop_start);
397 // Check initial condition
398 if( !Node->For.bCheckAfter )
400 ret = AST_ConvertNode(Block, Node->For.Condition, 1);
402 Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT);
403 ret = _StackPop(Block, Node->For.Condition, SS_DATATYPE_UNDEF); // Boolean?
404 if(ret < 0) return -1;
405 Bytecode_AppendCondJump(Block->Handle, loop_end);
409 ret = AST_ConvertNode(Block, Node->For.Code, 0);
412 Bytecode_SetLabel(Block->Handle, code_end);
415 ret = AST_ConvertNode(Block, Node->For.Increment, 0);
417 // ret = _StackPop(Block, Node->For.Increment, SS_DATATYPE_UNDEF); // TODO: Check if needed
418 // if(ret < 0) return -1;
421 if( Node->For.bCheckAfter )
423 ret = AST_ConvertNode(Block, Node->For.Condition, 1);
425 ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); // Boolean?
426 if(ret < 0) return ret;
427 Bytecode_AppendCondJump(Block->Handle, loop_start);
431 Bytecode_AppendJump(Block->Handle, loop_start);
434 Bytecode_SetLabel(Block->Handle, loop_end);
436 Block->BreakTarget = saved_break;
437 Block->ContinueTarget = saved_continue;
438 Block->Tag = saved_tag;
442 case NODETYPE_RETURN:
443 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
445 Bytecode_AppendReturn(Block->Handle);
446 ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); //
447 if(ret < 0) return -1;
451 case NODETYPE_CONTINUE: {
452 tAST_BlockInfo *bi = Block;
453 if( Node->Variable.Name[0] ) {
454 while(bi && (!bi->Tag || strcmp(bi->Tag, Node->Variable.Name) != 0))
458 while(bi && !bi->Tag)
462 // TODO: Check if BreakTarget/ContinueTarget are valid
463 if( Node->Type == NODETYPE_BREAK )
464 Bytecode_AppendJump(Block->Handle, bi->BreakTarget);
466 Bytecode_AppendJump(Block->Handle, bi->ContinueTarget);
470 case NODETYPE_DEFVAR:
471 ret = BC_Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name);
474 if( Node->DefVar.InitialValue )
476 ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1);
478 ret = _StackPop(Block, Node->DefVar.InitialValue, Node->DefVar.DataType);
479 if(ret < 0) return -1;
480 Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name);
486 if( Block->NamespaceDepth == MAX_NAMESPACE_DEPTH ) {
487 AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", MAX_NAMESPACE_DEPTH);
490 Block->CurNamespaceStack[ Block->NamespaceDepth ] = Node->Scope.Name;
491 Block->NamespaceDepth ++;
492 ret = AST_ConvertNode(Block, Node->Scope.Element, bKeepValue);
494 if( Block->NamespaceDepth != 0 ) {
495 AST_RuntimeError(Node, "Namespace scope used but no element at the end");
501 case NODETYPE_VARIABLE:
502 ret = BC_Variable_GetValue( Block, Node );
507 // Element of an Object
508 case NODETYPE_ELEMENT:
509 ret = AST_ConvertNode( Block, Node->Scope.Element, 1 );
512 // TODO: Support elements for non-objects
513 ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT);
514 if(ret < 0) return -1;
516 Bytecode_AppendElement(Block->Handle, Node->Scope.Name);
518 // TODO: Somehow know this at compile time?
519 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
520 if(ret < 0) return -1;
524 // Cast a value to another
526 ret = AST_ConvertNode(Block, Node->Cast.Value, 1);
528 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
529 if(ret < 0) return -1;
531 Bytecode_AppendCast(Block->Handle, Node->Cast.DataType);
532 ret = _StackPush(Block, Node, Node->Cast.DataType);
533 if(ret < 0) return -1;
537 // Index into an array
540 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1);
543 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
544 if(ret < 0) return -1;
545 if(ret != SS_DATATYPE_ARRAY && SS_GETARRAYDEPTH(ret) == 0) {
546 AST_RuntimeError(Node, "Type mismatch, Expected an array, got %i",
550 i = ret; // Hackily save the datatype
553 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1);
555 ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER);
556 if(ret < 0) return -1;
558 Bytecode_AppendIndex(Block->Handle);
560 // Update the array depth
561 if( i != SS_DATATYPE_ARRAY ) {
562 i = SS_DOWNARRAY(i); // Decrease the array level
564 ret = _StackPush(Block, Node, i);
565 if(ret < 0) return -1;
570 // TODO: Implement runtime constants
571 case NODETYPE_CONSTANT:
572 // TODO: Scan namespace for constant name
573 AST_RuntimeError(Node, "TODO - Runtime Constants");
574 Block->NamespaceDepth = 0;
578 case NODETYPE_STRING:
579 Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length);
580 ret = _StackPush(Block, Node, SS_DATATYPE_STRING);
581 if(ret < 0) return -1;
584 case NODETYPE_INTEGER:
585 Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer);
586 ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER);
587 if(ret < 0) return -1;
591 Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real);
592 ret = _StackPush(Block, Node, SS_DATATYPE_REAL);
593 if(ret < 0) return -1;
597 Bytecode_AppendConstNull(Block->Handle);
598 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
599 if(ret < 0) return -1;
603 // --- Operations ---
604 // Boolean Operations
605 case NODETYPE_LOGICALNOT: // Logical NOT (!)
606 if(!op) op = BC_OP_LOGICNOT;
607 case NODETYPE_BWNOT: // Bitwise NOT (~)
608 if(!op) op = BC_OP_BITNOT;
609 case NODETYPE_NEGATE: // Negation (-)
610 if(!op) op = BC_OP_NEG;
611 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
613 ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Undef
614 if(ret < 0) return -1;
616 Bytecode_AppendUniOp(Block->Handle, op);
617 ret = _StackPush(Block, Node, ret); // TODO: Logic = _INTEGER, Neg = No change
618 if(ret < 0) return -1;
624 case NODETYPE_LOGICALAND: if(!op) op = BC_OP_LOGICAND;
625 case NODETYPE_LOGICALOR: if(!op) op = BC_OP_LOGICOR;
626 case NODETYPE_LOGICALXOR: if(!op) op = BC_OP_LOGICXOR;
628 case NODETYPE_EQUALS: if(!op) op = BC_OP_EQUALS;
629 case NODETYPE_NOTEQUALS: if(!op) op = BC_OP_NOTEQUALS;
630 case NODETYPE_LESSTHAN: if(!op) op = BC_OP_LESSTHAN;
631 case NODETYPE_GREATERTHAN: if(!op) op = BC_OP_GREATERTHAN;
632 case NODETYPE_LESSTHANEQUAL: if(!op) op = BC_OP_LESSTHANOREQUAL;
633 case NODETYPE_GREATERTHANEQUAL: if(!op) op = BC_OP_GREATERTHANOREQUAL;
634 // General Binary Operations
635 case NODETYPE_ADD: if(!op) op = BC_OP_ADD;
636 case NODETYPE_SUBTRACT: if(!op) op = BC_OP_SUBTRACT;
637 case NODETYPE_MULTIPLY: if(!op) op = BC_OP_MULTIPLY;
638 case NODETYPE_DIVIDE: if(!op) op = BC_OP_DIVIDE;
639 case NODETYPE_MODULO: if(!op) op = BC_OP_MODULO;
640 case NODETYPE_BWAND: if(!op) op = BC_OP_BITAND;
641 case NODETYPE_BWOR: if(!op) op = BC_OP_BITOR;
642 case NODETYPE_BWXOR: if(!op) op = BC_OP_BITXOR;
643 case NODETYPE_BITSHIFTLEFT: if(!op) op = BC_OP_BITSHIFTLEFT;
644 case NODETYPE_BITSHIFTRIGHT: if(!op) op = BC_OP_BITSHIFTRIGHT;
645 case NODETYPE_BITROTATELEFT: if(!op) op = BC_OP_BITROTATELEFT;
646 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1);
648 ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object
649 if(ret < 0) return -1;
651 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1);
653 ret = _StackPop(Block, Node->BinOp.Right, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object
654 if(ret < 0) return -1;
656 Bytecode_AppendBinOp(Block->Handle, op);
657 _StackPush(Block, Node, ret);
662 AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type);
669 int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode)
672 switch(DestNode->Type)
675 case NODETYPE_VARIABLE:
676 ret = BC_Variable_SetValue( Block, DestNode );
681 ret = AST_ConvertNode(Block, DestNode->BinOp.Left, 1); // Array
683 ret = _StackPop(Block, DestNode->BinOp.Left, SS_DATATYPE_UNDEF);
684 if(ret < 0) return -1;
685 if(ret != SS_DATATYPE_ARRAY && SS_GETARRAYDEPTH(ret) == 0) {
686 AST_RuntimeError(DestNode, "Type mismatch, Expected an array, got %i",
690 type = SS_DOWNARRAY(ret);
692 ret = AST_ConvertNode(Block, DestNode->BinOp.Right, 1); // Offset
694 ret = _StackPop(Block, DestNode->BinOp.Right, SS_DATATYPE_INTEGER);
695 if(ret < 0) return -1;
697 Bytecode_AppendSetIndex( Block->Handle );
698 _StackPop(Block, DestNode, type);
701 case NODETYPE_ELEMENT:
702 ret = AST_ConvertNode(Block, DestNode->Scope.Element, 1);
704 ret = _StackPop(Block, DestNode->Scope.Element, SS_DATATYPE_OBJECT);
705 if(ret < 0) return -1;
707 Bytecode_AppendSetElement( Block->Handle, DestNode->Scope.Name );
711 // TODO: Support assigning to object attributes
712 AST_RuntimeError(DestNode, "Assignment target is not a LValue");
719 * \brief Define a variable
720 * \param Block Current block state
721 * \param Type Type of the variable
722 * \param Name Name of the variable
723 * \return Boolean Failure
725 int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name)
727 tAST_Variable *var, *prev = NULL;
729 for( var = Block->FirstVar; var; prev = var, var = var->Next )
731 if( strcmp(var->Name, Name) == 0 ) {
732 AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name);
737 var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 );
740 strcpy(var->Name, Name);
742 if(prev) prev->Next = var;
743 else Block->FirstVar = var;
745 Bytecode_AppendDefineVar(Block->Handle, Name, Type);
749 tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType)
751 tAST_Variable *var = NULL;
754 for( bs = Block; bs; bs = bs->Parent )
756 for( var = bs->FirstVar; var; var = var->Next )
758 if( strcmp(var->Name, VarNode->Variable.Name) == 0 )
766 // if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) {
767 // // Define variable
768 // var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL);
772 AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name);
777 #if TRACE_VAR_LOOKUPS
778 AST_RuntimeMessage(VarNode, "debug", "Variable lookup of '%s' %p type %i",
779 VarNode->Variable.Name, var, var->Type);
786 * \brief Set the value of a variable
787 * \return Boolean Failure
789 int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
793 // TODO: Implicit definition type
794 var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF);
799 _StackPop(Block, VarNode, var->Type);
800 Bytecode_AppendSaveVar(Block->Handle, VarNode->Variable.Name);
805 * \brief Get the value of a variable
807 int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
811 var = BC_Variable_Lookup(Block, VarNode, 0);
814 _StackPush(Block, VarNode, var->Type);
815 Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name);
819 void BC_Variable_Clear(tAST_BlockInfo *Block)
822 for( var = Block->FirstVar; var; )
824 tAST_Variable *tv = var->Next;
828 Block->FirstVar = NULL;
832 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...)
837 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
839 fprintf(stderr, "%s: ", Type);
840 va_start(args, Format);
841 vfprintf(stderr, Format, args);
843 fprintf(stderr, "\n");
845 void AST_RuntimeError(tAST_Node *Node, const char *Format, ...)
850 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
852 fprintf(stderr, "error: ");
853 va_start(args, Format);
854 vfprintf(stderr, Format, args);
856 fprintf(stderr, "\n");
860 int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type)
862 if(Block->StackDepth == MAX_STACK_DEPTH - 1) {
863 AST_RuntimeError(Node, "BUG - Stack overflow in AST-Bytecode conversion (node=%i)",
869 AST_RuntimeMessage(Node, "_StackPush", "%x - NT%i", Type, Node->Type);
871 Block->Stack[ ++Block->StackDepth ] = Type;
875 int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType)
877 if(Block->StackDepth == 0) {
878 AST_RuntimeError(Node, "BUG - Stack underflow in AST-Bytecode conversion (node=%i)",
883 AST_RuntimeMessage(Node, "_StackPop", "%x(?==%x) - NT%i",
884 Block->Stack[ Block->StackDepth ], WantedType, Node->Type);
886 if(WantedType != SS_DATATYPE_UNDEF && Block->Stack[ Block->StackDepth ] != SS_DATATYPE_UNDEF)
888 if( Block->Stack[ Block->StackDepth ] != WantedType ) {
889 AST_RuntimeError(Node, "AST-Bytecode - Type mismatch (wanted %x got %x)",
890 WantedType, Block->Stack[ Block->StackDepth ]);
895 return Block->Stack[Block->StackDepth--];