Usermode/SpiderScript - Restructured namespace handling, fixed a few bytecode bugs
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / exec_bytecode.c
1 /*
2  * SpiderScript Library
3  * by John Hodge (thePowersGang)
4  * 
5  * exec_bytecode.c
6  * - Execute bytecode
7  */
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include "common.h"
11 #include "bytecode.h"
12 #include <stdio.h>
13 #include <string.h>
14 #include "ast.h"
15 #include <inttypes.h>
16
17 #define TRACE   0
18
19 #if TRACE
20 # define DEBUG_F(v...)  printf(v)
21 #else
22 # define DEBUG_F(v...)
23 #endif
24
25 // === IMPORTS ===
26 extern void     AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
27
28 // === TYPES ===
29 typedef struct sBC_StackEnt     tBC_StackEnt;
30 typedef struct sBC_Stack        tBC_Stack;
31
32 enum eBC_StackEntTypes
33 {
34         ET_NULL,        // Start of the stack
35         // SS_DATATYPE_*
36         ET_FUNCTION_START = NUM_SS_DATATYPES,
37         ET_REFERENCE    // Reference to a tSpiderValue
38 };
39
40 struct sBC_StackEnt
41 {
42         uint8_t Type;
43         union {
44                 int64_t Integer;
45                 double  Real;
46                 tSpiderValue    *Reference;     // Used for everything else
47                 tSpiderObject   *Object;
48                 tSpiderNamespace        *Namespace;
49         };
50 };
51
52 struct sBC_Stack
53 {
54          int    EntrySpace;
55          int    EntryCount;
56         tBC_StackEnt    Entries[];
57 };
58
59 // === PROTOTYPES ===
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);
62
63 // === CODE ===
64 int Bytecode_int_StackPop(tBC_Stack *Stack, tBC_StackEnt *Dest)
65 {
66         if( Stack->EntryCount == 0 )    return 1;
67         Stack->EntryCount --;
68         *Dest = Stack->Entries[Stack->EntryCount];
69         return 0;
70 }
71
72 int Bytecode_int_StackPush(tBC_Stack *Stack, tBC_StackEnt *Src)
73 {
74         if( Stack->EntryCount == Stack->EntrySpace )    return 1;
75         Stack->Entries[Stack->EntryCount] = *Src;
76         Stack->EntryCount ++;
77         return 0;
78 }
79
80 int Bytecode_int_IsStackEntTrue(tBC_StackEnt *Ent)
81 {
82         switch(Ent->Type)
83         {
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:
91                 return -1;
92         default:
93                 return SpiderScript_IsValueTrue(Ent->Reference);
94         }
95 }
96
97 tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp)
98 {
99         switch(Ent->Type)
100         {
101         case SS_DATATYPE_INTEGER:
102         case SS_DATATYPE_REAL:
103         case SS_DATATYPE_OBJECT:
104                 if(!tmp) {
105                         tmp = malloc(sizeof(tSpiderValue));
106                         tmp->ReferenceCount = 1;
107                 } else {
108                         tmp->ReferenceCount = 2;
109                 }
110                 break;
111         default:
112                 break;
113         }
114         switch(Ent->Type)
115         {
116         case SS_DATATYPE_INTEGER:
117                 tmp->Type = SS_DATATYPE_INTEGER;
118                 tmp->Integer = Ent->Integer;
119                 return tmp;
120         case SS_DATATYPE_REAL:
121                 tmp->Type = SS_DATATYPE_REAL;
122                 tmp->Real = Ent->Real;
123                 return tmp;
124         case SS_DATATYPE_OBJECT:
125                 tmp->Type = SS_DATATYPE_OBJECT;
126                 tmp->Object = Ent->Object;
127                 return tmp;
128         case ET_FUNCTION_START:
129                 AST_RuntimeError(NULL, "_GetSpiderValue on ET_FUNCTION_START");
130                 return NULL;
131         default:
132                 SpiderScript_ReferenceValue(Ent->Reference);
133                 return Ent->Reference;
134         }
135 }
136
137 void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value)
138 {
139         if(!Value) {
140                 Ent->Type = ET_REFERENCE;
141                 Ent->Reference = NULL;
142                 return ;
143         }
144         switch(Value->Type)
145         {
146         case SS_DATATYPE_INTEGER:
147                 Ent->Type = SS_DATATYPE_INTEGER;
148                 Ent->Integer = Value->Integer;
149                 break;
150         case SS_DATATYPE_REAL:
151                 Ent->Type = SS_DATATYPE_REAL;
152                 Ent->Real = Value->Real;
153                 break;
154         case SS_DATATYPE_OBJECT:
155                 Ent->Type = SS_DATATYPE_OBJECT;
156                 Ent->Object = Value->Object;
157                 Ent->Object->ReferenceCount ++;
158                 break;
159         default:
160                 SpiderScript_ReferenceValue(Value);
161                 Ent->Type = ET_REFERENCE;
162                 Ent->Reference = Value;
163                 break;
164         }
165 }
166
167 void Bytecode_int_DerefStackValue(tBC_StackEnt *Ent)
168 {
169         switch(Ent->Type)
170         {
171         case SS_DATATYPE_INTEGER:
172         case SS_DATATYPE_REAL:
173                 break;
174         case SS_DATATYPE_OBJECT:
175                 if(Ent->Object) {
176                         Ent->Object->ReferenceCount --;
177                         if(Ent->Object->ReferenceCount == 0) {
178                                 Ent->Object->Type->Destructor( Ent->Object );
179                         }
180 //                      printf("Object %p derefed (obj refcount = %i)\n", Ent->Object, Ent->Object->ReferenceCount);
181                 }
182                 Ent->Object = NULL;
183                 break;
184         default:
185                 if(Ent->Reference)
186                         SpiderScript_DereferenceValue(Ent->Reference);
187                 Ent->Reference = NULL;
188                 break;
189         }
190 }
191 void Bytecode_int_RefStackValue(tBC_StackEnt *Ent)
192 {
193         switch(Ent->Type)
194         {
195         case SS_DATATYPE_INTEGER:
196         case SS_DATATYPE_REAL:
197                 break;
198         case SS_DATATYPE_OBJECT:
199                 if(Ent->Object) {
200                         Ent->Object->ReferenceCount ++;
201 //                      printf("Object %p referenced (count = %i)\n", Ent->Object, Ent->Object->ReferenceCount);
202                 }
203                 break;
204         default:
205                 if(Ent->Reference)
206                         SpiderScript_ReferenceValue(Ent->Reference);
207                 break;
208         }
209 }
210
211 void Bytecode_int_PrintStackValue(tBC_StackEnt *Ent)
212 {
213         switch(Ent->Type)
214         {
215         case SS_DATATYPE_INTEGER:
216                 printf("0x%"PRIx64, Ent->Integer);
217                 break;
218         case SS_DATATYPE_REAL:
219                 printf("%lf", Ent->Real);
220                 break;
221         case SS_DATATYPE_OBJECT:
222                 printf("Obj %p", Ent->Object);
223                 break;
224         default:
225                 printf("*%p", Ent->Reference);
226                 break;
227         }
228 }
229
230 #if TRACE
231 # define PRINT_STACKVAL(val)    Bytecode_int_PrintStackValue(&val)
232 #else
233 # define PRINT_STACKVAL(val)
234 #endif
235
236 #define GET_STACKVAL(dst)       if((ret = Bytecode_int_StackPop(Stack, &dst))) { \
237         AST_RuntimeError(NULL, "Stack pop failed, empty stack");\
238         return ret; \
239 }
240 #define PUT_STACKVAL(src)       if((ret = Bytecode_int_StackPush(Stack, &src))) { \
241         AST_RuntimeError(NULL, "Stack push failed, full stack");\
242         return ret; \
243 }
244 #define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer)
245 #define OP_STRING(op_ptr)       ((op_ptr)->Content.StringInt.String)
246
247 tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args)
248 {
249         const int       stack_size = 100;
250         tSpiderValue    *ret, tmpsval;
251         tBC_Stack       *stack;
252         tBC_StackEnt    val;
253          int    i;
254         
255         stack = malloc(sizeof(tBC_Stack) + stack_size*sizeof(tBC_StackEnt));
256         stack->EntrySpace = stack_size;
257         stack->EntryCount = 0;
258
259         // Push arguments in order (so top is last arg)
260         for( i = 0; i < NArguments; i ++ )
261         {
262                 Bytecode_int_SetSpiderValue(&val, Args[i]);
263                 Bytecode_int_StackPush(stack, &val);
264         }
265
266         // Call
267         Bytecode_int_ExecuteFunction(Script, Fcn, stack, NArguments);
268
269         // Get return value
270         if( Bytecode_int_StackPop(stack, &val) ) {
271                 free(stack);
272                 return NULL;
273         }
274         free(stack);
275         
276         ret = Bytecode_int_GetSpiderValue(&val, &tmpsval);
277         // Ensure it's a heap value
278         if(ret == &tmpsval) {
279                 ret = malloc(sizeof(tSpiderValue));
280                 memcpy(ret, &tmpsval, sizeof(tSpiderValue));
281         }
282
283         return ret;
284 }
285
286 tSpiderNamespace *Bytecode_int_ResolveNamespace(tSpiderNamespace *Start, const char *Name, const char **FinalName)
287 {
288         char    *pos;
289         tSpiderNamespace        *ns = Start;
290         while( (pos = strchr(Name, BC_NS_SEPARATOR)) )
291         {
292                  int    len = pos - Name;
293                 for( ns = ns->FirstChild; ns; ns = ns->Next )
294                 {
295                         if(memcmp(ns->Name, Name, len) == 0 && ns->Name[len] == 0)
296                         break;
297                 }
298                 if(!ns) {
299                         return NULL;
300                 }
301                 Name += len + 1;
302         }
303         if(FinalName)   *FinalName = Name;
304         return ns;
305 }
306
307 /**
308  * \brief Call an external function (may recurse into Bytecode_ExecuteFunction, but may not)
309  */
310 int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSpiderNamespace *DefaultNS, tBC_Op *op )
311 {
312         const char      *name = OP_STRING(op);
313          int    arg_count = OP_INDX(op);
314          int    i, ret = 0;
315         tSpiderValue    *args[arg_count];
316         tSpiderValue    *rv;
317         tBC_StackEnt    val1;
318         const char      *namespaces[] = {NULL}; // TODO: Default/imported namespaces
319
320         DEBUG_F("CALL (general) %s %i args\n", name, arg_count);
321         
322         // Read arguments
323         for( i = arg_count; i --; )
324         {
325                 GET_STACKVAL(val1);
326                 args[i] = Bytecode_int_GetSpiderValue(&val1, NULL);
327                 Bytecode_int_DerefStackValue(&val1);
328         }
329         
330         // Call the function etc.
331         if( op->Operation == BC_OP_CALLFUNCTION )
332         {
333                 rv = SpiderScript_ExecuteFunction(Script, name, namespaces, arg_count, args, &op->CacheEnt);
334         }
335         else if( op->Operation == BC_OP_CREATEOBJ )
336         {
337                 rv = SpiderScript_CreateObject(Script, name, namespaces, arg_count, args);
338         }
339         else if( op->Operation == BC_OP_CALLMETHOD )
340         {
341                 tSpiderObject   *obj;
342                 GET_STACKVAL(val1);
343                 
344                 if(val1.Type == SS_DATATYPE_OBJECT)
345                         obj = val1.Object;
346                 else if(val1.Type == ET_REFERENCE && val1.Reference && val1.Reference->Type == SS_DATATYPE_OBJECT)
347                         obj = val1.Reference->Object;
348                 else {
349                         // Error
350                         AST_RuntimeError(NULL, "OP_CALLMETHOD on non object");
351                         return -1;
352                 }
353                 rv = SpiderScript_ExecuteMethod(Script, obj, name, arg_count, args);
354                 Bytecode_int_DerefStackValue(&val1);
355         }
356         else
357         {
358                 AST_RuntimeError(NULL, "BUG - Unknown operation for CALL/CREATEOBJ (%i)", op->Operation);
359                 rv = ERRPTR;
360         }
361         if(rv == ERRPTR) {
362                 AST_RuntimeError(NULL, "SpiderScript_ExecuteFunction returned ERRPTR");
363                 return -1;
364         }
365         // Clean up args
366         for( i = arg_count; i --; )
367                 SpiderScript_DereferenceValue(args[i]);
368         // Get and push return
369         Bytecode_int_SetSpiderValue(&val1, rv);
370         PUT_STACKVAL(val1);
371         // Deref return
372         SpiderScript_DereferenceValue(rv);
373         
374         return ret;
375 }
376
377 int Bytecode_int_LocalBinOp_Integer(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2)
378 {
379         switch(Operation)
380         {
381         case BC_OP_ADD:         Val1->Integer = Val1->Integer + Val2->Integer;  break;
382         case BC_OP_SUBTRACT:    Val1->Integer = Val1->Integer - Val2->Integer;  break;
383         case BC_OP_MULTIPLY:    Val1->Integer = Val1->Integer * Val2->Integer;  break;
384         case BC_OP_DIVIDE:      Val1->Integer = Val1->Integer / Val2->Integer;  break;
385         
386         case BC_OP_EQUALS:              Val1->Integer = (Val1->Integer == Val2->Integer);       break;
387         case BC_OP_NOTEQUALS:           Val1->Integer = (Val1->Integer != Val2->Integer);       break;
388         case BC_OP_LESSTHAN:            Val1->Integer = (Val1->Integer <  Val2->Integer);       break;
389         case BC_OP_LESSTHANOREQUAL:     Val1->Integer = (Val1->Integer <= Val2->Integer);       break;
390         case BC_OP_GREATERTHAN:         Val1->Integer = (Val1->Integer >  Val2->Integer);       break;
391         case BC_OP_GREATERTHANOREQUAL:  Val1->Integer = (Val1->Integer >= Val2->Integer);       break;
392         
393         case BC_OP_BITAND:      Val1->Integer = Val1->Integer & Val2->Integer;  break;
394         case BC_OP_BITOR:       Val1->Integer = Val1->Integer | Val2->Integer;  break;
395         case BC_OP_BITXOR:      Val1->Integer = Val1->Integer ^ Val2->Integer;  break;
396         case BC_OP_MODULO:      Val1->Integer = Val1->Integer % Val2->Integer;  break;
397         default:        AST_RuntimeError(NULL, "Invalid operation on datatype Integer"); return -1;
398         }
399         return 0;
400 }
401
402 int Bytecode_int_LocalBinOp_Real(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2)
403 {
404         switch(Operation)
405         {
406         case BC_OP_ADD:         Val1->Real = Val1->Real + Val2->Real;   return 0;
407         case BC_OP_SUBTRACT:    Val1->Real = Val1->Real - Val2->Real;   return 0;
408         case BC_OP_MULTIPLY:    Val1->Real = Val1->Real * Val2->Real;   return 0;
409         case BC_OP_DIVIDE:      Val1->Real = Val1->Real / Val2->Real;   return 0;
410
411         case BC_OP_EQUALS:              Val1->Integer = (Val1->Real == Val2->Real);     break;
412         case BC_OP_NOTEQUALS:           Val1->Integer = (Val1->Real != Val2->Real);     break;
413         case BC_OP_LESSTHAN:            Val1->Integer = (Val1->Real <  Val2->Real);     break;
414         case BC_OP_LESSTHANOREQUAL:     Val1->Integer = (Val1->Real <= Val2->Real);     break;
415         case BC_OP_GREATERTHAN:         Val1->Integer = (Val1->Real >  Val2->Real);     break;
416         case BC_OP_GREATERTHANOREQUAL:  Val1->Integer = (Val1->Real >= Val2->Real);     break;
417         
418         default:        AST_RuntimeError(NULL, "Invalid operation on datatype Real"); return -1;
419         }
420         Val1->Type = SS_DATATYPE_INTEGER;       // Becomes logical
421         return 0;
422 }
423
424 #define STATE_HDR()     DEBUG_F("%p %2i ", op, Stack->EntryCount)
425
426 /**
427  * \brief Execute a bytecode function with a stack
428  */
429 int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount)
430 {
431          int    ret, ast_op, i;
432         tBC_Op  *op;
433         tBC_StackEnt    val1, val2;
434          int    local_var_count = Fcn->BCFcn->MaxVariableCount;
435         tBC_StackEnt    local_vars[local_var_count];    // Includes arguments
436         tSpiderValue    tmpVal1, tmpVal2;       // temp storage
437         tSpiderValue    *pval1, *pval2, *ret_val;
438         tSpiderNamespace        *default_namespace = &Script->Variant->RootNamespace;
439
440         // Initialise local vars
441         for( i = 0; i < local_var_count; i ++ )
442                 local_vars[i].Type = ET_NULL;
443         
444         // Pop off arguments
445         if( ArgCount > Fcn->ArgumentCount )     return -1;
446         DEBUG_F("Fcn->ArgumentCount = %i\n", Fcn->ArgumentCount);
447         // - Handle optional arguments
448         for( i = Fcn->ArgumentCount; i > ArgCount; )
449         {
450                 i --;
451                 local_vars[i].Integer = 0;
452                 local_vars[i].Type = Fcn->Arguments[i].Type;
453         }
454         for( ; i --; )
455         {
456                 GET_STACKVAL(local_vars[i]);
457                 // TODO: Type checks / enforcing
458         }
459         
460         // Mark the start
461         memset(&val1, 0, sizeof(val1));
462         val1.Type = ET_FUNCTION_START;
463         PUT_STACKVAL(val1);
464
465         // Execute!
466         op = Fcn->BCFcn->Operations;
467         while(op)
468         {
469                 const char      *opstr = "";
470                 tBC_Op  *nextop = op->Next, *jmp_target;
471                 ast_op = 0;
472                 switch(op->Operation)
473                 {
474                 case BC_OP_NOP:
475                         STATE_HDR();
476                         DEBUG_F("NOP\n");
477                         break;
478                 // Jumps
479                 case BC_OP_JUMP:
480                         STATE_HDR();
481                         jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
482                         DEBUG_F("JUMP #%i %p\n", OP_INDX(op), jmp_target);
483                         nextop = jmp_target;
484                         break;
485                 case BC_OP_JUMPIF:
486                         STATE_HDR();
487                         jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
488                         DEBUG_F("JUMPIF #%i %p\n", OP_INDX(op), jmp_target);
489                         GET_STACKVAL(val1);
490                         if( Bytecode_int_IsStackEntTrue(&val1) )
491                                 nextop = jmp_target;
492                         break;
493                 case BC_OP_JUMPIFNOT:
494                         STATE_HDR();
495                         jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
496                         DEBUG_F("JUMPIFNOT #%i %p\n", OP_INDX(op), jmp_target);
497                         GET_STACKVAL(val1);
498                         if( !Bytecode_int_IsStackEntTrue(&val1) )
499                                 nextop = jmp_target;
500                         break;
501                 
502                 // Define variables
503                 case BC_OP_DEFINEVAR: {
504                          int    type, slot;
505                         type = OP_INDX(op) & 0xFFFF;
506                         slot = OP_INDX(op) >> 16;
507                         if(slot < 0 || slot >= local_var_count) {
508                                 DEBUG_F("ERROR: slot %i out of range (max %i)\n", slot, local_var_count);
509                                 return -1;
510                         }
511                         STATE_HDR();
512                         DEBUG_F("DEFVAR %i of type %i\n", slot, type);
513                         if( local_vars[slot].Type != ET_NULL ) {
514                                 Bytecode_int_DerefStackValue( &local_vars[slot] );
515                                 local_vars[slot].Type = ET_NULL;
516                         }
517                         memset(&local_vars[slot], 0, sizeof(local_vars[0]));
518                         local_vars[slot].Type = type;
519                         } break;
520
521                 // Enter/Leave context
522                 // - NOP now            
523                 case BC_OP_ENTERCONTEXT:
524                         STATE_HDR();
525                         DEBUG_F("ENTERCONTEXT\n");
526                         break;
527                 case BC_OP_LEAVECONTEXT:
528                         STATE_HDR();
529                         DEBUG_F("LEAVECONTEXT\n");
530                         break;
531
532                 // Variables
533                 case BC_OP_LOADVAR: {
534                          int    slot = OP_INDX(op);
535                         STATE_HDR();
536                         DEBUG_F("LOADVAR %i ", slot);
537                         if( slot < 0 || slot >= local_var_count ) {
538                                 AST_RuntimeError(NULL, "Loading from invalid slot %i", slot);
539                                 return -1;
540                         }
541                         DEBUG_F("("); PRINT_STACKVAL(local_vars[slot]); DEBUG_F(")\n");
542                         PUT_STACKVAL(local_vars[slot]);
543                         Bytecode_int_RefStackValue( &local_vars[slot] );
544                         } break;
545                 case BC_OP_SAVEVAR: {
546                          int    slot = OP_INDX(op);
547                         STATE_HDR();
548                         DEBUG_F("SAVEVAR %i = ", slot);
549                         if( slot < 0 || slot >= local_var_count ) {
550                                 AST_RuntimeError(NULL, "Loading from invalid slot %i", slot);
551                                 return -1;
552                         }
553                         DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] ");
554                         Bytecode_int_DerefStackValue( &local_vars[slot] );
555                         GET_STACKVAL(local_vars[slot]);
556                         PRINT_STACKVAL(local_vars[slot]);
557                         DEBUG_F("\n");
558                         } break;
559
560                 // Constants:
561                 case BC_OP_LOADINT:
562                         STATE_HDR();
563                         DEBUG_F("LOADINT 0x%lx\n", op->Content.Integer);
564                         val1.Type = SS_DATATYPE_INTEGER;
565                         val1.Integer = op->Content.Integer;
566                         PUT_STACKVAL(val1);
567                         break;
568                 case BC_OP_LOADREAL:
569                         STATE_HDR();
570                         DEBUG_F("LOADREAL %lf\n", op->Content.Real);
571                         val1.Type = SS_DATATYPE_REAL;
572                         val1.Real = op->Content.Real;
573                         PUT_STACKVAL(val1);
574                         break;
575                 case BC_OP_LOADSTR:
576                         STATE_HDR();
577                         DEBUG_F("LOADSTR %i \"%s\"\n", OP_INDX(op), OP_STRING(op));
578                         val1.Type = SS_DATATYPE_STRING;
579                         val1.Reference = SpiderScript_CreateString(OP_INDX(op), OP_STRING(op));
580                         PUT_STACKVAL(val1);
581                         break;
582                 case BC_OP_LOADNULL:
583                         STATE_HDR();
584                         DEBUG_F("LOADNULL\n");
585                         val1.Type = ET_REFERENCE;
586                         val1.Reference = NULL;
587                         PUT_STACKVAL(val1);
588                         break;
589
590                 case BC_OP_CAST:
591                         STATE_HDR();
592                         val2.Type = OP_INDX(op);
593                         DEBUG_F("CAST to %i\n", val2.Type);
594                         GET_STACKVAL(val1);
595                         if(val1.Type == val2.Type) {
596                                 PUT_STACKVAL(val1);
597                                 break;
598                         }
599                         switch(val2.Type * 100 + val1.Type )
600                         {
601                         case SS_DATATYPE_INTEGER*100 + SS_DATATYPE_REAL:
602                                 val2.Integer = val1.Real;
603                                 PUT_STACKVAL(val2);
604                                 break;
605                         case SS_DATATYPE_REAL*100 + SS_DATATYPE_INTEGER:
606                                 val2.Real = val1.Integer;
607                                 PUT_STACKVAL(val2);
608                                 break;
609                         default: {
610                                 pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
611                                 pval2 = SpiderScript_CastValueTo(val2.Type, pval1);
612                                 if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
613                                 Bytecode_int_SetSpiderValue(&val2, pval2);
614                                 SpiderScript_DereferenceValue(pval2);
615                                 PUT_STACKVAL(val2);
616                                 } break;
617                         }
618                         break;
619
620                 case BC_OP_DUPSTACK:
621                         STATE_HDR();
622                         DEBUG_F("DUPSTACK ");
623                         GET_STACKVAL(val1);
624                         PRINT_STACKVAL(val1);
625                         DEBUG_F("\n");
626                         PUT_STACKVAL(val1);
627                         PUT_STACKVAL(val1);
628                         Bytecode_int_RefStackValue(&val1);
629                         break;
630
631                 // Discard the top item from the stack
632                 case BC_OP_DELSTACK:
633                         STATE_HDR();
634                         DEBUG_F("DELSTACK\n");
635                         GET_STACKVAL(val1);
636                         break;
637
638                 // Unary Operations
639                 case BC_OP_LOGICNOT:
640                         STATE_HDR();
641                         DEBUG_F("LOGICNOT\n");
642                         
643                         GET_STACKVAL(val1);
644                         val2.Type = SS_DATATYPE_INTEGER;
645                         val2.Integer = !Bytecode_int_IsStackEntTrue(&val1);
646                         Bytecode_int_StackPush(Stack, &val2);
647                         Bytecode_int_DerefStackValue(&val1);
648                         break;
649                 
650                 case BC_OP_BITNOT:
651                         if(!ast_op)     ast_op = NODETYPE_BWNOT,        opstr = "BITNOT";
652                 case BC_OP_NEG:
653                         if(!ast_op)     ast_op = NODETYPE_NEGATE,       opstr = "NEG";
654
655                         STATE_HDR();
656                         DEBUG_F("%s\n", opstr);
657
658                         GET_STACKVAL(val1);
659                         pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
660                         Bytecode_int_DerefStackValue(&val1);                    
661
662                         ret_val = AST_ExecuteNode_UniOp(Script, NULL, ast_op, pval1);
663                         if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
664                         Bytecode_int_SetSpiderValue(&val1, ret_val);
665                         if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val);
666                         Bytecode_int_StackPush(Stack, &val1);
667                         
668                         break;
669
670                 // Binary Operations
671                 case BC_OP_LOGICAND:
672                         if(!ast_op)     ast_op = NODETYPE_LOGICALAND,   opstr = "LOGICAND";
673                 case BC_OP_LOGICOR:
674                         if(!ast_op)     ast_op = NODETYPE_LOGICALOR,    opstr = "LOGICOR";
675                 case BC_OP_LOGICXOR:
676                         if(!ast_op)     ast_op = NODETYPE_LOGICALXOR,   opstr = "LOGICXOR";
677         
678                         STATE_HDR();
679                         DEBUG_F("%s\n", opstr);
680
681                         GET_STACKVAL(val1);
682                         GET_STACKVAL(val2);
683                         
684                         switch(op->Operation)
685                         {
686                         case BC_OP_LOGICAND:
687                                 i = Bytecode_int_IsStackEntTrue(&val1) && Bytecode_int_IsStackEntTrue(&val2);
688                                 break;
689                         case BC_OP_LOGICOR:
690                                 i = Bytecode_int_IsStackEntTrue(&val1) || Bytecode_int_IsStackEntTrue(&val2);
691                                 break;
692                         case BC_OP_LOGICXOR:
693                                 i = Bytecode_int_IsStackEntTrue(&val1) ^ Bytecode_int_IsStackEntTrue(&val2);
694                                 break;
695                         }
696                         Bytecode_int_DerefStackValue(&val1);
697                         Bytecode_int_DerefStackValue(&val2);
698
699                         val1.Type = SS_DATATYPE_INTEGER;
700                         val1.Integer = i;
701                         Bytecode_int_StackPush(Stack, &val1);
702                         break;
703
704                 case BC_OP_BITAND:
705                         if(!ast_op)     ast_op = NODETYPE_BWAND,        opstr = "BITAND";
706                 case BC_OP_BITOR:
707                         if(!ast_op)     ast_op = NODETYPE_BWOR,         opstr = "BITOR";
708                 case BC_OP_BITXOR:
709                         if(!ast_op)     ast_op = NODETYPE_BWXOR,        opstr = "BITXOR";
710
711                 case BC_OP_BITSHIFTLEFT:
712                         if(!ast_op)     ast_op = NODETYPE_BITSHIFTLEFT, opstr = "BITSHIFTLEFT";
713                 case BC_OP_BITSHIFTRIGHT:
714                         if(!ast_op)     ast_op = NODETYPE_BITSHIFTRIGHT, opstr = "BITSHIFTRIGHT";
715                 case BC_OP_BITROTATELEFT:
716                         if(!ast_op)     ast_op = NODETYPE_BITROTATELEFT, opstr = "BITROTATELEFT";
717
718                 case BC_OP_ADD:
719                         if(!ast_op)     ast_op = NODETYPE_ADD,  opstr = "ADD";
720                 case BC_OP_SUBTRACT:
721                         if(!ast_op)     ast_op = NODETYPE_SUBTRACT,     opstr = "SUBTRACT";
722                 case BC_OP_MULTIPLY:
723                         if(!ast_op)     ast_op = NODETYPE_MULTIPLY,     opstr = "MULTIPLY";
724                 case BC_OP_DIVIDE:
725                         if(!ast_op)     ast_op = NODETYPE_DIVIDE,       opstr = "DIVIDE";
726                 case BC_OP_MODULO:
727                         if(!ast_op)     ast_op = NODETYPE_MODULO,       opstr = "MODULO";
728
729                 case BC_OP_EQUALS:
730                         if(!ast_op)     ast_op = NODETYPE_EQUALS,       opstr = "EQUALS";
731                 case BC_OP_NOTEQUALS:
732                         if(!ast_op)     ast_op = NODETYPE_NOTEQUALS,    opstr = "NOTEQUALS";
733                 case BC_OP_LESSTHAN:
734                         if(!ast_op)     ast_op = NODETYPE_LESSTHAN,     opstr = "LESSTHAN";
735                 case BC_OP_LESSTHANOREQUAL:
736                         if(!ast_op)     ast_op = NODETYPE_LESSTHANEQUAL, opstr = "LESSTHANOREQUAL";
737                 case BC_OP_GREATERTHAN:
738                         if(!ast_op)     ast_op = NODETYPE_GREATERTHAN,  opstr = "GREATERTHAN";
739                 case BC_OP_GREATERTHANOREQUAL:
740                         if(!ast_op)     ast_op = NODETYPE_GREATERTHANEQUAL, opstr = "GREATERTHANOREQUAL";
741
742                         STATE_HDR();
743                         DEBUG_F("BINOP %i %s (bc %i)\n", ast_op, opstr, op->Operation);
744
745                         GET_STACKVAL(val2);     // Right
746                         GET_STACKVAL(val1);     // Left
747
748                         DEBUG_F(" ("); PRINT_STACKVAL(val1); DEBUG_F(")");
749                         DEBUG_F(" ("); PRINT_STACKVAL(val2); DEBUG_F(")\n");
750
751                         // Perform integer operations locally
752                         if( val1.Type == SS_DATATYPE_INTEGER && val2.Type == SS_DATATYPE_INTEGER )
753                         {
754                                 if( Bytecode_int_LocalBinOp_Integer(op->Operation, &val1, &val2) ) {
755                                         nextop = NULL;
756                                         break;
757                                 }
758                                 PUT_STACKVAL(val1);
759                                 break;
760                         }
761
762                         if(val1. Type == SS_DATATYPE_REAL && val2.Type == SS_DATATYPE_REAL )
763                         {
764                                 if( Bytecode_int_LocalBinOp_Real(op->Operation, &val1, &val2) ) {
765                                         nextop = NULL;
766                                         break;
767                                 }
768                                 PUT_STACKVAL(val1);
769                                 break;
770                         }
771                 
772                         pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
773                         pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2);
774                         Bytecode_int_DerefStackValue(&val1);
775                         Bytecode_int_DerefStackValue(&val2);
776
777                         // Hand to AST execution code
778                         ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2);
779                         if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
780                         if(pval2 != &tmpVal2)   SpiderScript_DereferenceValue(pval2);
781
782                         if(ret_val == ERRPTR) {
783                                 AST_RuntimeError(NULL, "_BinOp returned ERRPTR");
784                                 nextop = NULL;
785                                 break;
786                         }
787                         Bytecode_int_SetSpiderValue(&val1, ret_val);
788                         if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val);
789                         PUT_STACKVAL(val1);
790                         break;
791
792                 // Functions etc
793                 case BC_OP_CREATEOBJ:
794                 case BC_OP_CALLFUNCTION:
795                 case BC_OP_CALLMETHOD:
796                         STATE_HDR();
797
798                         if( op->Operation == BC_OP_CALLFUNCTION )
799                         {
800                                 tScript_Function        *fcn = NULL;
801                                 const char      *name = OP_STRING(op);
802                                  int    arg_count = OP_INDX(op);
803                                 DEBUG_F("CALL (local) %s %i args\n", name, arg_count);
804                                 // Check current script functions (for fast call)
805                                 for(fcn = Script->Functions; fcn; fcn = fcn->Next)
806                                 {
807                                         if(strcmp(name, fcn->Name) == 0) {
808                                                 break;
809                                         }
810                                 }
811                                 if(fcn && fcn->BCFcn)
812                                 {
813                                         DEBUG_F(" - Fast call\n");
814                                         Bytecode_int_ExecuteFunction(Script, fcn, Stack, arg_count);
815                                         break;
816                                 }
817                         }
818                 
819                         // Slower call
820                         if( Bytecode_int_CallExternFunction( Script, Stack, default_namespace, op ) ) {
821                                 nextop = NULL;
822                                 break;
823                         }
824                         break;
825
826                 case BC_OP_RETURN:
827                         STATE_HDR();
828
829                         DEBUG_F("RETURN\n");
830                         nextop = NULL;
831                         break;
832
833                 default:
834                         // TODO:
835                         STATE_HDR();
836                         AST_RuntimeError(NULL, "Unknown operation %i\n", op->Operation);
837                         nextop = NULL;
838                         break;
839                 }
840                 op = nextop;
841         }
842         
843         // Clean up
844         // - Delete local vars
845         for( i = 0; i < local_var_count; i ++ )
846         {
847                 if( local_vars[i].Type != ET_NULL )
848                 {
849                         Bytecode_int_DerefStackValue(&local_vars[i]);
850                 }
851         }
852         
853         // - Restore stack
854         if( Stack->Entries[Stack->EntryCount - 1].Type == ET_FUNCTION_START )
855                 Stack->EntryCount --;
856         else
857         {
858                  int    n_rolled = 1;
859                 GET_STACKVAL(val1);
860                 while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START )
861                 {
862                         Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] );
863                         n_rolled ++;
864                 }
865                 PUT_STACKVAL(val1);
866                 DEBUG_F("Rolled back %i entries\n", n_rolled);
867         }
868         
869
870         return 0;
871 }
872

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