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);
51 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...);
52 void AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
54 int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type);
55 int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType);
58 // int giNextBlockIdent = 1;
61 int SpiderScript_BytecodeScript(tSpiderScript *Script)
63 tScript_Function *fcn;
64 for(fcn = Script->Functions; fcn; fcn = fcn->Next)
66 if( Bytecode_ConvertFunction(fcn) == 0 )
73 * \brief Convert a function into bytecode
75 tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn)
78 tAST_BlockInfo bi = {0};
80 // TODO: Return BCFcn instead?
81 if(Fcn->BCFcn) return Fcn->BCFcn;
83 ret = Bytecode_CreateFunction(Fcn);
87 if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) )
89 AST_RuntimeError(Fcn->ASTFcn, "Error in converting function");
90 Bytecode_DeleteFunction(ret);
94 Bytecode_AppendConstInt(ret, 0); // TODO: NULL
95 Bytecode_AppendReturn(ret);
101 // Indepotent operation
102 #define CHECK_IF_NEEDED(b_warn) do { if(!bKeepValue) {\
103 if(b_warn)AST_RuntimeMessage(Node, "Bytecode", "Operation without saving");\
104 Bytecode_AppendDelete(Block->Handle);\
105 _StackPop(Block, Node, SS_DATATYPE_UNDEF);\
109 * \brief Convert a node into bytecode
110 * \param Block Execution context
111 * \param Node Node to execute
113 int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
118 int bAddedValue = 1; // Used to tell if the value needs to be deleted
129 Bytecode_AppendEnterContext(Block->Handle); // Create a new block
131 tAST_BlockInfo blockInfo = {0};
132 blockInfo.Parent = Block;
133 blockInfo.Handle = Block->Handle;
134 // Loop over all nodes, or until the return value is set
135 for(node = Node->Block.FirstChild;
137 node = node->NextSibling )
139 ret = AST_ConvertNode(Block, node, 0);
141 if( blockInfo.StackDepth != 0 ) {
142 AST_RuntimeError(node, "Stack not reset at end of node");
146 Bytecode_AppendLeaveContext(Block->Handle); // Leave this context
150 case NODETYPE_ASSIGN:
151 // Perform assignment operation
152 if( Node->Assign.Operation != NODETYPE_NOP )
156 ret = AST_ConvertNode(Block, Node->Assign.Dest, 1);
158 t1 = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
159 if(t1 < 0) return -1;
161 ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
163 t2 = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
164 if(t2 < 0) return -1;
167 switch(Node->Assign.Operation)
169 // General Binary Operations
170 case NODETYPE_ADD: op = BC_OP_ADD; break;
171 case NODETYPE_SUBTRACT: op = BC_OP_SUBTRACT; break;
172 case NODETYPE_MULTIPLY: op = BC_OP_MULTIPLY; break;
173 case NODETYPE_DIVIDE: op = BC_OP_DIVIDE; break;
174 case NODETYPE_MODULO: op = BC_OP_MODULO; break;
175 case NODETYPE_BWAND: op = BC_OP_BITAND; break;
176 case NODETYPE_BWOR: op = BC_OP_BITOR; break;
177 case NODETYPE_BWXOR: op = BC_OP_BITXOR; break;
178 case NODETYPE_BITSHIFTLEFT: op = BC_OP_BITSHIFTLEFT; break;
179 case NODETYPE_BITSHIFTRIGHT: op = BC_OP_BITSHIFTRIGHT; break;
180 case NODETYPE_BITROTATELEFT: op = BC_OP_BITROTATELEFT; break;
183 AST_RuntimeError(Node, "Unknown operation in ASSIGN %i", Node->Assign.Operation);
186 // printf("assign, op = %i\n", op);
187 ret = _StackPush(Block, Node, t1);
188 if(ret < 0) return -1;
189 Bytecode_AppendBinOp(Block->Handle, op);
193 ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
198 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
199 if(ret < 0) return -1;
200 ret = _StackPush(Block, Node, ret);
201 if(ret < 0) return -1;
202 ret = _StackPush(Block, Node, ret);
203 if(ret < 0) return -1;
204 Bytecode_AppendDuplicate(Block->Handle);
207 ret = BC_SaveValue(Block, Node->Assign.Dest);
211 // Post increment/decrement
212 case NODETYPE_POSTINC:
213 case NODETYPE_POSTDEC:
214 // Save original value if requested
216 ret = BC_Variable_GetValue(Block, Node->UniOp.Value);
220 Bytecode_AppendConstInt(Block->Handle, 1);
221 ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER);
222 if(ret < 0) return -1;
224 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
227 if( Node->Type == NODETYPE_POSTDEC )
228 Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT);
230 Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD);
232 ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER); // TODO: Check for objects too
233 if(ret < 0) return -1;
234 ret = BC_SaveValue(Block, Node->UniOp.Value);
239 case NODETYPE_METHODCALL: {
242 ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1);
245 // Push arguments to the stack
246 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
248 ret = AST_ConvertNode(Block, node, 1);
252 // TODO: Check arguments? Need to get the types somehow
253 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
254 if(ret < 0) return -1;
257 ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT);
258 if(ret < 0) return -1;
259 Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs);
261 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
262 if(ret < 0) return -1;
264 CHECK_IF_NEEDED(0); // Don't warn
265 // TODO: Implement warn_unused_ret
268 case NODETYPE_FUNCTIONCALL:
269 case NODETYPE_CREATEOBJECT: {
272 // Get name (mangled into a single string)
275 for( i = 0; i < Block->NamespaceDepth; i ++ )
276 newnamelen += strlen(Block->CurNamespaceStack[i]) + 1;
277 newnamelen += strlen(Node->FunctionCall.Name) + 1;
278 manglename = alloca(newnamelen);
280 for( i = 0; i < Block->NamespaceDepth; i ++ ) {
282 strcat(manglename, Block->CurNamespaceStack[i]);
283 pos = strlen(manglename);
284 manglename[pos] = BC_NS_SEPARATOR;
285 manglename[pos+1] = '\0';
287 strcat(manglename, Node->FunctionCall.Name);
288 Block->NamespaceDepth = 0;
290 // Push arguments to the stack
291 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
293 // TODO: Type Checking
294 ret = AST_ConvertNode(Block, node, 1);
298 // TODO: Check arguments? Need to get the types somehow
299 ret = _StackPop(Block, node, SS_DATATYPE_UNDEF);
300 if(ret < 0) return -1;
304 if( Node->Type == NODETYPE_CREATEOBJECT )
306 Bytecode_AppendCreateObj(Block->Handle, manglename, nargs);
310 Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs);
313 // TODO: Get return type
314 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
315 if(ret < 0) return -1;
317 CHECK_IF_NEEDED(0); // Don't warn
318 // TODO: Implement warn_unused_ret
324 ret = AST_ConvertNode(Block, Node->If.Condition, 1);
326 // TODO: Should be boolean/integer, but meh
327 ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF);
328 if(ret < 0) return -1;
330 if_end = Bytecode_AllocateLabel(Block->Handle);
332 if( Node->If.False->Type != NODETYPE_NOP )
334 int if_true = Bytecode_AllocateLabel(Block->Handle);
336 Bytecode_AppendCondJump(Block->Handle, if_true);
339 ret = AST_ConvertNode(Block, Node->If.False, 0);
341 Bytecode_AppendJump(Block->Handle, if_end);
342 Bytecode_SetLabel(Block->Handle, if_true);
346 Bytecode_AppendCondJumpNot(Block->Handle, if_end);
350 ret = AST_ConvertNode(Block, Node->If.True, 0);
354 Bytecode_SetLabel(Block->Handle, if_end);
358 case NODETYPE_LOOP: {
359 int loop_start, loop_end;
360 int saved_break, saved_continue;
361 const char *saved_tag;
364 ret = AST_ConvertNode(Block, Node->For.Init, 0);
367 loop_start = Bytecode_AllocateLabel(Block->Handle);
368 loop_end = Bytecode_AllocateLabel(Block->Handle);
370 saved_break = Block->BreakTarget;
371 saved_continue = Block->ContinueTarget;
372 saved_tag = Block->Tag;
373 Block->BreakTarget = loop_end;
374 Block->ContinueTarget = loop_end;
375 Block->Tag = Node->For.Tag;
377 Bytecode_SetLabel(Block->Handle, loop_start);
379 // Check initial condition
380 if( !Node->For.bCheckAfter )
382 ret = AST_ConvertNode(Block, Node->For.Condition, 1);
384 Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT);
385 ret = _StackPop(Block, Node->For.Condition, SS_DATATYPE_UNDEF); // Boolean?
386 if(ret < 0) return -1;
387 Bytecode_AppendCondJump(Block->Handle, loop_end);
391 ret = AST_ConvertNode(Block, Node->For.Code, 0);
395 ret = AST_ConvertNode(Block, Node->For.Increment, 0);
397 // ret = _StackPop(Block, Node->For.Increment, SS_DATATYPE_UNDEF); // TODO: Check if needed
398 // if(ret < 0) return -1;
401 if( Node->For.bCheckAfter )
403 ret = AST_ConvertNode(Block, Node->For.Condition, 1);
405 ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); // Boolean?
406 if(ret < 0) return ret;
407 Bytecode_AppendCondJump(Block->Handle, loop_start);
411 Bytecode_AppendJump(Block->Handle, loop_start);
414 Bytecode_SetLabel(Block->Handle, loop_end);
416 Block->BreakTarget = saved_break;
417 Block->ContinueTarget = saved_continue;
418 Block->Tag = saved_tag;
422 case NODETYPE_RETURN:
423 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
425 Bytecode_AppendReturn(Block->Handle);
426 ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); //
427 if(ret < 0) return -1;
431 case NODETYPE_CONTINUE: {
432 tAST_BlockInfo *bi = Block;
433 if( Node->Variable.Name[0] ) {
434 while(bi && strcmp(bi->Tag, Node->Variable.Name) == 0) bi = bi->Parent;
437 // TODO: Check if BreakTarget/ContinueTarget are valid
438 if( Node->Type == NODETYPE_BREAK )
439 Bytecode_AppendJump(Block->Handle, bi->BreakTarget);
441 Bytecode_AppendJump(Block->Handle, bi->ContinueTarget);
445 case NODETYPE_DEFVAR:
446 ret = BC_Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name);
449 if( Node->DefVar.InitialValue )
451 ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1);
453 ret = _StackPop(Block, Node->DefVar.InitialValue, Node->DefVar.DataType);
454 if(ret < 0) return -1;
455 Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name);
461 if( Block->NamespaceDepth == MAX_NAMESPACE_DEPTH ) {
462 AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", MAX_NAMESPACE_DEPTH);
465 Block->CurNamespaceStack[ Block->NamespaceDepth ] = Node->Scope.Name;
466 Block->NamespaceDepth ++;
467 ret = AST_ConvertNode(Block, Node->Scope.Element, bKeepValue);
469 if( Block->NamespaceDepth != 0 ) {
470 AST_RuntimeError(Node, "Namespace scope used but no element at the end");
476 case NODETYPE_VARIABLE:
477 ret = BC_Variable_GetValue( Block, Node );
482 // Element of an Object
483 case NODETYPE_ELEMENT:
484 ret = AST_ConvertNode( Block, Node->Scope.Element, 1 );
487 ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT);
488 if(ret < 0) return -1;
490 Bytecode_AppendElement(Block->Handle, Node->Scope.Name);
491 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
492 if(ret < 0) return -1;
496 // Cast a value to another
498 ret = AST_ConvertNode(Block, Node->Cast.Value, 1);
500 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
501 if(ret < 0) return -1;
503 Bytecode_AppendCast(Block->Handle, Node->Cast.DataType);
504 ret = _StackPush(Block, Node, Node->Cast.DataType);
505 if(ret < 0) return -1;
509 // Index into an array
512 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1);
515 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
516 if(ret < 0) return -1;
517 if(ret != SS_DATATYPE_ARRAY && (ret >> 16) == 0) {
518 AST_RuntimeError(Node, "Type mismatch, Expected an array, got %i",
522 i = ret; // Hackily save the datatype
525 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1);
527 ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER);
528 if(ret < 0) return -1;
530 Bytecode_AppendIndex(Block->Handle);
532 // Update the array depth
533 if( i != SS_DATATYPE_ARRAY ) {
534 i -= 0x10000; // Decrease the array level
536 ret = _StackPush(Block, Node, i);
537 if(ret < 0) return -1;
542 // TODO: Implement runtime constants
543 case NODETYPE_CONSTANT:
544 // TODO: Scan namespace for constant name
545 AST_RuntimeError(Node, "TODO - Runtime Constants");
546 Block->NamespaceDepth = 0;
551 case NODETYPE_STRING:
552 Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length);
553 ret = _StackPush(Block, Node, SS_DATATYPE_STRING);
554 if(ret < 0) return -1;
557 case NODETYPE_INTEGER:
558 Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer);
559 ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER);
560 if(ret < 0) return -1;
564 Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real);
565 ret = _StackPush(Block, Node, SS_DATATYPE_REAL);
566 if(ret < 0) return -1;
570 // --- Operations ---
571 // Boolean Operations
572 case NODETYPE_LOGICALNOT: // Logical NOT (!)
573 if(!op) op = BC_OP_LOGICNOT;
574 case NODETYPE_BWNOT: // Bitwise NOT (~)
575 if(!op) op = BC_OP_BITNOT;
576 case NODETYPE_NEGATE: // Negation (-)
577 if(!op) op = BC_OP_NEG;
578 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
580 ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Undef
581 if(ret < 0) return -1;
583 Bytecode_AppendUniOp(Block->Handle, op);
584 ret = _StackPush(Block, Node, ret); // TODO: Logic = _INTEGER, Neg = No change
585 if(ret < 0) return -1;
591 case NODETYPE_LOGICALAND: if(!op) op = BC_OP_LOGICAND;
592 case NODETYPE_LOGICALOR: if(!op) op = BC_OP_LOGICOR;
593 case NODETYPE_LOGICALXOR: if(!op) op = BC_OP_LOGICXOR;
595 case NODETYPE_EQUALS: if(!op) op = BC_OP_EQUALS;
596 case NODETYPE_NOTEQUALS: if(!op) op = BC_OP_NOTEQUALS;
597 case NODETYPE_LESSTHAN: if(!op) op = BC_OP_LESSTHAN;
598 case NODETYPE_GREATERTHAN: if(!op) op = BC_OP_GREATERTHAN;
599 case NODETYPE_LESSTHANEQUAL: if(!op) op = BC_OP_LESSTHANOREQUAL;
600 case NODETYPE_GREATERTHANEQUAL: if(!op) op = BC_OP_GREATERTHANOREQUAL;
601 // General Binary Operations
602 case NODETYPE_ADD: if(!op) op = BC_OP_ADD;
603 case NODETYPE_SUBTRACT: if(!op) op = BC_OP_SUBTRACT;
604 case NODETYPE_MULTIPLY: if(!op) op = BC_OP_MULTIPLY;
605 case NODETYPE_DIVIDE: if(!op) op = BC_OP_DIVIDE;
606 case NODETYPE_MODULO: if(!op) op = BC_OP_MODULO;
607 case NODETYPE_BWAND: if(!op) op = BC_OP_BITAND;
608 case NODETYPE_BWOR: if(!op) op = BC_OP_BITOR;
609 case NODETYPE_BWXOR: if(!op) op = BC_OP_BITXOR;
610 case NODETYPE_BITSHIFTLEFT: if(!op) op = BC_OP_BITSHIFTLEFT;
611 case NODETYPE_BITSHIFTRIGHT: if(!op) op = BC_OP_BITSHIFTRIGHT;
612 case NODETYPE_BITROTATELEFT: if(!op) op = BC_OP_BITROTATELEFT;
613 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1);
615 ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object
616 if(ret < 0) return -1;
618 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1);
620 ret = _StackPop(Block, Node->BinOp.Right, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object
621 if(ret < 0) return -1;
623 Bytecode_AppendBinOp(Block->Handle, op);
624 _StackPush(Block, Node, ret);
629 AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type);
636 int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode)
639 switch(DestNode->Type)
642 case NODETYPE_VARIABLE:
643 ret = BC_Variable_SetValue( Block, DestNode );
647 ret = AST_ConvertNode(Block, DestNode->BinOp.Left, 1); // Array
649 ret = _StackPop(Block, DestNode->BinOp.Left, SS_DATATYPE_UNDEF);
650 if(ret < 0) return -1;
651 if(ret != SS_DATATYPE_ARRAY && (ret >> 16) == 0) {
652 AST_RuntimeError(DestNode, "Type mismatch, Expected an array, got %i",
657 ret = AST_ConvertNode(Block, DestNode->BinOp.Right, 1); // Offset
659 ret = _StackPop(Block, DestNode->BinOp.Right, SS_DATATYPE_INTEGER);
660 if(ret < 0) return -1;
662 Bytecode_AppendSetIndex( Block->Handle );
665 case NODETYPE_ELEMENT:
666 ret = AST_ConvertNode(Block, DestNode->Scope.Element, 1);
668 ret = _StackPop(Block, DestNode->Scope.Element, SS_DATATYPE_OBJECT);
669 if(ret < 0) return -1;
671 Bytecode_AppendSetElement( Block->Handle, DestNode->Scope.Name );
675 // TODO: Support assigning to object attributes
676 AST_RuntimeError(DestNode, "Assignment target is not a LValue");
683 * \brief Define a variable
684 * \param Block Current block state
685 * \param Type Type of the variable
686 * \param Name Name of the variable
687 * \return Boolean Failure
689 int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name)
691 tAST_Variable *var, *prev = NULL;
693 for( var = Block->FirstVar; var; prev = var, var = var->Next )
695 if( strcmp(var->Name, Name) == 0 ) {
696 AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name);
701 var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 );
704 strcpy(var->Name, Name);
706 if(prev) prev->Next = var;
707 else Block->FirstVar = var;
709 Bytecode_AppendDefineVar(Block->Handle, Name, Type);
713 tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType)
715 tAST_Variable *var = NULL;
718 for( bs = Block; bs; bs = bs->Parent )
720 for( var = bs->FirstVar; var; var = var->Next )
722 if( strcmp(var->Name, VarNode->Variable.Name) == 0 )
730 // if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) {
731 // // Define variable
732 // var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL);
736 AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name);
741 #if TRACE_VAR_LOOKUPS
742 AST_RuntimeMessage(VarNode, "debug", "Variable lookup of '%s' %p type %i",
743 VarNode->Variable.Name, var, var->Type);
750 * \brief Set the value of a variable
751 * \return Boolean Failure
753 int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
757 // TODO: Implicit definition type
758 var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF);
763 _StackPop(Block, VarNode, var->Type);
764 Bytecode_AppendSaveVar(Block->Handle, VarNode->Variable.Name);
769 * \brief Get the value of a variable
771 int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
775 var = BC_Variable_Lookup(Block, VarNode, 0);
778 _StackPush(Block, VarNode, var->Type);
779 Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name);
784 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...)
789 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
791 fprintf(stderr, "%s: ", Type);
792 va_start(args, Format);
793 vfprintf(stderr, Format, args);
795 fprintf(stderr, "\n");
797 void AST_RuntimeError(tAST_Node *Node, const char *Format, ...)
802 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
804 fprintf(stderr, "error: ");
805 va_start(args, Format);
806 vfprintf(stderr, Format, args);
808 fprintf(stderr, "\n");
812 int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type)
814 if(Block->StackDepth == MAX_STACK_DEPTH - 1) {
815 AST_RuntimeError(Node, "BUG - Stack overflow in AST-Bytecode conversion (node=%i)",
821 AST_RuntimeMessage(Node, "_StackPush", "%x - NT%i", Type, Node->Type);
823 Block->Stack[ ++Block->StackDepth ] = Type;
827 int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType)
829 if(Block->StackDepth == 0) {
830 AST_RuntimeError(Node, "BUG - Stack underflow in AST-Bytecode conversion (node=%i)",
835 AST_RuntimeMessage(Node, "_StackPop", "%x(?==%x) - NT%i",
836 Block->Stack[ Block->StackDepth ], WantedType, Node->Type);
838 if(WantedType != SS_DATATYPE_UNDEF && Block->Stack[ Block->StackDepth ] != SS_DATATYPE_UNDEF)
840 if( Block->Stack[ Block->StackDepth ] != WantedType ) {
841 AST_RuntimeError(Node, "AST-Bytecode - Type mismatch (wanted %x got %x)",
842 WantedType, Block->Stack[ Block->StackDepth ]);
847 return Block->Stack[Block->StackDepth--];