3 * by John Hodge (thePowersGang)
6 * - Generate a bytecode file
10 #include <spiderscript.h>
15 typedef struct sBC_StackEnt tBC_StackEnt;
16 typedef struct sBC_Stack tBC_Stack;
18 enum eBC_StackEntTypes
20 ET_NULL, // Start of the stack
22 ET_FUNCTION_START = NUM_SS_DATATYPES,
23 ET_REFERENCE // Reference to a tSpiderValue
32 tSpiderValue *Reference; // Used for everything else
33 tSpiderObject *Object;
41 tBC_StackEnt Entries[];
45 int Bytecode_int_StackPop(tBC_Stack *Stack, tBC_StackEnt *Dest)
47 if( Stack->EntryCount == 0 ) return 1;
49 *Dest = Stack->Entries[Stack->EntryCount];
53 int Bytecode_int_StackPush(tBC_Stack *Stack, tBC_StackEnt *Src)
55 if( Stack->EntryCount == Stack->EntrySpace ) return 1;
56 Stack->Entries[Stack->EntryCount] = *Src;
61 int Bytecode_int_IsStackEntTrue(tBC_StackEnt *Ent)
65 case SS_DATATYPE_INTEGER:
66 return !!Ent->Integer;
67 case SS_DATATYPE_REAL:
68 return (-.5f < Ent->Real && Ent->Real < 0.5f);
69 case SS_DATATYPE_OBJECT:
70 return Ent->Object != NULL;
71 case ET_FUNCTION_START:
74 return SpiderScript_IsValueTrue(Ent->Reference);
78 tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp)
82 case SS_DATATYPE_INTEGER:
83 tmp->Type = SS_DATATYPE_INTEGER;
84 tmp->ReferenceCount = 2; // Stops it being freed
85 tmp->Integer = Ent->Integer;
87 case SS_DATATYPE_REAL:
88 tmp->Type = SS_DATATYPE_REAL;
89 tmp->ReferenceCount = 2; // Stops it being freed
90 tmp->Real = Ent->Real;
92 case SS_DATATYPE_OBJECT:
93 tmp->Type = SS_DATATYPE_OBJECT;
94 tmp->ReferenceCount = 2;
95 tmp->Object = Ent->Object;
97 case ET_FUNCTION_START:
100 return Ent->Reference;
104 void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value)
108 case SS_DATATYPE_INTEGER:
109 Ent->Type = SS_DATATYPE_INTEGER;
110 Ent->Integer = Value->Integer;
112 case SS_DATATYPE_REAL:
113 Ent->Type = SS_DATATYPE_REAL;
114 Ent->Real = Value->Real;
116 case SS_DATATYPE_OBJECT:
117 Ent->Type = SS_DATATYPE_OBJECT;
118 Ent->Object = Value->Object;
121 SpiderScript_ReferenceValue(Value);
122 Ent->Reference = Value;
127 #define GET_STACKVAL(dst) if((ret = Bytecode_int_StackPop(Stack, &dst))) return ret;
128 #define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer)
129 #define OP_STRING(op_ptr) ((op_ptr)->Content.StringInt.String)
131 int Bytecode_ExecuteFunction(tSpiderScript *Script, tBC_Function *Fcn, tBC_Stack *Stack, int ArgCount)
135 tBC_StackEnt val1, val2;
136 tBC_StackEnt local_vars[Fcn->MaxVariableCount]; // Includes arguments
137 tSpiderValue tmpVal1, tmpVal2; // temp storage
138 tSpiderValue *pval1, *pval2, *ret_val;
141 if( ArgCount > Fcn->ArgumentCount ) return -1;
142 for( i = Fcn->ArgumentCount; --i != ArgCount; )
144 local_vars[i].Integer = 0;
145 local_vars[i].Type = Fcn->Arguments[i].Type;
149 GET_STACKVAL(local_vars[i]);
150 // TODO: Type checks / enforcing
154 memset(&val1, 0, sizeof(val1));
155 val1.Type = ET_FUNCTION_START;
156 Bytecode_int_StackPush(Stack, &val1);
159 op = Fcn->Operations;
162 tBC_Op *nextop = op->Next;
164 switch(op->Operation)
168 nextop = Fcn->Labels[ OP_INDX(op) ];
172 if( Bytecode_int_IsStackEntTrue(&val1) )
173 nextop = Fcn->Labels[op->Content.StringInt.Integer];
175 case BC_OP_JUMPIFNOT:
177 if( !Bytecode_int_IsStackEntTrue(&val1) )
178 nextop = Fcn->Labels[op->Content.StringInt.Integer];
182 case BC_OP_DEFINEVAR: {
184 type = OP_INDX(op) & 0xFFFF;
185 slot = OP_INDX(op) >> 16;
186 if(slot < 0 || slot >= sizeof(local_vars)/sizeof(local_vars[0])) return -1;
187 memset(&local_vars[slot], 0, sizeof(local_vars[0]));
188 local_vars[slot].Type = type;
193 ast_op = NODETYPE_ADD;
195 if(!ast_op) ast_op = NODETYPE_SUBTRACT;
199 pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
200 pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2);
201 ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2);
202 if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
203 if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2);
204 Bytecode_int_SetSpiderValue(&val1, ret_val);
205 if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val);
216 // - Delete local vars