SpiderScript - Bugfixing, most bytecode runs now
[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                 uint64_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                 break;
158         default:
159                 SpiderScript_ReferenceValue(Value);
160                 Ent->Type = ET_REFERENCE;
161                 Ent->Reference = Value;
162                 break;
163         }
164 }
165
166 void Bytecode_int_DerefStackValue(tBC_StackEnt *Ent)
167 {
168         switch(Ent->Type)
169         {
170         case SS_DATATYPE_INTEGER:
171         case SS_DATATYPE_REAL:
172         case SS_DATATYPE_OBJECT:
173                 break;
174         default:
175                 SpiderScript_DereferenceValue(Ent->Reference);
176                 break;
177         }
178 }
179 void Bytecode_int_RefStackValue(tBC_StackEnt *Ent)
180 {
181         switch(Ent->Type)
182         {
183         case SS_DATATYPE_INTEGER:
184         case SS_DATATYPE_REAL:
185         case SS_DATATYPE_OBJECT:
186                 break;
187         default:
188                 SpiderScript_ReferenceValue(Ent->Reference);
189                 break;
190         }
191 }
192
193 void Bytecode_int_PrintStackValue(tBC_StackEnt *Ent)
194 {
195         switch(Ent->Type)
196         {
197         case SS_DATATYPE_INTEGER:
198                 printf("0x%"PRIx64, Ent->Integer);
199                 break;
200         case SS_DATATYPE_REAL:
201                 printf("%lf", Ent->Real);
202                 break;
203         case SS_DATATYPE_OBJECT:
204                 printf("Obj %p", Ent->Object);
205                 break;
206         default:
207                 printf("*%p", Ent->Reference);
208                 break;
209         }
210 }
211
212 #if TRACE
213 # define PRINT_STACKVAL(val)    Bytecode_int_PrintStackValue(&val)
214 #else
215 # define PRINT_STACKVAL(val)
216 #endif
217
218 #define GET_STACKVAL(dst)       if((ret = Bytecode_int_StackPop(Stack, &dst))) { \
219         AST_RuntimeError(NULL, "Stack pop failed, empty stack");\
220         return ret; \
221 }
222 #define PUT_STACKVAL(src)       if((ret = Bytecode_int_StackPush(Stack, &src))) { \
223         AST_RuntimeError(NULL, "Stack push failed, full stack");\
224         return ret; \
225 }
226 #define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer)
227 #define OP_STRING(op_ptr)       ((op_ptr)->Content.StringInt.String)
228
229 tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args)
230 {
231         const int       stack_size = 100;
232         tSpiderValue    *ret, tmpsval;
233         tBC_Stack       *stack;
234         tBC_StackEnt    val;
235          int    i;
236         
237         stack = malloc(sizeof(tBC_Stack) + stack_size*sizeof(tBC_StackEnt));
238         stack->EntrySpace = stack_size;
239         stack->EntryCount = 0;
240
241         // Push arguments in order (so top is last arg)
242         for( i = 0; i < NArguments; i ++ )
243         {
244                 Bytecode_int_SetSpiderValue(&val, Args[i]);
245                 Bytecode_int_StackPush(stack, &val);
246         }
247
248         // Call
249         Bytecode_int_ExecuteFunction(Script, Fcn, stack, NArguments);
250
251         // Get return value
252         if( Bytecode_int_StackPop(stack, &val) ) {
253                 free(stack);
254                 return NULL;
255         }
256         free(stack);
257         ret = Bytecode_int_GetSpiderValue(&val, &tmpsval);
258         // Ensure it's a heap value
259         if(ret == &tmpsval) {
260                 ret = malloc(sizeof(tSpiderValue));
261                 memcpy(ret, &tmpsval, sizeof(tSpiderValue));
262         }
263
264         return ret;
265 }
266
267 tSpiderNamespace *Bytecode_int_ResolveNamespace(tSpiderNamespace *Start, const char *Name, const char **FinalName)
268 {
269         char    *pos;
270         tSpiderNamespace        *ns = Start;
271         while( (pos = strchr(Name, BC_NS_SEPARATOR)) )
272         {
273                  int    len = pos - Name;
274                 for( ns = ns->FirstChild; ns; ns = ns->Next )
275                 {
276                         if(memcmp(ns->Name, Name, len) == 0 && ns->Name[len] == 0)
277                         break;
278                 }
279                 if(!ns) {
280                         return NULL;
281                 }
282                 Name += len + 1;
283         }
284         if(FinalName)   *FinalName = Name;
285         return ns;
286 }
287
288 #define STATE_HDR()     DEBUG_F("%p %2i ", op, Stack->EntryCount)
289
290 /**
291  * \brief Execute a bytecode function with a stack
292  */
293 int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount)
294 {
295          int    ret, ast_op, i;
296         tBC_Op  *op;
297         tBC_StackEnt    val1, val2;
298          int    local_var_count = Fcn->BCFcn->MaxVariableCount;
299         tBC_StackEnt    local_vars[local_var_count];    // Includes arguments
300         tSpiderValue    tmpVal1, tmpVal2;       // temp storage
301         tSpiderValue    *pval1, *pval2, *ret_val;
302         tSpiderNamespace        *default_namespace = &Script->Variant->RootNamespace;
303
304         // Initialise local vars
305         for( i = 0; i < local_var_count; i ++ )
306                 local_vars[i].Type = ET_NULL;
307         
308         // Pop off arguments
309         if( ArgCount > Fcn->ArgumentCount )     return -1;
310         DEBUG_F("Fcn->ArgumentCount = %i\n", Fcn->ArgumentCount);
311         for( i = Fcn->ArgumentCount; i > ArgCount; )
312         {
313                 i --;
314                 local_vars[i].Integer = 0;
315                 local_vars[i].Type = Fcn->Arguments[i].Type;
316         }
317         for( ; i --; )
318         {
319                 GET_STACKVAL(local_vars[i]);
320                 // TODO: Type checks / enforcing
321         }
322         
323         // Mark the start
324         memset(&val1, 0, sizeof(val1));
325         val1.Type = ET_FUNCTION_START;
326         PUT_STACKVAL(val1);
327
328         // Execute!
329         op = Fcn->BCFcn->Operations;
330         while(op)
331         {
332                 const char      *opstr = "";
333                 tBC_Op  *nextop = op->Next, *jmp_target;
334                 ast_op = 0;
335                 switch(op->Operation)
336                 {
337                 case BC_OP_NOP:
338                         break;
339                 // Jumps
340                 case BC_OP_JUMP:
341                         STATE_HDR();
342                         // NOTE: Evil, all jumps are off by -1, so fix that
343                         jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
344                         DEBUG_F("JUMP #%i %p\n", OP_INDX(op), jmp_target);
345                         nextop = jmp_target;
346                         break;
347                 case BC_OP_JUMPIF:
348                         STATE_HDR();
349                         jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
350                         DEBUG_F("JUMPIF #%i %p\n", OP_INDX(op), jmp_target);
351                         GET_STACKVAL(val1);
352                         if( Bytecode_int_IsStackEntTrue(&val1) )
353                                 nextop = jmp_target;
354                         break;
355                 case BC_OP_JUMPIFNOT:
356                         STATE_HDR();
357                         jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
358                         DEBUG_F("JUMPIFNOT #%i %p\n", OP_INDX(op), jmp_target);
359                         GET_STACKVAL(val1);
360                         if( !Bytecode_int_IsStackEntTrue(&val1) )
361                                 nextop = jmp_target;
362                         break;
363                 
364                 // Define variables
365                 case BC_OP_DEFINEVAR: {
366                          int    type, slot;
367                         type = OP_INDX(op) & 0xFFFF;
368                         slot = OP_INDX(op) >> 16;
369                         if(slot < 0 || slot >= local_var_count) {
370                                 DEBUG_F("ERROR: slot %i out of range (max %i)\n", slot, local_var_count);
371                                 return -1;
372                         }
373                         STATE_HDR();
374                         DEBUG_F("DEFVAR %i of type %i\n", slot, type);
375                         if( local_vars[slot].Type != ET_NULL ) {
376                                 Bytecode_int_DerefStackValue( &local_vars[slot] );
377                                 local_vars[slot].Type = ET_NULL;
378                         }
379                         memset(&local_vars[slot], 0, sizeof(local_vars[0]));
380                         local_vars[slot].Type = type;
381                         } break;
382
383                 // Enter/Leave context
384                 // - NOP now            
385                 case BC_OP_ENTERCONTEXT:
386                         STATE_HDR();
387                         DEBUG_F("ENTERCONTEXT\n");
388                         break;
389                 case BC_OP_LEAVECONTEXT:
390                         STATE_HDR();
391                         DEBUG_F("LEAVECONTEXT\n");
392                         break;
393
394                 // Variables
395                 case BC_OP_LOADVAR:
396                         STATE_HDR();
397                         DEBUG_F("LOADVAR %i ", OP_INDX(op));
398                         if( OP_INDX(op) < 0 || OP_INDX(op) >= local_var_count ) {
399                                 AST_RuntimeError(NULL, "Loading from invalid slot %i", OP_INDX(op));
400                                 return -1;
401                         }
402                         DEBUG_F("("); PRINT_STACKVAL(local_vars[OP_INDX(op)]); DEBUG_F(")\n");
403                         PUT_STACKVAL(local_vars[OP_INDX(op)]);
404                         Bytecode_int_RefStackValue( &local_vars[OP_INDX(op)] );
405                         break;
406                 case BC_OP_SAVEVAR:
407                         STATE_HDR();
408                         DEBUG_F("SAVEVAR %i = ", OP_INDX(op));
409                         if( OP_INDX(op) < 0 || OP_INDX(op) >= local_var_count ) {
410                                 AST_RuntimeError(NULL, "Loading from invalid slot %i", OP_INDX(op));
411                                 return -1;
412                         }
413                         PRINT_STACKVAL(local_vars[OP_INDX(op)]);
414                         DEBUG_F("\n");
415                         GET_STACKVAL(local_vars[OP_INDX(op)]);
416                         break;
417
418                 // Constants:
419                 case BC_OP_LOADINT:
420                         STATE_HDR();
421                         DEBUG_F("LOADINT 0x%lx\n", op->Content.Integer);
422                         val1.Type = SS_DATATYPE_INTEGER;
423                         val1.Integer = op->Content.Integer;
424                         PUT_STACKVAL(val1);
425                         break;
426                 case BC_OP_LOADREAL:
427                         STATE_HDR();
428                         DEBUG_F("LOADREAL %lf\n", op->Content.Real);
429                         val1.Type = SS_DATATYPE_REAL;
430                         val1.Real = op->Content.Real;
431                         PUT_STACKVAL(val1);
432                         break;
433                 case BC_OP_LOADSTR:
434                         STATE_HDR();
435                         DEBUG_F("LOADSTR %i \"%s\"\n", OP_INDX(op), OP_STRING(op));
436                         val1.Type = SS_DATATYPE_STRING;
437                         val1.Reference = SpiderScript_CreateString(OP_INDX(op), OP_STRING(op));
438                         PUT_STACKVAL(val1);
439                         break;
440
441                 case BC_OP_CAST:
442                         STATE_HDR();
443                         val2.Type = OP_INDX(op);
444                         DEBUG_F("CAST to %i\n", val2.Type);
445                         GET_STACKVAL(val1);
446                         if(val1.Type == val2.Type) {
447                                 PUT_STACKVAL(val1);
448                                 break;
449                         }
450                         switch(val2.Type * 100 + val1.Type )
451                         {
452                         case SS_DATATYPE_INTEGER*100 + SS_DATATYPE_REAL:
453                                 val2.Integer = val1.Real;
454                                 PUT_STACKVAL(val2);
455                                 break;
456                         case SS_DATATYPE_REAL*100 + SS_DATATYPE_INTEGER:
457                                 val2.Real = val1.Integer;
458                                 PUT_STACKVAL(val2);
459                                 break;
460                         default: {
461                                 pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
462                                 pval2 = SpiderScript_CastValueTo(val2.Type, pval1);
463                                 if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
464                                 Bytecode_int_SetSpiderValue(&val2, pval2);
465                                 SpiderScript_DereferenceValue(pval2);
466                                 PUT_STACKVAL(val2);
467                                 } break;
468                         }
469                         break;
470
471                 case BC_OP_DUPSTACK:
472                         STATE_HDR();
473                         DEBUG_F("DUPSTACK ");
474                         GET_STACKVAL(val1);
475                         PRINT_STACKVAL(val1);
476                         DEBUG_F("\n");
477                         PUT_STACKVAL(val1);
478                         PUT_STACKVAL(val1);
479                         Bytecode_int_RefStackValue(&val1);
480                         break;
481
482                 // Discard the top item from the stack
483                 case BC_OP_DELSTACK:
484                         STATE_HDR();
485                         DEBUG_F("DELSTACK\n");
486                         GET_STACKVAL(val1);
487                         break;
488
489                 // Unary Operations
490                 case BC_OP_LOGICNOT:
491                         STATE_HDR();
492                         DEBUG_F("LOGICNOT\n");
493                         
494                         GET_STACKVAL(val1);
495                         val2.Type = SS_DATATYPE_INTEGER;
496                         val2.Integer = !Bytecode_int_IsStackEntTrue(&val1);
497                         Bytecode_int_StackPush(Stack, &val2);
498                         Bytecode_int_DerefStackValue(&val1);
499                         break;
500                 case BC_OP_BITNOT:
501                         if(!ast_op)     ast_op = NODETYPE_BWNOT;
502
503                         STATE_HDR();
504                         DEBUG_F("UNIOP %i\n", ast_op);
505
506                         GET_STACKVAL(val1);
507                         pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
508                         Bytecode_int_DerefStackValue(&val1);                    
509
510                         ret_val = AST_ExecuteNode_UniOp(Script, NULL, ast_op, pval1);
511                         if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
512                         Bytecode_int_SetSpiderValue(&val1, ret_val);
513                         if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val);
514                         Bytecode_int_StackPush(Stack, &val1);
515                         
516                         break;
517
518                 // Binary Operations
519                 case BC_OP_LOGICAND:
520                         if(!ast_op)     ast_op = NODETYPE_LOGICALAND,   opstr = "LOGICAND";
521                 case BC_OP_LOGICOR:
522                         if(!ast_op)     ast_op = NODETYPE_LOGICALOR,    opstr = "LOGICOR";
523                 case BC_OP_LOGICXOR:
524                         if(!ast_op)     ast_op = NODETYPE_LOGICALXOR,   opstr = "LOGICXOR";
525
526                 case BC_OP_BITAND:
527                         if(!ast_op)     ast_op = NODETYPE_BWAND,        opstr = "BITAND";
528                 case BC_OP_BITOR:
529                         if(!ast_op)     ast_op = NODETYPE_BWOR,         opstr = "BITOR";
530                 case BC_OP_BITXOR:
531                         if(!ast_op)     ast_op = NODETYPE_BWXOR,        opstr = "BITXOR";
532
533                 case BC_OP_BITSHIFTLEFT:
534                         if(!ast_op)     ast_op = NODETYPE_BITSHIFTLEFT, opstr = "BITSHIFTLEFT";
535                 case BC_OP_BITSHIFTRIGHT:
536                         if(!ast_op)     ast_op = NODETYPE_BITSHIFTRIGHT, opstr = "BITSHIFTRIGHT";
537                 case BC_OP_BITROTATELEFT:
538                         if(!ast_op)     ast_op = NODETYPE_BITROTATELEFT, opstr = "BITROTATELEFT";
539
540                 case BC_OP_ADD:
541                         if(!ast_op)     ast_op = NODETYPE_ADD,  opstr = "ADD";
542                 case BC_OP_SUBTRACT:
543                         if(!ast_op)     ast_op = NODETYPE_SUBTRACT,     opstr = "SUBTRACT";
544                 case BC_OP_MULTIPLY:
545                         if(!ast_op)     ast_op = NODETYPE_MULTIPLY,     opstr = "MULTIPLY";
546                 case BC_OP_DIVIDE:
547                         if(!ast_op)     ast_op = NODETYPE_DIVIDE,       opstr = "DIVIDE";
548                 case BC_OP_MODULO:
549                         if(!ast_op)     ast_op = NODETYPE_MODULO,       opstr = "MODULO";
550
551                 case BC_OP_EQUALS:
552                         if(!ast_op)     ast_op = NODETYPE_EQUALS,       opstr = "EQUALS";
553                 case BC_OP_LESSTHAN:
554                         if(!ast_op)     ast_op = NODETYPE_LESSTHAN,     opstr = "LESSTHAN";
555                 case BC_OP_LESSTHANOREQUAL:
556                         if(!ast_op)     ast_op = NODETYPE_LESSTHANEQUAL, opstr = "LESSTHANOREQUAL";
557                 case BC_OP_GREATERTHAN:
558                         if(!ast_op)     ast_op = NODETYPE_GREATERTHAN,  opstr = "GREATERTHAN";
559                 case BC_OP_GREATERTHANOREQUAL:
560                         if(!ast_op)     ast_op = NODETYPE_GREATERTHANEQUAL, opstr = "GREATERTHANOREQUAL";
561
562                         STATE_HDR();
563                         DEBUG_F("BINOP %i %s (bc %i)\n", ast_op, opstr, op->Operation);
564
565                         GET_STACKVAL(val2);     // Right
566                         GET_STACKVAL(val1);     // Left
567                         pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
568                         pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2);
569                         Bytecode_int_DerefStackValue(&val1);
570                         Bytecode_int_DerefStackValue(&val2);
571
572                         ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2);
573                         if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
574                         if(pval2 != &tmpVal2)   SpiderScript_DereferenceValue(pval2);
575                         Bytecode_int_SetSpiderValue(&val1, ret_val);
576                         if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val);
577                         PUT_STACKVAL(val1);
578                         break;
579
580                 // Functions etc
581                 case BC_OP_CALLFUNCTION: {
582                         tScript_Function        *fcn;
583                         const char      *name = OP_STRING(op);
584                          int    arg_count = OP_INDX(op);
585                         
586                         STATE_HDR();
587                         DEBUG_F("CALL FUNCTION %s %i args\n", name, arg_count);
588
589                         // Check current script functions (for fast call)
590                         for(fcn = Script->Functions; fcn; fcn = fcn->Next)
591                         {
592                                 if(strcmp(name, fcn->Name) == 0) {
593                                         break;
594                                 }
595                         }
596                         if(fcn && fcn->BCFcn)
597                         {
598                                 DEBUG_F(" - Fast call\n");
599                                 Bytecode_int_ExecuteFunction(Script, fcn, Stack, arg_count);
600                                 break;
601                         }
602                         
603                         // Slower call
604                         {
605                                 tSpiderNamespace        *ns = NULL;
606                                 tSpiderValue    *args[arg_count];
607                                 tSpiderValue    *rv;
608 //                              for( i = 0; i < arg_count; i ++ )
609                                 for( i = arg_count; i --; )
610                                 {
611                                         GET_STACKVAL(val1);
612                                         args[i] = Bytecode_int_GetSpiderValue(&val1, NULL);
613                                         Bytecode_int_DerefStackValue(&val1);
614                                 }
615                                 
616                                 if( name[0] == BC_NS_SEPARATOR ) {
617                                         name ++;
618                                         ns = Bytecode_int_ResolveNamespace(&Script->Variant->RootNamespace, name, &name);
619                                 }
620                                 else {
621                                         // TODO: Support multiple default namespaces
622                                         ns = Bytecode_int_ResolveNamespace(default_namespace, name, &name);
623                                 }
624                                 
625                                 rv = SpiderScript_ExecuteFunction(Script, ns, name, arg_count, args);
626                                 if(rv == ERRPTR) {
627                                         AST_RuntimeError(NULL, "SpiderScript_ExecuteFunction returned ERRPTR");
628                                         nextop = NULL;
629                                         break;
630                                 }
631                                 // Clean up args
632                                 for( i = arg_count; i --; )
633                                         SpiderScript_DereferenceValue(args[i]);
634                                 // Get and push return
635                                 Bytecode_int_SetSpiderValue(&val1, rv);
636                                 PUT_STACKVAL(val1);
637                                 // Deref return
638                                 SpiderScript_DereferenceValue(rv);
639                         }
640                         } break;
641
642                 case BC_OP_RETURN:
643                         STATE_HDR();
644                         DEBUG_F("RETURN\n");
645                         nextop = NULL;
646                         break;
647
648                 default:
649                         // TODO:
650                         STATE_HDR();
651                         printf("Unknown operation %i\n", op->Operation);
652                         nextop = NULL;
653                         break;
654                 }
655                 op = nextop;
656         }
657         
658         // Clean up
659         // - Delete local vars
660         for( i = 0; i < local_var_count; i ++ )
661         {
662                 if( local_vars[i].Type != ET_NULL )
663                 {
664                         Bytecode_int_DerefStackValue(&local_vars[i]);
665                 }
666         }
667         
668         // - Restore stack
669 //      printf("TODO: Roll back stack\n");
670         if( Stack->Entries[Stack->EntryCount - 1].Type == ET_FUNCTION_START )
671                 Stack->EntryCount --;
672         else
673         {
674                 GET_STACKVAL(val1);
675                 while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START )
676                 {
677                         Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] );
678                 }
679                 PUT_STACKVAL(val1);
680         }
681         
682
683         return 0;
684 }
685

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