3 * by John Hodge (thePowersGang)
20 # define DEBUG_F(v...) printf(v)
22 # define DEBUG_F(v...)
26 extern void AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
29 typedef struct sBC_StackEnt tBC_StackEnt;
30 typedef struct sBC_Stack tBC_Stack;
32 enum eBC_StackEntTypes
34 ET_NULL, // Start of the stack
36 ET_FUNCTION_START = NUM_SS_DATATYPES,
37 ET_REFERENCE // Reference to a tSpiderValue
46 tSpiderValue *Reference; // Used for everything else
47 tSpiderObject *Object;
48 tSpiderNamespace *Namespace;
56 tBC_StackEnt Entries[];
60 tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args);
61 int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount);
64 int Bytecode_int_StackPop(tBC_Stack *Stack, tBC_StackEnt *Dest)
66 if( Stack->EntryCount == 0 ) return 1;
68 *Dest = Stack->Entries[Stack->EntryCount];
72 int Bytecode_int_StackPush(tBC_Stack *Stack, tBC_StackEnt *Src)
74 if( Stack->EntryCount == Stack->EntrySpace ) return 1;
75 Stack->Entries[Stack->EntryCount] = *Src;
80 int Bytecode_int_IsStackEntTrue(tBC_StackEnt *Ent)
84 case SS_DATATYPE_INTEGER:
85 return !!Ent->Integer;
86 case SS_DATATYPE_REAL:
87 return !(-.5f < Ent->Real && Ent->Real < 0.5f);
88 case SS_DATATYPE_OBJECT:
89 return Ent->Object != NULL;
90 case ET_FUNCTION_START:
93 return SpiderScript_IsValueTrue(Ent->Reference);
97 tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp)
101 case SS_DATATYPE_INTEGER:
102 case SS_DATATYPE_REAL:
103 case SS_DATATYPE_OBJECT:
105 tmp = malloc(sizeof(tSpiderValue));
106 tmp->ReferenceCount = 1;
108 // Stops a stack value from having free() called on it
109 tmp->ReferenceCount = 2;
117 case SS_DATATYPE_INTEGER:
118 tmp->Type = SS_DATATYPE_INTEGER;
119 tmp->Integer = Ent->Integer;
121 case SS_DATATYPE_REAL:
122 tmp->Type = SS_DATATYPE_REAL;
123 tmp->Real = Ent->Real;
125 case SS_DATATYPE_OBJECT:
126 tmp->Type = SS_DATATYPE_OBJECT;
127 tmp->Object = Ent->Object;
129 case ET_FUNCTION_START:
130 AST_RuntimeError(NULL, "_GetSpiderValue on ET_FUNCTION_START");
133 SpiderScript_ReferenceValue(Ent->Reference);
134 return Ent->Reference;
138 void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value)
141 Ent->Type = ET_REFERENCE;
142 Ent->Reference = NULL;
147 case SS_DATATYPE_INTEGER:
148 Ent->Type = SS_DATATYPE_INTEGER;
149 Ent->Integer = Value->Integer;
151 case SS_DATATYPE_REAL:
152 Ent->Type = SS_DATATYPE_REAL;
153 Ent->Real = Value->Real;
155 case SS_DATATYPE_OBJECT:
156 Ent->Type = SS_DATATYPE_OBJECT;
157 Ent->Object = Value->Object;
158 Ent->Object->ReferenceCount ++;
161 SpiderScript_ReferenceValue(Value);
162 Ent->Type = ET_REFERENCE;
163 Ent->Reference = Value;
168 void Bytecode_int_DerefStackValue(tBC_StackEnt *Ent)
172 case SS_DATATYPE_INTEGER:
173 case SS_DATATYPE_REAL:
175 case SS_DATATYPE_OBJECT:
177 Ent->Object->ReferenceCount --;
178 if(Ent->Object->ReferenceCount == 0) {
179 Ent->Object->Type->Destructor( Ent->Object );
181 // printf("Object %p derefed (obj refcount = %i)\n", Ent->Object, Ent->Object->ReferenceCount);
187 SpiderScript_DereferenceValue(Ent->Reference);
188 Ent->Reference = NULL;
192 void Bytecode_int_RefStackValue(tBC_StackEnt *Ent)
196 case SS_DATATYPE_INTEGER:
197 case SS_DATATYPE_REAL:
199 case SS_DATATYPE_OBJECT:
201 Ent->Object->ReferenceCount ++;
202 // printf("Object %p referenced (count = %i)\n", Ent->Object, Ent->Object->ReferenceCount);
207 SpiderScript_ReferenceValue(Ent->Reference);
212 void Bytecode_int_PrintStackValue(tBC_StackEnt *Ent)
216 case SS_DATATYPE_INTEGER:
217 printf("0x%"PRIx64, Ent->Integer);
219 case SS_DATATYPE_REAL:
220 printf("%lf", Ent->Real);
222 case SS_DATATYPE_OBJECT:
223 printf("Obj %p", Ent->Object);
227 printf("*%p (%i refs)", Ent->Reference, Ent->Reference->ReferenceCount);
235 # define PRINT_STACKVAL(val) Bytecode_int_PrintStackValue(&val)
237 # define PRINT_STACKVAL(val)
240 #define GET_STACKVAL(dst) if((ret = Bytecode_int_StackPop(Stack, &dst))) { \
241 AST_RuntimeError(NULL, "Stack pop failed, empty stack");\
244 #define PUT_STACKVAL(src) if((ret = Bytecode_int_StackPush(Stack, &src))) { \
245 AST_RuntimeError(NULL, "Stack push failed, full stack");\
248 #define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer)
249 #define OP_STRING(op_ptr) ((op_ptr)->Content.StringInt.String)
251 tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args)
253 const int stack_size = 100;
254 tSpiderValue *ret, tmpsval;
259 stack = malloc(sizeof(tBC_Stack) + stack_size*sizeof(tBC_StackEnt));
260 stack->EntrySpace = stack_size;
261 stack->EntryCount = 0;
263 // Push arguments in order (so top is last arg)
264 for( i = 0; i < NArguments; i ++ )
266 Bytecode_int_SetSpiderValue(&val, Args[i]);
267 Bytecode_int_StackPush(stack, &val);
271 Bytecode_int_ExecuteFunction(Script, Fcn, stack, NArguments);
274 if( Bytecode_int_StackPop(stack, &val) ) {
280 ret = Bytecode_int_GetSpiderValue(&val, &tmpsval);
281 // Ensure it's a heap value
282 if(ret == &tmpsval) {
283 ret = malloc(sizeof(tSpiderValue));
284 memcpy(ret, &tmpsval, sizeof(tSpiderValue));
285 // Set to 2 in _GetSpiderValue, so stack doesn't have free() called
286 ret->ReferenceCount = 1;
292 tSpiderNamespace *Bytecode_int_ResolveNamespace(tSpiderNamespace *Start, const char *Name, const char **FinalName)
295 tSpiderNamespace *ns = Start;
296 while( (pos = strchr(Name, BC_NS_SEPARATOR)) )
298 int len = pos - Name;
299 for( ns = ns->FirstChild; ns; ns = ns->Next )
301 if(memcmp(ns->Name, Name, len) == 0 && ns->Name[len] == 0)
309 if(FinalName) *FinalName = Name;
314 * \brief Call an external function (may recurse into Bytecode_ExecuteFunction, but may not)
316 int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSpiderNamespace *DefaultNS, tBC_Op *op )
318 const char *name = OP_STRING(op);
319 int arg_count = OP_INDX(op);
321 tSpiderValue *args[arg_count];
324 const char *namespaces[] = {NULL}; // TODO: Default/imported namespaces
326 DEBUG_F("CALL (general) %s %i args\n", name, arg_count);
329 for( i = arg_count; i --; )
332 args[i] = Bytecode_int_GetSpiderValue(&val1, NULL);
333 Bytecode_int_DerefStackValue(&val1);
336 // Call the function etc.
337 if( op->Operation == BC_OP_CALLFUNCTION )
339 rv = SpiderScript_ExecuteFunction(Script, name, namespaces, arg_count, args, &op->CacheEnt);
341 else if( op->Operation == BC_OP_CREATEOBJ )
343 rv = SpiderScript_CreateObject(Script, name, namespaces, arg_count, args);
345 else if( op->Operation == BC_OP_CALLMETHOD )
350 if(val1.Type == SS_DATATYPE_OBJECT)
352 else if(val1.Type == ET_REFERENCE && val1.Reference && val1.Reference->Type == SS_DATATYPE_OBJECT)
353 obj = val1.Reference->Object;
356 AST_RuntimeError(NULL, "OP_CALLMETHOD on non object");
359 rv = SpiderScript_ExecuteMethod(Script, obj, name, arg_count, args);
360 Bytecode_int_DerefStackValue(&val1);
364 AST_RuntimeError(NULL, "BUG - Unknown operation for CALL/CREATEOBJ (%i)", op->Operation);
368 AST_RuntimeError(NULL, "SpiderScript_ExecuteFunction returned ERRPTR");
372 for( i = arg_count; i --; )
373 SpiderScript_DereferenceValue(args[i]);
374 // Get and push return
375 Bytecode_int_SetSpiderValue(&val1, rv);
378 SpiderScript_DereferenceValue(rv);
382 printf("%s returned NULL\n", name);
384 if( rv && rv != ERRPTR && rv->ReferenceCount != 1 ) {
385 printf("Return value from %s reference count fail (%i)\n",
386 name, rv->ReferenceCount);
393 int Bytecode_int_LocalBinOp_Integer(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2)
397 case BC_OP_ADD: Val1->Integer = Val1->Integer + Val2->Integer; break;
398 case BC_OP_SUBTRACT: Val1->Integer = Val1->Integer - Val2->Integer; break;
399 case BC_OP_MULTIPLY: Val1->Integer = Val1->Integer * Val2->Integer; break;
400 case BC_OP_DIVIDE: Val1->Integer = Val1->Integer / Val2->Integer; break;
402 case BC_OP_EQUALS: Val1->Integer = (Val1->Integer == Val2->Integer); break;
403 case BC_OP_NOTEQUALS: Val1->Integer = (Val1->Integer != Val2->Integer); break;
404 case BC_OP_LESSTHAN: Val1->Integer = (Val1->Integer < Val2->Integer); break;
405 case BC_OP_LESSTHANOREQUAL: Val1->Integer = (Val1->Integer <= Val2->Integer); break;
406 case BC_OP_GREATERTHAN: Val1->Integer = (Val1->Integer > Val2->Integer); break;
407 case BC_OP_GREATERTHANOREQUAL: Val1->Integer = (Val1->Integer >= Val2->Integer); break;
409 case BC_OP_BITAND: Val1->Integer = Val1->Integer & Val2->Integer; break;
410 case BC_OP_BITOR: Val1->Integer = Val1->Integer | Val2->Integer; break;
411 case BC_OP_BITXOR: Val1->Integer = Val1->Integer ^ Val2->Integer; break;
412 case BC_OP_MODULO: Val1->Integer = Val1->Integer % Val2->Integer; break;
413 default: AST_RuntimeError(NULL, "Invalid operation on datatype Integer"); return -1;
418 int Bytecode_int_LocalBinOp_Real(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2)
422 // Real = Real OP Real
423 case BC_OP_ADD: Val1->Real = Val1->Real + Val2->Real; return 0;
424 case BC_OP_SUBTRACT: Val1->Real = Val1->Real - Val2->Real; return 0;
425 case BC_OP_MULTIPLY: Val1->Real = Val1->Real * Val2->Real; return 0;
426 case BC_OP_DIVIDE: Val1->Real = Val1->Real / Val2->Real; return 0;
428 // Bool/Integer = Real OP Real
429 case BC_OP_EQUALS: Val1->Integer = (Val1->Real == Val2->Real); break;
430 case BC_OP_NOTEQUALS: Val1->Integer = (Val1->Real != Val2->Real); break;
431 case BC_OP_LESSTHAN: Val1->Integer = (Val1->Real < Val2->Real); break;
432 case BC_OP_LESSTHANOREQUAL: Val1->Integer = (Val1->Real <= Val2->Real); break;
433 case BC_OP_GREATERTHAN: Val1->Integer = (Val1->Real > Val2->Real); break;
434 case BC_OP_GREATERTHANOREQUAL: Val1->Integer = (Val1->Real >= Val2->Real); break;
436 default: AST_RuntimeError(NULL, "Invalid operation on datatype Real"); return -1;
438 Val1->Type = SS_DATATYPE_INTEGER; // Becomes logical
442 #define STATE_HDR() DEBUG_F("%p %2i ", op, Stack->EntryCount)
445 * \brief Execute a bytecode function with a stack
447 int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount)
451 tBC_StackEnt val1, val2;
452 int local_var_count = Fcn->BCFcn->MaxVariableCount;
453 tBC_StackEnt local_vars[local_var_count]; // Includes arguments
454 tSpiderValue tmpVal1, tmpVal2; // temp storage
455 tSpiderValue *pval1, *pval2, *ret_val;
456 tSpiderNamespace *default_namespace = &Script->Variant->RootNamespace;
458 // Initialise local vars
459 for( i = 0; i < local_var_count; i ++ )
460 local_vars[i].Type = ET_NULL;
463 if( ArgCount > Fcn->ArgumentCount ) return -1;
464 DEBUG_F("Fcn->ArgumentCount = %i\n", Fcn->ArgumentCount);
465 // - Handle optional arguments
466 for( i = Fcn->ArgumentCount; i > ArgCount; )
469 local_vars[i].Integer = 0;
470 local_vars[i].Type = Fcn->Arguments[i].Type;
474 GET_STACKVAL(local_vars[i]);
475 // TODO: Type checks / enforcing
479 memset(&val1, 0, sizeof(val1));
480 val1.Type = ET_FUNCTION_START;
484 op = Fcn->BCFcn->Operations;
487 const char *opstr = "";
488 tBC_Op *nextop = op->Next, *jmp_target;
490 switch(op->Operation)
499 jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
500 DEBUG_F("JUMP #%i %p\n", OP_INDX(op), jmp_target);
505 jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
506 DEBUG_F("JUMPIF #%i %p\n", OP_INDX(op), jmp_target);
508 if( Bytecode_int_IsStackEntTrue(&val1) )
511 case BC_OP_JUMPIFNOT:
513 jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
514 DEBUG_F("JUMPIFNOT #%i %p\n", OP_INDX(op), jmp_target);
516 if( !Bytecode_int_IsStackEntTrue(&val1) )
521 case BC_OP_DEFINEVAR: {
523 type = OP_INDX(op) & 0xFFFF;
524 slot = OP_INDX(op) >> 16;
525 if(slot < 0 || slot >= local_var_count) {
526 DEBUG_F("ERROR: slot %i out of range (max %i)\n", slot, local_var_count);
530 DEBUG_F("DEFVAR %i of type %i\n", slot, type);
531 if( local_vars[slot].Type != ET_NULL ) {
532 Bytecode_int_DerefStackValue( &local_vars[slot] );
533 local_vars[slot].Type = ET_NULL;
535 memset(&local_vars[slot], 0, sizeof(local_vars[0]));
536 local_vars[slot].Type = type;
539 // Enter/Leave context
541 case BC_OP_ENTERCONTEXT:
543 DEBUG_F("ENTERCONTEXT\n");
545 case BC_OP_LEAVECONTEXT:
547 DEBUG_F("LEAVECONTEXT\n");
551 case BC_OP_LOADVAR: {
552 int slot = OP_INDX(op);
554 DEBUG_F("LOADVAR %i ", slot);
555 if( slot < 0 || slot >= local_var_count ) {
556 AST_RuntimeError(NULL, "Loading from invalid slot %i", slot);
559 DEBUG_F("("); PRINT_STACKVAL(local_vars[slot]); DEBUG_F(")\n");
560 PUT_STACKVAL(local_vars[slot]);
561 Bytecode_int_RefStackValue( &local_vars[slot] );
563 case BC_OP_SAVEVAR: {
564 int slot = OP_INDX(op);
566 DEBUG_F("SAVEVAR %i = ", slot);
567 if( slot < 0 || slot >= local_var_count ) {
568 AST_RuntimeError(NULL, "Loading from invalid slot %i", slot);
571 // Remove whatever was in there before
572 DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] ");
573 Bytecode_int_DerefStackValue( &local_vars[slot] );
575 GET_STACKVAL(local_vars[slot]);
576 PRINT_STACKVAL(local_vars[slot]);
580 // Array index (get or set)
584 GET_STACKVAL(val1); // Index
585 // TODO: Check that index is an integer
586 if( val1.Type != SS_DATATYPE_INTEGER ) {
591 // Get array as raw spider value
592 GET_STACKVAL(val2); // Array
593 pval1 = Bytecode_int_GetSpiderValue(&val2, &tmpVal1);
594 Bytecode_int_DerefStackValue(&val2);
596 if( op->Operation == BC_OP_SETINDEX ) {
598 pval2 = Bytecode_int_GetSpiderValue(&val2, NULL);
599 Bytecode_int_DerefStackValue(&val2);
601 DEBUG_F("SETINDEX %i ", val1.Integer); PRINT_STACKVAL(val2); DEBUG_F("\n");
603 ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, pval2);
604 if(ret_val == ERRPTR) { nextop = NULL; break; }
605 SpiderScript_DereferenceValue(pval2);
608 DEBUG_F("INDEX %i ", val1.Integer);
609 ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, ERRPTR);
610 if(ret_val == ERRPTR) { nextop = NULL; break; }
612 Bytecode_int_SetSpiderValue(&val1, ret_val);
613 SpiderScript_DereferenceValue(ret_val);
616 DEBUG_F("[Got "); PRINT_STACKVAL(val1); DEBUG_F("]\n");
619 // Dereference the array (or object, ...)
620 if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
623 // Object element (get or set)
625 case BC_OP_SETELEMENT:
629 // - Integers/Reals can't have elements :)
630 if( val1.Type != ET_REFERENCE ) {
635 pval1 = Bytecode_int_GetSpiderValue(&val1, NULL);
636 Bytecode_int_DerefStackValue(&val1);
638 if( op->Operation == BC_OP_SETELEMENT ) {
640 pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2);
641 Bytecode_int_DerefStackValue(&val2);
643 DEBUG_F("SETELEMENT %s ", OP_STRING(op)); PRINT_STACKVAL(val2); DEBUG_F("\n");
645 ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), pval2);
646 if(ret_val == ERRPTR) { nextop = NULL; break; }
648 if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2);
651 DEBUG_F("ELEMENT %s ", OP_STRING(op));
653 ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), ERRPTR);
654 if(ret_val == ERRPTR) { nextop = NULL; break; }
656 Bytecode_int_SetSpiderValue(&val2, ret_val);
657 SpiderScript_DereferenceValue(ret_val);
660 DEBUG_F("[Got "); PRINT_STACKVAL(val2); DEBUG_F("]\n");
663 SpiderScript_DereferenceValue(pval1);
669 DEBUG_F("LOADINT 0x%lx\n", op->Content.Integer);
670 val1.Type = SS_DATATYPE_INTEGER;
671 val1.Integer = op->Content.Integer;
676 DEBUG_F("LOADREAL %lf\n", op->Content.Real);
677 val1.Type = SS_DATATYPE_REAL;
678 val1.Real = op->Content.Real;
683 DEBUG_F("LOADSTR %i \"%s\"\n", OP_INDX(op), OP_STRING(op));
684 val1.Type = SS_DATATYPE_STRING;
685 val1.Reference = SpiderScript_CreateString(OP_INDX(op), OP_STRING(op));
690 DEBUG_F("LOADNULL\n");
691 val1.Type = ET_REFERENCE;
692 val1.Reference = NULL;
698 val2.Type = OP_INDX(op);
699 DEBUG_F("CAST to %i\n", val2.Type);
701 if(val1.Type == val2.Type) {
705 if( val2.Type == SS_DATATYPE_INTEGER && val1.Type == SS_DATATYPE_REAL ) {
706 val2.Integer = val1.Real;
708 else if( val2.Type == SS_DATATYPE_REAL && val2.Type == SS_DATATYPE_INTEGER ) {
709 val2.Real = val1.Integer;
712 pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
713 pval2 = SpiderScript_CastValueTo(val2.Type, pval1);
715 Bytecode_int_SetSpiderValue(&val2, pval2);
716 SpiderScript_DereferenceValue(pval2);
718 if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
719 Bytecode_int_DerefStackValue(&val1);
720 // printf("CAST (%x->%x) - Original %i references remaining\n",
721 // pval1->Type, OP_INDX(op),
722 // pval1->ReferenceCount);
729 DEBUG_F("DUPSTACK ");
731 PRINT_STACKVAL(val1);
735 Bytecode_int_RefStackValue(&val1);
738 // Discard the top item from the stack
741 DEBUG_F("DELSTACK\n");
748 DEBUG_F("LOGICNOT\n");
751 val2.Type = SS_DATATYPE_INTEGER;
752 val2.Integer = !Bytecode_int_IsStackEntTrue(&val1);
753 Bytecode_int_StackPush(Stack, &val2);
754 Bytecode_int_DerefStackValue(&val1);
758 if(!ast_op) ast_op = NODETYPE_BWNOT, opstr = "BITNOT";
760 if(!ast_op) ast_op = NODETYPE_NEGATE, opstr = "NEG";
763 DEBUG_F("%s\n", opstr);
766 pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
767 Bytecode_int_DerefStackValue(&val1);
769 ret_val = AST_ExecuteNode_UniOp(Script, NULL, ast_op, pval1);
770 if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
771 Bytecode_int_SetSpiderValue(&val1, ret_val);
772 if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val);
773 Bytecode_int_StackPush(Stack, &val1);
779 if(!ast_op) ast_op = NODETYPE_LOGICALAND, opstr = "LOGICAND";
781 if(!ast_op) ast_op = NODETYPE_LOGICALOR, opstr = "LOGICOR";
783 if(!ast_op) ast_op = NODETYPE_LOGICALXOR, opstr = "LOGICXOR";
786 DEBUG_F("%s\n", opstr);
791 switch(op->Operation)
794 i = Bytecode_int_IsStackEntTrue(&val1) && Bytecode_int_IsStackEntTrue(&val2);
797 i = Bytecode_int_IsStackEntTrue(&val1) || Bytecode_int_IsStackEntTrue(&val2);
800 i = Bytecode_int_IsStackEntTrue(&val1) ^ Bytecode_int_IsStackEntTrue(&val2);
803 Bytecode_int_DerefStackValue(&val1);
804 Bytecode_int_DerefStackValue(&val2);
806 val1.Type = SS_DATATYPE_INTEGER;
808 Bytecode_int_StackPush(Stack, &val1);
812 if(!ast_op) ast_op = NODETYPE_BWAND, opstr = "BITAND";
814 if(!ast_op) ast_op = NODETYPE_BWOR, opstr = "BITOR";
816 if(!ast_op) ast_op = NODETYPE_BWXOR, opstr = "BITXOR";
818 case BC_OP_BITSHIFTLEFT:
819 if(!ast_op) ast_op = NODETYPE_BITSHIFTLEFT, opstr = "BITSHIFTLEFT";
820 case BC_OP_BITSHIFTRIGHT:
821 if(!ast_op) ast_op = NODETYPE_BITSHIFTRIGHT, opstr = "BITSHIFTRIGHT";
822 case BC_OP_BITROTATELEFT:
823 if(!ast_op) ast_op = NODETYPE_BITROTATELEFT, opstr = "BITROTATELEFT";
826 if(!ast_op) ast_op = NODETYPE_ADD, opstr = "ADD";
828 if(!ast_op) ast_op = NODETYPE_SUBTRACT, opstr = "SUBTRACT";
830 if(!ast_op) ast_op = NODETYPE_MULTIPLY, opstr = "MULTIPLY";
832 if(!ast_op) ast_op = NODETYPE_DIVIDE, opstr = "DIVIDE";
834 if(!ast_op) ast_op = NODETYPE_MODULO, opstr = "MODULO";
837 if(!ast_op) ast_op = NODETYPE_EQUALS, opstr = "EQUALS";
838 case BC_OP_NOTEQUALS:
839 if(!ast_op) ast_op = NODETYPE_NOTEQUALS, opstr = "NOTEQUALS";
841 if(!ast_op) ast_op = NODETYPE_LESSTHAN, opstr = "LESSTHAN";
842 case BC_OP_LESSTHANOREQUAL:
843 if(!ast_op) ast_op = NODETYPE_LESSTHANEQUAL, opstr = "LESSTHANOREQUAL";
844 case BC_OP_GREATERTHAN:
845 if(!ast_op) ast_op = NODETYPE_GREATERTHAN, opstr = "GREATERTHAN";
846 case BC_OP_GREATERTHANOREQUAL:
847 if(!ast_op) ast_op = NODETYPE_GREATERTHANEQUAL, opstr = "GREATERTHANOREQUAL";
850 DEBUG_F("BINOP %i %s (bc %i)\n", ast_op, opstr, op->Operation);
852 GET_STACKVAL(val2); // Right
853 GET_STACKVAL(val1); // Left
855 DEBUG_F(" ("); PRINT_STACKVAL(val1); DEBUG_F(")");
856 DEBUG_F(" ("); PRINT_STACKVAL(val2); DEBUG_F(")\n");
858 // Perform integer operations locally
859 if( val1.Type == SS_DATATYPE_INTEGER && val2.Type == SS_DATATYPE_INTEGER )
861 if( Bytecode_int_LocalBinOp_Integer(op->Operation, &val1, &val2) ) {
869 if(val1. Type == SS_DATATYPE_REAL && val2.Type == SS_DATATYPE_REAL )
871 if( Bytecode_int_LocalBinOp_Real(op->Operation, &val1, &val2) ) {
879 pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
880 pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2);
881 Bytecode_int_DerefStackValue(&val1);
882 Bytecode_int_DerefStackValue(&val2);
884 // Hand to AST execution code
885 ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2);
886 if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
887 if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2);
889 if(ret_val == ERRPTR) {
890 AST_RuntimeError(NULL, "_BinOp returned ERRPTR");
894 Bytecode_int_SetSpiderValue(&val1, ret_val);
895 if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val);
900 case BC_OP_CREATEOBJ:
901 case BC_OP_CALLFUNCTION:
902 case BC_OP_CALLMETHOD:
905 if( op->Operation == BC_OP_CALLFUNCTION )
907 tScript_Function *fcn = NULL;
908 const char *name = OP_STRING(op);
909 int arg_count = OP_INDX(op);
910 DEBUG_F("CALL (local) %s %i args\n", name, arg_count);
911 // Check current script functions (for fast call)
912 for(fcn = Script->Functions; fcn; fcn = fcn->Next)
914 if(strcmp(name, fcn->Name) == 0) {
918 if(fcn && fcn->BCFcn)
920 DEBUG_F(" - Fast call\n");
921 Bytecode_int_ExecuteFunction(Script, fcn, Stack, arg_count);
927 if( Bytecode_int_CallExternFunction( Script, Stack, default_namespace, op ) ) {
943 AST_RuntimeError(NULL, "Unknown operation %i\n", op->Operation);
951 // - Delete local vars
952 for( i = 0; i < local_var_count; i ++ )
954 if( local_vars[i].Type != ET_NULL )
956 DEBUG_F("Var %i - ", i);
957 PRINT_STACKVAL(local_vars[i]);
958 Bytecode_int_DerefStackValue(&local_vars[i]);
962 DEBUG_F("Var %i - empty\n", i);
966 if( Stack->Entries[Stack->EntryCount - 1].Type == ET_FUNCTION_START )
967 Stack->EntryCount --;
972 while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START )
974 Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] );
978 DEBUG_F("Rolled back %i entries\n", n_rolled);