4 * AST to Bytecode Conversion
12 #include "bytecode_gen.h"
13 #include "bytecode_ops.h"
15 #define TRACE_VAR_LOOKUPS 0
16 #define TRACE_NODE_RETURNS 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 char Stack[MAX_STACK_DEPTH]; // Stores types of stack values
42 int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue);
43 int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode);
45 int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name);
46 int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
47 int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
49 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...);
50 void AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
52 int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type);
53 int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType);
56 // int giNextBlockIdent = 1;
59 int SpiderScript_BytecodeScript(tSpiderScript *Script)
61 tScript_Function *fcn;
62 for(fcn = Script->Functions; fcn; fcn = fcn->Next)
64 if( Bytecode_ConvertFunction(fcn) == 0 )
71 * \brief Convert a function into bytecode
73 tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn)
76 tAST_BlockInfo bi = {0};
78 // TODO: Return BCFcn instead?
79 if(Fcn->BCFcn) return Fcn->BCFcn;
81 ret = Bytecode_CreateFunction(Fcn);
85 if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) )
87 Bytecode_DeleteFunction(ret);
91 Bytecode_AppendConstInt(ret, 0); // TODO: NULL
92 Bytecode_AppendReturn(ret);
98 // Indepotent operation
99 #define CHECK_IF_NEEDED(b_warn) do { if(!bKeepValue) {\
100 if(b_warn)AST_RuntimeMessage(Node, "Bytecode", "Operation without saving");\
101 Bytecode_AppendDelete(Block->Handle);\
102 _StackPop(Block, Node, SS_DATATYPE_UNDEF);\
106 * \brief Convert a node into bytecode
107 * \param Block Execution context
108 * \param Node Node to execute
110 int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
115 int bAddedValue = 1; // Used to tell if the value needs to be deleted
126 Bytecode_AppendEnterContext(Block->Handle); // Create a new block
128 tAST_BlockInfo blockInfo = {0};
129 blockInfo.Parent = Block;
130 blockInfo.Handle = Block->Handle;
131 // Loop over all nodes, or until the return value is set
132 for(node = Node->Block.FirstChild;
134 node = node->NextSibling )
136 AST_ConvertNode(Block, node, 0);
139 Bytecode_AppendLeaveContext(Block->Handle); // Leave this context
143 case NODETYPE_ASSIGN:
144 // Perform assignment operation
145 if( Node->Assign.Operation != NODETYPE_NOP )
149 ret = AST_ConvertNode(Block, Node->Assign.Dest, 1);
151 ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
154 t1 = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
155 if(t1 < 0) return ret;
156 t2 = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
157 if(t1 < 0) return ret;
159 switch(Node->Assign.Operation)
161 // General Binary Operations
162 case NODETYPE_ADD: op = BC_OP_ADD; break;
163 case NODETYPE_SUBTRACT: op = BC_OP_SUBTRACT; break;
164 case NODETYPE_MULTIPLY: op = BC_OP_MULTIPLY; break;
165 case NODETYPE_DIVIDE: op = BC_OP_DIVIDE; break;
166 case NODETYPE_MODULO: op = BC_OP_MODULO; break;
167 case NODETYPE_BWAND: op = BC_OP_BITAND; break;
168 case NODETYPE_BWOR: op = BC_OP_BITOR; break;
169 case NODETYPE_BWXOR: op = BC_OP_BITXOR; break;
170 case NODETYPE_BITSHIFTLEFT: op = BC_OP_BITSHIFTLEFT; break;
171 case NODETYPE_BITSHIFTRIGHT: op = BC_OP_BITSHIFTRIGHT; break;
172 case NODETYPE_BITROTATELEFT: op = BC_OP_BITROTATELEFT; break;
175 AST_RuntimeError(Node, "Unknown operation in ASSIGN %i", Node->Assign.Operation);
178 // printf("assign, op = %i\n", op);
179 ret = _StackPush(Block, Node, t1);
180 if(ret < 0) return ret;
181 Bytecode_AppendBinOp(Block->Handle, op);
185 ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
190 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
191 if(ret < 0) return ret;
192 ret = _StackPush(Block, Node, ret);
193 if(ret < 0) return ret;
194 ret = _StackPush(Block, Node, ret);
195 if(ret < 0) return ret;
196 Bytecode_AppendDuplicate(Block->Handle);
199 ret = BC_SaveValue(Block, Node->Assign.Dest);
202 // Post increment/decrement
203 case NODETYPE_POSTINC:
204 case NODETYPE_POSTDEC:
205 // Save original value if requested
207 ret = BC_Variable_GetValue(Block, Node->UniOp.Value);
211 Bytecode_AppendConstInt(Block->Handle, 1);
212 ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER);
213 if(ret < 0) return ret;
215 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
218 if( Node->Type == NODETYPE_POSTDEC )
219 Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT);
221 Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD);
223 ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER); // TODO: Check for objects too
224 if(ret < 0) return ret;
225 ret = BC_SaveValue(Block, Node->UniOp.Value);
229 case NODETYPE_METHODCALL: {
232 ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1);
235 // Push arguments to the stack
236 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
238 ret = AST_ConvertNode(Block, node, 1);
242 // TODO: Check arguments? Need to get the types somehow
243 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
244 if(ret < 0) return ret;
247 ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT);
248 if(ret < 0) return ret;
249 Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs);
251 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
253 CHECK_IF_NEEDED(0); // Don't warn
254 // TODO: Implement warn_unused_ret
257 case NODETYPE_FUNCTIONCALL:
258 case NODETYPE_CREATEOBJECT: {
261 // Get name (mangled into a single string)
264 for( i = 0; i < Block->NamespaceDepth; i ++ )
265 newnamelen += strlen(Block->CurNamespaceStack[i]) + 1;
266 newnamelen += strlen(Node->FunctionCall.Name) + 1;
267 manglename = alloca(newnamelen);
269 for( i = 0; i < Block->NamespaceDepth; i ++ ) {
271 strcat(manglename, Block->CurNamespaceStack[i]);
272 pos = strlen(manglename);
273 manglename[pos] = BC_NS_SEPARATOR;
274 manglename[pos+1] = '\0';
276 strcat(manglename, Node->FunctionCall.Name);
277 Block->NamespaceDepth = 0;
279 // Push arguments to the stack
280 for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
282 // TODO: Type Checking
283 ret = AST_ConvertNode(Block, node, 1);
287 // TODO: Check arguments? Need to get the types somehow
288 ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
289 if(ret < 0) return ret;
293 if( Node->Type == NODETYPE_CREATEOBJECT )
295 Bytecode_AppendCreateObj(Block->Handle, manglename, nargs);
299 Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs);
302 // TODO: Get return type
303 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
305 CHECK_IF_NEEDED(0); // Don't warn
306 // TODO: Implement warn_unused_ret
312 ret = AST_ConvertNode(Block, Node->If.Condition, 1);
315 if_end = Bytecode_AllocateLabel(Block->Handle);
317 if( Node->If.False->Type != NODETYPE_NOP )
319 int if_true = Bytecode_AllocateLabel(Block->Handle);
321 // TODO: Should be boolean, but do I care realy?
322 ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF);
323 if(ret < 0) return ret;
324 Bytecode_AppendCondJump(Block->Handle, if_true);
327 ret = AST_ConvertNode(Block, Node->If.False, 0);
329 Bytecode_AppendJump(Block->Handle, if_end);
330 Bytecode_SetLabel(Block->Handle, if_true);
334 // TODO: Should really be boolean, but meh
335 ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF);
336 if(ret < 0) return ret;
337 Bytecode_AppendCondJumpNot(Block->Handle, if_end);
341 ret = AST_ConvertNode(Block, Node->If.True, 0);
345 Bytecode_SetLabel(Block->Handle, if_end);
349 case NODETYPE_LOOP: {
350 int loop_start, loop_end;
351 int saved_break, saved_continue;
352 const char *saved_tag;
355 ret = AST_ConvertNode(Block, Node->For.Init, 0);
358 loop_start = Bytecode_AllocateLabel(Block->Handle);
359 loop_end = Bytecode_AllocateLabel(Block->Handle);
361 saved_break = Block->BreakTarget;
362 saved_continue = Block->ContinueTarget;
363 saved_tag = Block->Tag;
364 Block->BreakTarget = loop_end;
365 Block->ContinueTarget = loop_end;
366 Block->Tag = Node->For.Tag;
368 Bytecode_SetLabel(Block->Handle, loop_start);
370 // Check initial condition
371 if( !Node->For.bCheckAfter )
373 ret = AST_ConvertNode(Block, Node->For.Condition, 1);
375 Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT);
376 ret = _StackPop(Block, Node->For.Condition, SS_DATATYPE_UNDEF); // Boolean?
377 if(ret < 0) return ret;
378 Bytecode_AppendCondJump(Block->Handle, loop_end);
382 ret = AST_ConvertNode(Block, Node->For.Code, 0);
386 ret = AST_ConvertNode(Block, Node->For.Increment, 0);
388 // ret = _StackPop(Block, Node->For.Increment, SS_DATATYPE_UNDEF); // TODO: Check if needed
389 // if(ret < 0) return ret;
392 if( Node->For.bCheckAfter )
394 ret = AST_ConvertNode(Block, Node->For.Condition, 1);
396 ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); // Boolean?
397 if(ret < 0) return ret;
398 Bytecode_AppendCondJump(Block->Handle, loop_start);
402 Bytecode_AppendJump(Block->Handle, loop_start);
405 Bytecode_SetLabel(Block->Handle, loop_end);
407 Block->BreakTarget = saved_break;
408 Block->ContinueTarget = saved_continue;
409 Block->Tag = saved_tag;
413 case NODETYPE_RETURN:
414 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
416 Bytecode_AppendReturn(Block->Handle);
417 ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); //
421 case NODETYPE_CONTINUE: {
422 tAST_BlockInfo *bi = Block;
423 if( Node->Variable.Name[0] ) {
424 while(bi && strcmp(bi->Tag, Node->Variable.Name) == 0) bi = bi->Parent;
427 // TODO: Check if BreakTarget/ContinueTarget are valid
428 if( Node->Type == NODETYPE_BREAK )
429 Bytecode_AppendJump(Block->Handle, bi->BreakTarget);
431 Bytecode_AppendJump(Block->Handle, bi->ContinueTarget);
435 case NODETYPE_DEFVAR:
436 ret = BC_Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name);
439 if( Node->DefVar.InitialValue )
441 ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1);
443 ret = _StackPop(Block, Node->DefVar.InitialValue, Node->DefVar.DataType);
444 if(ret < 0) return ret;
445 Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name);
451 if( Block->NamespaceDepth == MAX_NAMESPACE_DEPTH ) {
452 AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", MAX_NAMESPACE_DEPTH);
455 Block->CurNamespaceStack[ Block->NamespaceDepth ] = Node->Scope.Name;
456 Block->NamespaceDepth ++;
457 ret = AST_ConvertNode(Block, Node->Scope.Element, bKeepValue);
458 if( Block->NamespaceDepth != 0 ) {
459 AST_RuntimeError(Node, "Namespace scope used but no element at the end");
462 CHECK_IF_NEEDED(0); // No warning?
466 case NODETYPE_VARIABLE:
467 ret = BC_Variable_GetValue( Block, Node );
471 // Element of an Object
472 case NODETYPE_ELEMENT:
473 ret = AST_ConvertNode( Block, Node->Scope.Element, 1 );
476 ret = _StackPop(Block, Node->Scope.Element, SS_DATATYPE_OBJECT);
477 if(ret < 0) return ret;
479 Bytecode_AppendElement(Block->Handle, Node->Scope.Name);
480 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
481 if(ret<0) return ret;
485 // Cast a value to another
487 ret = AST_ConvertNode(Block, Node->Cast.Value, 1);
489 ret = _StackPop(Block, Node->Cast.Value, SS_DATATYPE_UNDEF);
490 if(ret<0) return ret;
492 Bytecode_AppendCast(Block->Handle, Node->Cast.DataType);
493 ret = _StackPush(Block, Node, Node->Cast.DataType);
494 if(ret<0) return ret;
498 // Index into an array
500 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); // Array
502 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); // Offset
505 ret = _StackPop(Block, Node->BinOp.Right, SS_DATATYPE_ARRAY);
506 if(ret<0) return ret;
507 ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_INTEGER);
508 if(ret<0) return ret;
510 Bytecode_AppendIndex(Block->Handle);
511 ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); // TODO: Get array datatype?
512 if(ret<0) return ret;
516 // TODO: Implement runtime constants
517 case NODETYPE_CONSTANT:
518 // TODO: Scan namespace for constant name
519 AST_RuntimeError(Node, "TODO - Runtime Constants");
520 Block->NamespaceDepth = 0;
525 case NODETYPE_STRING:
526 Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length);
527 ret = _StackPush(Block, Node, SS_DATATYPE_STRING);
528 if(ret<0) return ret;
531 case NODETYPE_INTEGER:
532 Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer);
533 ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER);
534 if(ret<0) return ret;
538 Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real);
539 ret = _StackPush(Block, Node, SS_DATATYPE_REAL);
540 if(ret<0) return ret;
544 // --- Operations ---
545 // Boolean Operations
546 case NODETYPE_LOGICALNOT: // Logical NOT (!)
547 if(!op) op = BC_OP_LOGICNOT;
548 case NODETYPE_BWNOT: // Bitwise NOT (~)
549 if(!op) op = BC_OP_BITNOT;
550 case NODETYPE_NEGATE: // Negation (-)
551 if(!op) op = BC_OP_NEG;
552 ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
554 ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Undef
555 if(ret<0) return ret;
557 Bytecode_AppendUniOp(Block->Handle, op);
558 ret = _StackPush(Block, Node, ret); // TODO: Logic = _INTEGER, Neg = No change
559 if(ret<0) return ret;
565 case NODETYPE_LOGICALAND: if(!op) op = BC_OP_LOGICAND;
566 case NODETYPE_LOGICALOR: if(!op) op = BC_OP_LOGICOR;
567 case NODETYPE_LOGICALXOR: if(!op) op = BC_OP_LOGICXOR;
569 case NODETYPE_EQUALS: if(!op) op = BC_OP_EQUALS;
570 case NODETYPE_NOTEQUALS: if(!op) op = BC_OP_NOTEQUALS;
571 case NODETYPE_LESSTHAN: if(!op) op = BC_OP_LESSTHAN;
572 case NODETYPE_GREATERTHAN: if(!op) op = BC_OP_GREATERTHAN;
573 case NODETYPE_LESSTHANEQUAL: if(!op) op = BC_OP_LESSTHANOREQUAL;
574 case NODETYPE_GREATERTHANEQUAL: if(!op) op = BC_OP_GREATERTHANOREQUAL;
575 // General Binary Operations
576 case NODETYPE_ADD: if(!op) op = BC_OP_ADD;
577 case NODETYPE_SUBTRACT: if(!op) op = BC_OP_SUBTRACT;
578 case NODETYPE_MULTIPLY: if(!op) op = BC_OP_MULTIPLY;
579 case NODETYPE_DIVIDE: if(!op) op = BC_OP_DIVIDE;
580 case NODETYPE_MODULO: if(!op) op = BC_OP_MODULO;
581 case NODETYPE_BWAND: if(!op) op = BC_OP_BITAND;
582 case NODETYPE_BWOR: if(!op) op = BC_OP_BITOR;
583 case NODETYPE_BWXOR: if(!op) op = BC_OP_BITXOR;
584 case NODETYPE_BITSHIFTLEFT: if(!op) op = BC_OP_BITSHIFTLEFT;
585 case NODETYPE_BITSHIFTRIGHT: if(!op) op = BC_OP_BITSHIFTRIGHT;
586 case NODETYPE_BITROTATELEFT: if(!op) op = BC_OP_BITROTATELEFT;
587 ret = AST_ConvertNode(Block, Node->BinOp.Left, 1);
589 ret = AST_ConvertNode(Block, Node->BinOp.Right, 1);
592 ret = _StackPop(Block, Node->BinOp.Right, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object
593 if(ret<0) return ret;
594 ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object
595 if(ret<0) return ret;
597 Bytecode_AppendBinOp(Block->Handle, op);
598 _StackPush(Block, Node, ret);
604 AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type);
608 #if TRACE_NODE_RETURNS
609 if(ret && ret != ERRPTR) {
610 AST_RuntimeError(Node, "Ret type of %p %i is %i", Node, Node->Type, ret->Type);
613 AST_RuntimeError(Node, "Ret type of %p %i is %p", Node, Node->Type, ret);
620 int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode)
623 switch(DestNode->Type)
626 case NODETYPE_VARIABLE:
627 ret = BC_Variable_SetValue( Block, DestNode );
631 ret = AST_ConvertNode(Block, DestNode->BinOp.Left, 1); // Array
633 ret = AST_ConvertNode(Block, DestNode->BinOp.Right, 1); // Offset
635 Bytecode_AppendSetIndex( Block->Handle );
638 case NODETYPE_ELEMENT:
639 ret = AST_ConvertNode(Block, DestNode->Scope.Element, 1);
641 Bytecode_AppendSetElement( Block->Handle, DestNode->Scope.Name );
645 // TODO: Support assigning to object attributes
646 AST_RuntimeError(DestNode, "Assignment target is not a LValue");
653 * \brief Define a variable
654 * \param Block Current block state
655 * \param Type Type of the variable
656 * \param Name Name of the variable
657 * \return Boolean Failure
659 int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name)
662 tAST_Variable *var, *prev = NULL;
664 for( var = Block->FirstVar; var; prev = var, var = var->Next )
666 if( strcmp(var->Name, Name) == 0 ) {
667 AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name);
672 var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 );
675 strcpy(var->Name, Name);
677 if(prev) prev->Next = var;
678 else Block->FirstVar = var;
682 Bytecode_AppendDefineVar(Block->Handle, Name, Type);
687 tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType)
690 tAST_Variable *var = NULL;
693 if( VarNode->BlockState == Block && VarNode->BlockIdent == Block->Ident ) {
694 var = VarNode->ValueCache;
695 #if TRACE_VAR_LOOKUPS
696 AST_RuntimeMessage(VarNode, "debug", "Fast var fetch on '%s' %p (%p:%i)",
697 VarNode->Variable.Name, var,
698 VarNode->BlockState, VarNode->BlockIdent
705 for( bs = Block; bs; bs = bs->Parent )
707 for( var = bs->FirstVar; var; var = var->Next )
709 if( strcmp(var->Name, VarNode->Variable.Name) == 0 )
717 if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) {
719 var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL);
723 AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name);
728 #if TRACE_VAR_LOOKUPS
729 AST_RuntimeMessage(VarNode, "debug", "Saved variable lookup of '%s' %p (%p:%i)",
730 VarNode->Variable.Name, var,
731 Block, Block->Ident);
734 VarNode->ValueCache = var;
735 VarNode->BlockState = Block;
736 VarNode->BlockIdent = Block->Ident;
746 * \brief Set the value of a variable
747 * \return Boolean Failure
749 int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
753 var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF);
758 Bytecode_AppendSaveVar(Block->Handle, VarNode->Variable.Name);
763 * \brief Get the value of a variable
765 int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode)
769 var = BC_Variable_Lookup(Block, VarNode, 0);
772 Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name);
777 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...)
782 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
784 fprintf(stderr, "%s: ", Type);
785 va_start(args, Format);
786 vfprintf(stderr, Format, args);
788 fprintf(stderr, "\n");
790 void AST_RuntimeError(tAST_Node *Node, const char *Format, ...)
795 fprintf(stderr, "%s:%i: ", Node->File, Node->Line);
797 fprintf(stderr, "error: ");
798 va_start(args, Format);
799 vfprintf(stderr, Format, args);
801 fprintf(stderr, "\n");
805 int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type)
807 if(Block->StackDepth == MAX_STACK_DEPTH - 1) {
808 AST_RuntimeError(Node, "BUG - Stack overflow in AST-Bytecode conversion");
812 Block->Stack[ ++Block->StackDepth ] = Type;
816 int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType)
818 if(Block->StackDepth == 0) {
819 AST_RuntimeError(Node, "BUG - Stack underflow in AST-Bytecode conversion");
822 if(WantedType != SS_DATATYPE_UNDEF && Block->Stack[ Block->StackDepth ] != SS_DATATYPE_UNDEF)
824 if( Block->Stack[ Block->StackDepth ] != WantedType ) {
829 return Block->Stack[Block->StackDepth--];