The Squirrel interpreter. See http://www.squirrel-lang.org/
squirrel/sqvm.cpp@0:97a4f8cc534c, 2014-12-16 (annotated)
- Committer:
- jhnwkmn
- Date:
- Tue Dec 16 10:20:34 2014 +0000
- Revision:
- 0:97a4f8cc534c
- Child:
- 1:8a2835ae5c5d
Initial import of Squirrel.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jhnwkmn | 0:97a4f8cc534c | 1 | /* |
jhnwkmn | 0:97a4f8cc534c | 2 | see copyright notice in squirrel.h |
jhnwkmn | 0:97a4f8cc534c | 3 | */ |
jhnwkmn | 0:97a4f8cc534c | 4 | #include "sqpcheader.h" |
jhnwkmn | 0:97a4f8cc534c | 5 | #include <math.h> |
jhnwkmn | 0:97a4f8cc534c | 6 | #include <stdlib.h> |
jhnwkmn | 0:97a4f8cc534c | 7 | #include "sqopcodes.h" |
jhnwkmn | 0:97a4f8cc534c | 8 | #include "sqvm.h" |
jhnwkmn | 0:97a4f8cc534c | 9 | #include "sqfuncproto.h" |
jhnwkmn | 0:97a4f8cc534c | 10 | #include "sqclosure.h" |
jhnwkmn | 0:97a4f8cc534c | 11 | #include "sqstring.h" |
jhnwkmn | 0:97a4f8cc534c | 12 | #include "sqtable.h" |
jhnwkmn | 0:97a4f8cc534c | 13 | #include "squserdata.h" |
jhnwkmn | 0:97a4f8cc534c | 14 | #include "sqarray.h" |
jhnwkmn | 0:97a4f8cc534c | 15 | #include "sqclass.h" |
jhnwkmn | 0:97a4f8cc534c | 16 | |
jhnwkmn | 0:97a4f8cc534c | 17 | #define TOP() (_stack._vals[_top-1]) |
jhnwkmn | 0:97a4f8cc534c | 18 | |
jhnwkmn | 0:97a4f8cc534c | 19 | bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) |
jhnwkmn | 0:97a4f8cc534c | 20 | { |
jhnwkmn | 0:97a4f8cc534c | 21 | SQInteger res; |
jhnwkmn | 0:97a4f8cc534c | 22 | if((type(o1)|type(o2)) == OT_INTEGER) |
jhnwkmn | 0:97a4f8cc534c | 23 | { |
jhnwkmn | 0:97a4f8cc534c | 24 | SQInteger i1 = _integer(o1), i2 = _integer(o2); |
jhnwkmn | 0:97a4f8cc534c | 25 | switch(op) { |
jhnwkmn | 0:97a4f8cc534c | 26 | case BW_AND: res = i1 & i2; break; |
jhnwkmn | 0:97a4f8cc534c | 27 | case BW_OR: res = i1 | i2; break; |
jhnwkmn | 0:97a4f8cc534c | 28 | case BW_XOR: res = i1 ^ i2; break; |
jhnwkmn | 0:97a4f8cc534c | 29 | case BW_SHIFTL: res = i1 << i2; break; |
jhnwkmn | 0:97a4f8cc534c | 30 | case BW_SHIFTR: res = i1 >> i2; break; |
jhnwkmn | 0:97a4f8cc534c | 31 | case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; |
jhnwkmn | 0:97a4f8cc534c | 32 | default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } |
jhnwkmn | 0:97a4f8cc534c | 33 | } |
jhnwkmn | 0:97a4f8cc534c | 34 | } |
jhnwkmn | 0:97a4f8cc534c | 35 | else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} |
jhnwkmn | 0:97a4f8cc534c | 36 | trg = res; |
jhnwkmn | 0:97a4f8cc534c | 37 | return true; |
jhnwkmn | 0:97a4f8cc534c | 38 | } |
jhnwkmn | 0:97a4f8cc534c | 39 | |
jhnwkmn | 0:97a4f8cc534c | 40 | #define _ARITH_(op,trg,o1,o2) \ |
jhnwkmn | 0:97a4f8cc534c | 41 | { \ |
jhnwkmn | 0:97a4f8cc534c | 42 | SQInteger tmask = type(o1)|type(o2); \ |
jhnwkmn | 0:97a4f8cc534c | 43 | switch(tmask) { \ |
jhnwkmn | 0:97a4f8cc534c | 44 | case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \ |
jhnwkmn | 0:97a4f8cc534c | 45 | case (OT_FLOAT|OT_INTEGER): \ |
jhnwkmn | 0:97a4f8cc534c | 46 | case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ |
jhnwkmn | 0:97a4f8cc534c | 47 | default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ |
jhnwkmn | 0:97a4f8cc534c | 48 | } \ |
jhnwkmn | 0:97a4f8cc534c | 49 | } |
jhnwkmn | 0:97a4f8cc534c | 50 | |
jhnwkmn | 0:97a4f8cc534c | 51 | #define _ARITH_NOZERO(op,trg,o1,o2,err) \ |
jhnwkmn | 0:97a4f8cc534c | 52 | { \ |
jhnwkmn | 0:97a4f8cc534c | 53 | SQInteger tmask = type(o1)|type(o2); \ |
jhnwkmn | 0:97a4f8cc534c | 54 | switch(tmask) { \ |
jhnwkmn | 0:97a4f8cc534c | 55 | case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\ |
jhnwkmn | 0:97a4f8cc534c | 56 | case (OT_FLOAT|OT_INTEGER): \ |
jhnwkmn | 0:97a4f8cc534c | 57 | case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ |
jhnwkmn | 0:97a4f8cc534c | 58 | default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ |
jhnwkmn | 0:97a4f8cc534c | 59 | } \ |
jhnwkmn | 0:97a4f8cc534c | 60 | } |
jhnwkmn | 0:97a4f8cc534c | 61 | |
jhnwkmn | 0:97a4f8cc534c | 62 | bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) |
jhnwkmn | 0:97a4f8cc534c | 63 | { |
jhnwkmn | 0:97a4f8cc534c | 64 | SQInteger tmask = type(o1)|type(o2); |
jhnwkmn | 0:97a4f8cc534c | 65 | switch(tmask) { |
jhnwkmn | 0:97a4f8cc534c | 66 | case OT_INTEGER:{ |
jhnwkmn | 0:97a4f8cc534c | 67 | SQInteger res, i1 = _integer(o1), i2 = _integer(o2); |
jhnwkmn | 0:97a4f8cc534c | 68 | switch(op) { |
jhnwkmn | 0:97a4f8cc534c | 69 | case '+': res = i1 + i2; break; |
jhnwkmn | 0:97a4f8cc534c | 70 | case '-': res = i1 - i2; break; |
jhnwkmn | 0:97a4f8cc534c | 71 | case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; } |
jhnwkmn | 0:97a4f8cc534c | 72 | res = i1 / i2; |
jhnwkmn | 0:97a4f8cc534c | 73 | break; |
jhnwkmn | 0:97a4f8cc534c | 74 | case '*': res = i1 * i2; break; |
jhnwkmn | 0:97a4f8cc534c | 75 | case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } |
jhnwkmn | 0:97a4f8cc534c | 76 | res = i1 % i2; |
jhnwkmn | 0:97a4f8cc534c | 77 | break; |
jhnwkmn | 0:97a4f8cc534c | 78 | default: res = 0xDEADBEEF; |
jhnwkmn | 0:97a4f8cc534c | 79 | } |
jhnwkmn | 0:97a4f8cc534c | 80 | trg = res; } |
jhnwkmn | 0:97a4f8cc534c | 81 | break; |
jhnwkmn | 0:97a4f8cc534c | 82 | case (OT_FLOAT|OT_INTEGER): |
jhnwkmn | 0:97a4f8cc534c | 83 | case (OT_FLOAT):{ |
jhnwkmn | 0:97a4f8cc534c | 84 | SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); |
jhnwkmn | 0:97a4f8cc534c | 85 | switch(op) { |
jhnwkmn | 0:97a4f8cc534c | 86 | case '+': res = f1 + f2; break; |
jhnwkmn | 0:97a4f8cc534c | 87 | case '-': res = f1 - f2; break; |
jhnwkmn | 0:97a4f8cc534c | 88 | case '/': res = f1 / f2; break; |
jhnwkmn | 0:97a4f8cc534c | 89 | case '*': res = f1 * f2; break; |
jhnwkmn | 0:97a4f8cc534c | 90 | case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; |
jhnwkmn | 0:97a4f8cc534c | 91 | default: res = 0x0f; |
jhnwkmn | 0:97a4f8cc534c | 92 | } |
jhnwkmn | 0:97a4f8cc534c | 93 | trg = res; } |
jhnwkmn | 0:97a4f8cc534c | 94 | break; |
jhnwkmn | 0:97a4f8cc534c | 95 | default: |
jhnwkmn | 0:97a4f8cc534c | 96 | if(op == '+' && (tmask & _RT_STRING)){ |
jhnwkmn | 0:97a4f8cc534c | 97 | if(!StringCat(o1, o2, trg)) return false; |
jhnwkmn | 0:97a4f8cc534c | 98 | } |
jhnwkmn | 0:97a4f8cc534c | 99 | else if(!ArithMetaMethod(op,o1,o2,trg)) { |
jhnwkmn | 0:97a4f8cc534c | 100 | return false; |
jhnwkmn | 0:97a4f8cc534c | 101 | } |
jhnwkmn | 0:97a4f8cc534c | 102 | } |
jhnwkmn | 0:97a4f8cc534c | 103 | return true; |
jhnwkmn | 0:97a4f8cc534c | 104 | } |
jhnwkmn | 0:97a4f8cc534c | 105 | |
jhnwkmn | 0:97a4f8cc534c | 106 | SQVM::SQVM(SQSharedState *ss) |
jhnwkmn | 0:97a4f8cc534c | 107 | { |
jhnwkmn | 0:97a4f8cc534c | 108 | _sharedstate=ss; |
jhnwkmn | 0:97a4f8cc534c | 109 | _suspended = SQFalse; |
jhnwkmn | 0:97a4f8cc534c | 110 | _suspended_target = -1; |
jhnwkmn | 0:97a4f8cc534c | 111 | _suspended_root = SQFalse; |
jhnwkmn | 0:97a4f8cc534c | 112 | _suspended_traps = -1; |
jhnwkmn | 0:97a4f8cc534c | 113 | _foreignptr = NULL; |
jhnwkmn | 0:97a4f8cc534c | 114 | _nnativecalls = 0; |
jhnwkmn | 0:97a4f8cc534c | 115 | _nmetamethodscall = 0; |
jhnwkmn | 0:97a4f8cc534c | 116 | _lasterror.Null(); |
jhnwkmn | 0:97a4f8cc534c | 117 | _errorhandler.Null(); |
jhnwkmn | 0:97a4f8cc534c | 118 | _debughook = false; |
jhnwkmn | 0:97a4f8cc534c | 119 | _debughook_native = NULL; |
jhnwkmn | 0:97a4f8cc534c | 120 | _debughook_closure.Null(); |
jhnwkmn | 0:97a4f8cc534c | 121 | _openouters = NULL; |
jhnwkmn | 0:97a4f8cc534c | 122 | ci = NULL; |
jhnwkmn | 0:97a4f8cc534c | 123 | INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); |
jhnwkmn | 0:97a4f8cc534c | 124 | } |
jhnwkmn | 0:97a4f8cc534c | 125 | |
jhnwkmn | 0:97a4f8cc534c | 126 | void SQVM::Finalize() |
jhnwkmn | 0:97a4f8cc534c | 127 | { |
jhnwkmn | 0:97a4f8cc534c | 128 | if(_openouters) CloseOuters(&_stack._vals[0]); |
jhnwkmn | 0:97a4f8cc534c | 129 | _roottable.Null(); |
jhnwkmn | 0:97a4f8cc534c | 130 | _lasterror.Null(); |
jhnwkmn | 0:97a4f8cc534c | 131 | _errorhandler.Null(); |
jhnwkmn | 0:97a4f8cc534c | 132 | _debughook = false; |
jhnwkmn | 0:97a4f8cc534c | 133 | _debughook_native = NULL; |
jhnwkmn | 0:97a4f8cc534c | 134 | _debughook_closure.Null(); |
jhnwkmn | 0:97a4f8cc534c | 135 | temp_reg.Null(); |
jhnwkmn | 0:97a4f8cc534c | 136 | _callstackdata.resize(0); |
jhnwkmn | 0:97a4f8cc534c | 137 | SQInteger size=_stack.size(); |
jhnwkmn | 0:97a4f8cc534c | 138 | for(SQInteger i=0;i<size;i++) |
jhnwkmn | 0:97a4f8cc534c | 139 | _stack[i].Null(); |
jhnwkmn | 0:97a4f8cc534c | 140 | } |
jhnwkmn | 0:97a4f8cc534c | 141 | |
jhnwkmn | 0:97a4f8cc534c | 142 | SQVM::~SQVM() |
jhnwkmn | 0:97a4f8cc534c | 143 | { |
jhnwkmn | 0:97a4f8cc534c | 144 | Finalize(); |
jhnwkmn | 0:97a4f8cc534c | 145 | REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); |
jhnwkmn | 0:97a4f8cc534c | 146 | } |
jhnwkmn | 0:97a4f8cc534c | 147 | |
jhnwkmn | 0:97a4f8cc534c | 148 | bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest) |
jhnwkmn | 0:97a4f8cc534c | 149 | { |
jhnwkmn | 0:97a4f8cc534c | 150 | SQMetaMethod mm; |
jhnwkmn | 0:97a4f8cc534c | 151 | switch(op){ |
jhnwkmn | 0:97a4f8cc534c | 152 | case _SC('+'): mm=MT_ADD; break; |
jhnwkmn | 0:97a4f8cc534c | 153 | case _SC('-'): mm=MT_SUB; break; |
jhnwkmn | 0:97a4f8cc534c | 154 | case _SC('/'): mm=MT_DIV; break; |
jhnwkmn | 0:97a4f8cc534c | 155 | case _SC('*'): mm=MT_MUL; break; |
jhnwkmn | 0:97a4f8cc534c | 156 | case _SC('%'): mm=MT_MODULO; break; |
jhnwkmn | 0:97a4f8cc534c | 157 | default: mm = MT_ADD; assert(0); break; //shutup compiler |
jhnwkmn | 0:97a4f8cc534c | 158 | } |
jhnwkmn | 0:97a4f8cc534c | 159 | if(is_delegable(o1) && _delegable(o1)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 160 | |
jhnwkmn | 0:97a4f8cc534c | 161 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 162 | if(_delegable(o1)->GetMetaMethod(this, mm, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 163 | Push(o1);Push(o2); |
jhnwkmn | 0:97a4f8cc534c | 164 | return CallMetaMethod(closure,mm,2,dest); |
jhnwkmn | 0:97a4f8cc534c | 165 | } |
jhnwkmn | 0:97a4f8cc534c | 166 | } |
jhnwkmn | 0:97a4f8cc534c | 167 | Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); |
jhnwkmn | 0:97a4f8cc534c | 168 | return false; |
jhnwkmn | 0:97a4f8cc534c | 169 | } |
jhnwkmn | 0:97a4f8cc534c | 170 | |
jhnwkmn | 0:97a4f8cc534c | 171 | bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) |
jhnwkmn | 0:97a4f8cc534c | 172 | { |
jhnwkmn | 0:97a4f8cc534c | 173 | |
jhnwkmn | 0:97a4f8cc534c | 174 | switch(type(o)) { |
jhnwkmn | 0:97a4f8cc534c | 175 | case OT_INTEGER: |
jhnwkmn | 0:97a4f8cc534c | 176 | trg = -_integer(o); |
jhnwkmn | 0:97a4f8cc534c | 177 | return true; |
jhnwkmn | 0:97a4f8cc534c | 178 | case OT_FLOAT: |
jhnwkmn | 0:97a4f8cc534c | 179 | trg = -_float(o); |
jhnwkmn | 0:97a4f8cc534c | 180 | return true; |
jhnwkmn | 0:97a4f8cc534c | 181 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 182 | case OT_USERDATA: |
jhnwkmn | 0:97a4f8cc534c | 183 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 184 | if(_delegable(o)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 185 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 186 | if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 187 | Push(o); |
jhnwkmn | 0:97a4f8cc534c | 188 | if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false; |
jhnwkmn | 0:97a4f8cc534c | 189 | _Swap(trg,temp_reg); |
jhnwkmn | 0:97a4f8cc534c | 190 | return true; |
jhnwkmn | 0:97a4f8cc534c | 191 | |
jhnwkmn | 0:97a4f8cc534c | 192 | } |
jhnwkmn | 0:97a4f8cc534c | 193 | } |
jhnwkmn | 0:97a4f8cc534c | 194 | default:break; //shutup compiler |
jhnwkmn | 0:97a4f8cc534c | 195 | } |
jhnwkmn | 0:97a4f8cc534c | 196 | Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o)); |
jhnwkmn | 0:97a4f8cc534c | 197 | return false; |
jhnwkmn | 0:97a4f8cc534c | 198 | } |
jhnwkmn | 0:97a4f8cc534c | 199 | |
jhnwkmn | 0:97a4f8cc534c | 200 | #define _RET_SUCCEED(exp) { result = (exp); return true; } |
jhnwkmn | 0:97a4f8cc534c | 201 | bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) |
jhnwkmn | 0:97a4f8cc534c | 202 | { |
jhnwkmn | 0:97a4f8cc534c | 203 | SQObjectType t1 = type(o1), t2 = type(o2); |
jhnwkmn | 0:97a4f8cc534c | 204 | if(t1 == t2) { |
jhnwkmn | 0:97a4f8cc534c | 205 | if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0); |
jhnwkmn | 0:97a4f8cc534c | 206 | SQObjectPtr res; |
jhnwkmn | 0:97a4f8cc534c | 207 | switch(t1){ |
jhnwkmn | 0:97a4f8cc534c | 208 | case OT_STRING: |
jhnwkmn | 0:97a4f8cc534c | 209 | _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); |
jhnwkmn | 0:97a4f8cc534c | 210 | case OT_INTEGER: |
jhnwkmn | 0:97a4f8cc534c | 211 | _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1); |
jhnwkmn | 0:97a4f8cc534c | 212 | case OT_FLOAT: |
jhnwkmn | 0:97a4f8cc534c | 213 | _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); |
jhnwkmn | 0:97a4f8cc534c | 214 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 215 | case OT_USERDATA: |
jhnwkmn | 0:97a4f8cc534c | 216 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 217 | if(_delegable(o1)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 218 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 219 | if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 220 | Push(o1);Push(o2); |
jhnwkmn | 0:97a4f8cc534c | 221 | if(CallMetaMethod(closure,MT_CMP,2,res)) { |
jhnwkmn | 0:97a4f8cc534c | 222 | if(type(res) != OT_INTEGER) { |
jhnwkmn | 0:97a4f8cc534c | 223 | Raise_Error(_SC("_cmp must return an integer")); |
jhnwkmn | 0:97a4f8cc534c | 224 | return false; |
jhnwkmn | 0:97a4f8cc534c | 225 | } |
jhnwkmn | 0:97a4f8cc534c | 226 | _RET_SUCCEED(_integer(res)) |
jhnwkmn | 0:97a4f8cc534c | 227 | } |
jhnwkmn | 0:97a4f8cc534c | 228 | return false; |
jhnwkmn | 0:97a4f8cc534c | 229 | } |
jhnwkmn | 0:97a4f8cc534c | 230 | } |
jhnwkmn | 0:97a4f8cc534c | 231 | //continues through (no break needed) |
jhnwkmn | 0:97a4f8cc534c | 232 | default: |
jhnwkmn | 0:97a4f8cc534c | 233 | _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 ); |
jhnwkmn | 0:97a4f8cc534c | 234 | } |
jhnwkmn | 0:97a4f8cc534c | 235 | assert(0); |
jhnwkmn | 0:97a4f8cc534c | 236 | //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } |
jhnwkmn | 0:97a4f8cc534c | 237 | // _RET_SUCCEED(_integer(res)); |
jhnwkmn | 0:97a4f8cc534c | 238 | |
jhnwkmn | 0:97a4f8cc534c | 239 | } |
jhnwkmn | 0:97a4f8cc534c | 240 | else{ |
jhnwkmn | 0:97a4f8cc534c | 241 | if(sq_isnumeric(o1) && sq_isnumeric(o2)){ |
jhnwkmn | 0:97a4f8cc534c | 242 | if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { |
jhnwkmn | 0:97a4f8cc534c | 243 | if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } |
jhnwkmn | 0:97a4f8cc534c | 244 | else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } |
jhnwkmn | 0:97a4f8cc534c | 245 | _RET_SUCCEED(1); |
jhnwkmn | 0:97a4f8cc534c | 246 | } |
jhnwkmn | 0:97a4f8cc534c | 247 | else{ |
jhnwkmn | 0:97a4f8cc534c | 248 | if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); } |
jhnwkmn | 0:97a4f8cc534c | 249 | else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); } |
jhnwkmn | 0:97a4f8cc534c | 250 | _RET_SUCCEED(1); |
jhnwkmn | 0:97a4f8cc534c | 251 | } |
jhnwkmn | 0:97a4f8cc534c | 252 | } |
jhnwkmn | 0:97a4f8cc534c | 253 | else if(t1==OT_NULL) {_RET_SUCCEED(-1);} |
jhnwkmn | 0:97a4f8cc534c | 254 | else if(t2==OT_NULL) {_RET_SUCCEED(1);} |
jhnwkmn | 0:97a4f8cc534c | 255 | else { Raise_CompareError(o1,o2); return false; } |
jhnwkmn | 0:97a4f8cc534c | 256 | |
jhnwkmn | 0:97a4f8cc534c | 257 | } |
jhnwkmn | 0:97a4f8cc534c | 258 | assert(0); |
jhnwkmn | 0:97a4f8cc534c | 259 | _RET_SUCCEED(0); //cannot happen |
jhnwkmn | 0:97a4f8cc534c | 260 | } |
jhnwkmn | 0:97a4f8cc534c | 261 | |
jhnwkmn | 0:97a4f8cc534c | 262 | bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res) |
jhnwkmn | 0:97a4f8cc534c | 263 | { |
jhnwkmn | 0:97a4f8cc534c | 264 | SQInteger r; |
jhnwkmn | 0:97a4f8cc534c | 265 | if(ObjCmp(o1,o2,r)) { |
jhnwkmn | 0:97a4f8cc534c | 266 | switch(op) { |
jhnwkmn | 0:97a4f8cc534c | 267 | case CMP_G: res = (r > 0); return true; |
jhnwkmn | 0:97a4f8cc534c | 268 | case CMP_GE: res = (r >= 0); return true; |
jhnwkmn | 0:97a4f8cc534c | 269 | case CMP_L: res = (r < 0); return true; |
jhnwkmn | 0:97a4f8cc534c | 270 | case CMP_LE: res = (r <= 0); return true; |
jhnwkmn | 0:97a4f8cc534c | 271 | case CMP_3W: res = r; return true; |
jhnwkmn | 0:97a4f8cc534c | 272 | } |
jhnwkmn | 0:97a4f8cc534c | 273 | assert(0); |
jhnwkmn | 0:97a4f8cc534c | 274 | } |
jhnwkmn | 0:97a4f8cc534c | 275 | return false; |
jhnwkmn | 0:97a4f8cc534c | 276 | } |
jhnwkmn | 0:97a4f8cc534c | 277 | |
jhnwkmn | 0:97a4f8cc534c | 278 | bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) |
jhnwkmn | 0:97a4f8cc534c | 279 | { |
jhnwkmn | 0:97a4f8cc534c | 280 | switch(type(o)) { |
jhnwkmn | 0:97a4f8cc534c | 281 | case OT_STRING: |
jhnwkmn | 0:97a4f8cc534c | 282 | res = o; |
jhnwkmn | 0:97a4f8cc534c | 283 | return true; |
jhnwkmn | 0:97a4f8cc534c | 284 | case OT_FLOAT: |
jhnwkmn | 0:97a4f8cc534c | 285 | scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o)); |
jhnwkmn | 0:97a4f8cc534c | 286 | break; |
jhnwkmn | 0:97a4f8cc534c | 287 | case OT_INTEGER: |
jhnwkmn | 0:97a4f8cc534c | 288 | scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_PRINT_INT_FMT,_integer(o)); |
jhnwkmn | 0:97a4f8cc534c | 289 | break; |
jhnwkmn | 0:97a4f8cc534c | 290 | case OT_BOOL: |
jhnwkmn | 0:97a4f8cc534c | 291 | scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false")); |
jhnwkmn | 0:97a4f8cc534c | 292 | break; |
jhnwkmn | 0:97a4f8cc534c | 293 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 294 | case OT_USERDATA: |
jhnwkmn | 0:97a4f8cc534c | 295 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 296 | if(_delegable(o)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 297 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 298 | if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 299 | Push(o); |
jhnwkmn | 0:97a4f8cc534c | 300 | if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {; |
jhnwkmn | 0:97a4f8cc534c | 301 | if(type(res) == OT_STRING) |
jhnwkmn | 0:97a4f8cc534c | 302 | return true; |
jhnwkmn | 0:97a4f8cc534c | 303 | } |
jhnwkmn | 0:97a4f8cc534c | 304 | else { |
jhnwkmn | 0:97a4f8cc534c | 305 | return false; |
jhnwkmn | 0:97a4f8cc534c | 306 | } |
jhnwkmn | 0:97a4f8cc534c | 307 | } |
jhnwkmn | 0:97a4f8cc534c | 308 | } |
jhnwkmn | 0:97a4f8cc534c | 309 | default: |
jhnwkmn | 0:97a4f8cc534c | 310 | scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); |
jhnwkmn | 0:97a4f8cc534c | 311 | } |
jhnwkmn | 0:97a4f8cc534c | 312 | res = SQString::Create(_ss(this),_spval); |
jhnwkmn | 0:97a4f8cc534c | 313 | return true; |
jhnwkmn | 0:97a4f8cc534c | 314 | } |
jhnwkmn | 0:97a4f8cc534c | 315 | |
jhnwkmn | 0:97a4f8cc534c | 316 | |
jhnwkmn | 0:97a4f8cc534c | 317 | bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) |
jhnwkmn | 0:97a4f8cc534c | 318 | { |
jhnwkmn | 0:97a4f8cc534c | 319 | SQObjectPtr a, b; |
jhnwkmn | 0:97a4f8cc534c | 320 | if(!ToString(str, a)) return false; |
jhnwkmn | 0:97a4f8cc534c | 321 | if(!ToString(obj, b)) return false; |
jhnwkmn | 0:97a4f8cc534c | 322 | SQInteger l = _string(a)->_len , ol = _string(b)->_len; |
jhnwkmn | 0:97a4f8cc534c | 323 | SQChar *s = _sp(rsl(l + ol + 1)); |
jhnwkmn | 0:97a4f8cc534c | 324 | memcpy(s, _stringval(a), rsl(l)); |
jhnwkmn | 0:97a4f8cc534c | 325 | memcpy(s + l, _stringval(b), rsl(ol)); |
jhnwkmn | 0:97a4f8cc534c | 326 | dest = SQString::Create(_ss(this), _spval, l + ol); |
jhnwkmn | 0:97a4f8cc534c | 327 | return true; |
jhnwkmn | 0:97a4f8cc534c | 328 | } |
jhnwkmn | 0:97a4f8cc534c | 329 | |
jhnwkmn | 0:97a4f8cc534c | 330 | bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) |
jhnwkmn | 0:97a4f8cc534c | 331 | { |
jhnwkmn | 0:97a4f8cc534c | 332 | if(is_delegable(obj1) && _delegable(obj1)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 333 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 334 | if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 335 | Push(obj1); |
jhnwkmn | 0:97a4f8cc534c | 336 | return CallMetaMethod(closure,MT_TYPEOF,1,dest); |
jhnwkmn | 0:97a4f8cc534c | 337 | } |
jhnwkmn | 0:97a4f8cc534c | 338 | } |
jhnwkmn | 0:97a4f8cc534c | 339 | dest = SQString::Create(_ss(this),GetTypeName(obj1)); |
jhnwkmn | 0:97a4f8cc534c | 340 | return true; |
jhnwkmn | 0:97a4f8cc534c | 341 | } |
jhnwkmn | 0:97a4f8cc534c | 342 | |
jhnwkmn | 0:97a4f8cc534c | 343 | bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) |
jhnwkmn | 0:97a4f8cc534c | 344 | { |
jhnwkmn | 0:97a4f8cc534c | 345 | _stack.resize(stacksize); |
jhnwkmn | 0:97a4f8cc534c | 346 | _alloccallsstacksize = 4; |
jhnwkmn | 0:97a4f8cc534c | 347 | _callstackdata.resize(_alloccallsstacksize); |
jhnwkmn | 0:97a4f8cc534c | 348 | _callsstacksize = 0; |
jhnwkmn | 0:97a4f8cc534c | 349 | _callsstack = &_callstackdata[0]; |
jhnwkmn | 0:97a4f8cc534c | 350 | _stackbase = 0; |
jhnwkmn | 0:97a4f8cc534c | 351 | _top = 0; |
jhnwkmn | 0:97a4f8cc534c | 352 | if(!friendvm) |
jhnwkmn | 0:97a4f8cc534c | 353 | _roottable = SQTable::Create(_ss(this), 0); |
jhnwkmn | 0:97a4f8cc534c | 354 | else { |
jhnwkmn | 0:97a4f8cc534c | 355 | _roottable = friendvm->_roottable; |
jhnwkmn | 0:97a4f8cc534c | 356 | _errorhandler = friendvm->_errorhandler; |
jhnwkmn | 0:97a4f8cc534c | 357 | _debughook = friendvm->_debughook; |
jhnwkmn | 0:97a4f8cc534c | 358 | _debughook_native = friendvm->_debughook_native; |
jhnwkmn | 0:97a4f8cc534c | 359 | _debughook_closure = friendvm->_debughook_closure; |
jhnwkmn | 0:97a4f8cc534c | 360 | } |
jhnwkmn | 0:97a4f8cc534c | 361 | |
jhnwkmn | 0:97a4f8cc534c | 362 | sq_base_register(this); |
jhnwkmn | 0:97a4f8cc534c | 363 | return true; |
jhnwkmn | 0:97a4f8cc534c | 364 | } |
jhnwkmn | 0:97a4f8cc534c | 365 | |
jhnwkmn | 0:97a4f8cc534c | 366 | |
jhnwkmn | 0:97a4f8cc534c | 367 | bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall) |
jhnwkmn | 0:97a4f8cc534c | 368 | { |
jhnwkmn | 0:97a4f8cc534c | 369 | SQFunctionProto *func = closure->_function; |
jhnwkmn | 0:97a4f8cc534c | 370 | |
jhnwkmn | 0:97a4f8cc534c | 371 | SQInteger paramssize = func->_nparameters; |
jhnwkmn | 0:97a4f8cc534c | 372 | const SQInteger newtop = stackbase + func->_stacksize; |
jhnwkmn | 0:97a4f8cc534c | 373 | SQInteger nargs = args; |
jhnwkmn | 0:97a4f8cc534c | 374 | if(func->_varparams) |
jhnwkmn | 0:97a4f8cc534c | 375 | { |
jhnwkmn | 0:97a4f8cc534c | 376 | paramssize--; |
jhnwkmn | 0:97a4f8cc534c | 377 | if (nargs < paramssize) { |
jhnwkmn | 0:97a4f8cc534c | 378 | Raise_Error(_SC("wrong number of parameters")); |
jhnwkmn | 0:97a4f8cc534c | 379 | return false; |
jhnwkmn | 0:97a4f8cc534c | 380 | } |
jhnwkmn | 0:97a4f8cc534c | 381 | |
jhnwkmn | 0:97a4f8cc534c | 382 | //dumpstack(stackbase); |
jhnwkmn | 0:97a4f8cc534c | 383 | SQInteger nvargs = nargs - paramssize; |
jhnwkmn | 0:97a4f8cc534c | 384 | SQArray *arr = SQArray::Create(_ss(this),nvargs); |
jhnwkmn | 0:97a4f8cc534c | 385 | SQInteger pbase = stackbase+paramssize; |
jhnwkmn | 0:97a4f8cc534c | 386 | for(SQInteger n = 0; n < nvargs; n++) { |
jhnwkmn | 0:97a4f8cc534c | 387 | arr->_values[n] = _stack._vals[pbase]; |
jhnwkmn | 0:97a4f8cc534c | 388 | _stack._vals[pbase].Null(); |
jhnwkmn | 0:97a4f8cc534c | 389 | pbase++; |
jhnwkmn | 0:97a4f8cc534c | 390 | |
jhnwkmn | 0:97a4f8cc534c | 391 | } |
jhnwkmn | 0:97a4f8cc534c | 392 | _stack._vals[stackbase+paramssize] = arr; |
jhnwkmn | 0:97a4f8cc534c | 393 | //dumpstack(stackbase); |
jhnwkmn | 0:97a4f8cc534c | 394 | } |
jhnwkmn | 0:97a4f8cc534c | 395 | else if (paramssize != nargs) { |
jhnwkmn | 0:97a4f8cc534c | 396 | SQInteger ndef = func->_ndefaultparams; |
jhnwkmn | 0:97a4f8cc534c | 397 | SQInteger diff; |
jhnwkmn | 0:97a4f8cc534c | 398 | if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) { |
jhnwkmn | 0:97a4f8cc534c | 399 | for(SQInteger n = ndef - diff; n < ndef; n++) { |
jhnwkmn | 0:97a4f8cc534c | 400 | _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; |
jhnwkmn | 0:97a4f8cc534c | 401 | } |
jhnwkmn | 0:97a4f8cc534c | 402 | } |
jhnwkmn | 0:97a4f8cc534c | 403 | else { |
jhnwkmn | 0:97a4f8cc534c | 404 | Raise_Error(_SC("wrong number of parameters")); |
jhnwkmn | 0:97a4f8cc534c | 405 | return false; |
jhnwkmn | 0:97a4f8cc534c | 406 | } |
jhnwkmn | 0:97a4f8cc534c | 407 | } |
jhnwkmn | 0:97a4f8cc534c | 408 | |
jhnwkmn | 0:97a4f8cc534c | 409 | if(closure->_env) { |
jhnwkmn | 0:97a4f8cc534c | 410 | _stack._vals[stackbase] = closure->_env->_obj; |
jhnwkmn | 0:97a4f8cc534c | 411 | } |
jhnwkmn | 0:97a4f8cc534c | 412 | |
jhnwkmn | 0:97a4f8cc534c | 413 | if(!EnterFrame(stackbase, newtop, tailcall)) return false; |
jhnwkmn | 0:97a4f8cc534c | 414 | |
jhnwkmn | 0:97a4f8cc534c | 415 | ci->_closure = closure; |
jhnwkmn | 0:97a4f8cc534c | 416 | ci->_literals = func->_literals; |
jhnwkmn | 0:97a4f8cc534c | 417 | ci->_ip = func->_instructions; |
jhnwkmn | 0:97a4f8cc534c | 418 | ci->_target = (SQInt32)target; |
jhnwkmn | 0:97a4f8cc534c | 419 | |
jhnwkmn | 0:97a4f8cc534c | 420 | if (_debughook) { |
jhnwkmn | 0:97a4f8cc534c | 421 | CallDebugHook(_SC('c')); |
jhnwkmn | 0:97a4f8cc534c | 422 | } |
jhnwkmn | 0:97a4f8cc534c | 423 | |
jhnwkmn | 0:97a4f8cc534c | 424 | if (closure->_function->_bgenerator) { |
jhnwkmn | 0:97a4f8cc534c | 425 | SQFunctionProto *f = closure->_function; |
jhnwkmn | 0:97a4f8cc534c | 426 | SQGenerator *gen = SQGenerator::Create(_ss(this), closure); |
jhnwkmn | 0:97a4f8cc534c | 427 | if(!gen->Yield(this,f->_stacksize)) |
jhnwkmn | 0:97a4f8cc534c | 428 | return false; |
jhnwkmn | 0:97a4f8cc534c | 429 | SQObjectPtr temp; |
jhnwkmn | 0:97a4f8cc534c | 430 | Return(1, target, temp); |
jhnwkmn | 0:97a4f8cc534c | 431 | STK(target) = gen; |
jhnwkmn | 0:97a4f8cc534c | 432 | } |
jhnwkmn | 0:97a4f8cc534c | 433 | |
jhnwkmn | 0:97a4f8cc534c | 434 | |
jhnwkmn | 0:97a4f8cc534c | 435 | return true; |
jhnwkmn | 0:97a4f8cc534c | 436 | } |
jhnwkmn | 0:97a4f8cc534c | 437 | |
jhnwkmn | 0:97a4f8cc534c | 438 | bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) |
jhnwkmn | 0:97a4f8cc534c | 439 | { |
jhnwkmn | 0:97a4f8cc534c | 440 | SQBool _isroot = ci->_root; |
jhnwkmn | 0:97a4f8cc534c | 441 | SQInteger callerbase = _stackbase - ci->_prevstkbase; |
jhnwkmn | 0:97a4f8cc534c | 442 | |
jhnwkmn | 0:97a4f8cc534c | 443 | if (_debughook) { |
jhnwkmn | 0:97a4f8cc534c | 444 | for(SQInteger i=0; i<ci->_ncalls; i++) { |
jhnwkmn | 0:97a4f8cc534c | 445 | CallDebugHook(_SC('r')); |
jhnwkmn | 0:97a4f8cc534c | 446 | } |
jhnwkmn | 0:97a4f8cc534c | 447 | } |
jhnwkmn | 0:97a4f8cc534c | 448 | |
jhnwkmn | 0:97a4f8cc534c | 449 | SQObjectPtr *dest; |
jhnwkmn | 0:97a4f8cc534c | 450 | if (_isroot) { |
jhnwkmn | 0:97a4f8cc534c | 451 | dest = &(retval); |
jhnwkmn | 0:97a4f8cc534c | 452 | } else if (ci->_target == -1) { |
jhnwkmn | 0:97a4f8cc534c | 453 | dest = NULL; |
jhnwkmn | 0:97a4f8cc534c | 454 | } else { |
jhnwkmn | 0:97a4f8cc534c | 455 | dest = &_stack._vals[callerbase + ci->_target]; |
jhnwkmn | 0:97a4f8cc534c | 456 | } |
jhnwkmn | 0:97a4f8cc534c | 457 | if (dest) { |
jhnwkmn | 0:97a4f8cc534c | 458 | if(_arg0 != 0xFF) { |
jhnwkmn | 0:97a4f8cc534c | 459 | *dest = _stack._vals[_stackbase+_arg1]; |
jhnwkmn | 0:97a4f8cc534c | 460 | } |
jhnwkmn | 0:97a4f8cc534c | 461 | else { |
jhnwkmn | 0:97a4f8cc534c | 462 | dest->Null(); |
jhnwkmn | 0:97a4f8cc534c | 463 | } |
jhnwkmn | 0:97a4f8cc534c | 464 | //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_; |
jhnwkmn | 0:97a4f8cc534c | 465 | } |
jhnwkmn | 0:97a4f8cc534c | 466 | LeaveFrame(); |
jhnwkmn | 0:97a4f8cc534c | 467 | return _isroot ? true : false; |
jhnwkmn | 0:97a4f8cc534c | 468 | } |
jhnwkmn | 0:97a4f8cc534c | 469 | |
jhnwkmn | 0:97a4f8cc534c | 470 | #define _RET_ON_FAIL(exp) { if(!exp) return false; } |
jhnwkmn | 0:97a4f8cc534c | 471 | |
jhnwkmn | 0:97a4f8cc534c | 472 | bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) |
jhnwkmn | 0:97a4f8cc534c | 473 | { |
jhnwkmn | 0:97a4f8cc534c | 474 | SQObjectPtr trg; |
jhnwkmn | 0:97a4f8cc534c | 475 | _RET_ON_FAIL(ARITH_OP( op , trg, a, incr)); |
jhnwkmn | 0:97a4f8cc534c | 476 | target = a; |
jhnwkmn | 0:97a4f8cc534c | 477 | a = trg; |
jhnwkmn | 0:97a4f8cc534c | 478 | return true; |
jhnwkmn | 0:97a4f8cc534c | 479 | } |
jhnwkmn | 0:97a4f8cc534c | 480 | |
jhnwkmn | 0:97a4f8cc534c | 481 | bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx) |
jhnwkmn | 0:97a4f8cc534c | 482 | { |
jhnwkmn | 0:97a4f8cc534c | 483 | SQObjectPtr tmp, tself = self, tkey = key; |
jhnwkmn | 0:97a4f8cc534c | 484 | if (!Get(tself, tkey, tmp, false, selfidx)) { return false; } |
jhnwkmn | 0:97a4f8cc534c | 485 | _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) |
jhnwkmn | 0:97a4f8cc534c | 486 | if (!Set(tself, tkey, target,selfidx)) { return false; } |
jhnwkmn | 0:97a4f8cc534c | 487 | if (postfix) target = tmp; |
jhnwkmn | 0:97a4f8cc534c | 488 | return true; |
jhnwkmn | 0:97a4f8cc534c | 489 | } |
jhnwkmn | 0:97a4f8cc534c | 490 | |
jhnwkmn | 0:97a4f8cc534c | 491 | #define arg0 (_i_._arg0) |
jhnwkmn | 0:97a4f8cc534c | 492 | #define sarg0 ((SQInteger)*((signed char *)&_i_._arg0)) |
jhnwkmn | 0:97a4f8cc534c | 493 | #define arg1 (_i_._arg1) |
jhnwkmn | 0:97a4f8cc534c | 494 | #define sarg1 (*((SQInt32 *)&_i_._arg1)) |
jhnwkmn | 0:97a4f8cc534c | 495 | #define arg2 (_i_._arg2) |
jhnwkmn | 0:97a4f8cc534c | 496 | #define arg3 (_i_._arg3) |
jhnwkmn | 0:97a4f8cc534c | 497 | #define sarg3 ((SQInteger)*((signed char *)&_i_._arg3)) |
jhnwkmn | 0:97a4f8cc534c | 498 | |
jhnwkmn | 0:97a4f8cc534c | 499 | SQRESULT SQVM::Suspend() |
jhnwkmn | 0:97a4f8cc534c | 500 | { |
jhnwkmn | 0:97a4f8cc534c | 501 | if (_suspended) |
jhnwkmn | 0:97a4f8cc534c | 502 | return sq_throwerror(this, _SC("cannot suspend an already suspended vm")); |
jhnwkmn | 0:97a4f8cc534c | 503 | if (_nnativecalls!=2) |
jhnwkmn | 0:97a4f8cc534c | 504 | return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods")); |
jhnwkmn | 0:97a4f8cc534c | 505 | return SQ_SUSPEND_FLAG; |
jhnwkmn | 0:97a4f8cc534c | 506 | } |
jhnwkmn | 0:97a4f8cc534c | 507 | |
jhnwkmn | 0:97a4f8cc534c | 508 | |
jhnwkmn | 0:97a4f8cc534c | 509 | #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; } |
jhnwkmn | 0:97a4f8cc534c | 510 | bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr |
jhnwkmn | 0:97a4f8cc534c | 511 | &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump) |
jhnwkmn | 0:97a4f8cc534c | 512 | { |
jhnwkmn | 0:97a4f8cc534c | 513 | SQInteger nrefidx; |
jhnwkmn | 0:97a4f8cc534c | 514 | switch(type(o1)) { |
jhnwkmn | 0:97a4f8cc534c | 515 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 516 | if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos); |
jhnwkmn | 0:97a4f8cc534c | 517 | o4 = (SQInteger)nrefidx; _FINISH(1); |
jhnwkmn | 0:97a4f8cc534c | 518 | case OT_ARRAY: |
jhnwkmn | 0:97a4f8cc534c | 519 | if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos); |
jhnwkmn | 0:97a4f8cc534c | 520 | o4 = (SQInteger) nrefidx; _FINISH(1); |
jhnwkmn | 0:97a4f8cc534c | 521 | case OT_STRING: |
jhnwkmn | 0:97a4f8cc534c | 522 | if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); |
jhnwkmn | 0:97a4f8cc534c | 523 | o4 = (SQInteger)nrefidx; _FINISH(1); |
jhnwkmn | 0:97a4f8cc534c | 524 | case OT_CLASS: |
jhnwkmn | 0:97a4f8cc534c | 525 | if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); |
jhnwkmn | 0:97a4f8cc534c | 526 | o4 = (SQInteger)nrefidx; _FINISH(1); |
jhnwkmn | 0:97a4f8cc534c | 527 | case OT_USERDATA: |
jhnwkmn | 0:97a4f8cc534c | 528 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 529 | if(_delegable(o1)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 530 | SQObjectPtr itr; |
jhnwkmn | 0:97a4f8cc534c | 531 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 532 | if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 533 | Push(o1); |
jhnwkmn | 0:97a4f8cc534c | 534 | Push(o4); |
jhnwkmn | 0:97a4f8cc534c | 535 | if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) { |
jhnwkmn | 0:97a4f8cc534c | 536 | o4 = o2 = itr; |
jhnwkmn | 0:97a4f8cc534c | 537 | if(type(itr) == OT_NULL) _FINISH(exitpos); |
jhnwkmn | 0:97a4f8cc534c | 538 | if(!Get(o1, itr, o3, false, DONT_FALL_BACK)) { |
jhnwkmn | 0:97a4f8cc534c | 539 | Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed |
jhnwkmn | 0:97a4f8cc534c | 540 | return false; |
jhnwkmn | 0:97a4f8cc534c | 541 | } |
jhnwkmn | 0:97a4f8cc534c | 542 | _FINISH(1); |
jhnwkmn | 0:97a4f8cc534c | 543 | } |
jhnwkmn | 0:97a4f8cc534c | 544 | else { |
jhnwkmn | 0:97a4f8cc534c | 545 | return false; |
jhnwkmn | 0:97a4f8cc534c | 546 | } |
jhnwkmn | 0:97a4f8cc534c | 547 | } |
jhnwkmn | 0:97a4f8cc534c | 548 | Raise_Error(_SC("_nexti failed")); |
jhnwkmn | 0:97a4f8cc534c | 549 | return false; |
jhnwkmn | 0:97a4f8cc534c | 550 | } |
jhnwkmn | 0:97a4f8cc534c | 551 | break; |
jhnwkmn | 0:97a4f8cc534c | 552 | case OT_GENERATOR: |
jhnwkmn | 0:97a4f8cc534c | 553 | if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos); |
jhnwkmn | 0:97a4f8cc534c | 554 | if(_generator(o1)->_state == SQGenerator::eSuspended) { |
jhnwkmn | 0:97a4f8cc534c | 555 | SQInteger idx = 0; |
jhnwkmn | 0:97a4f8cc534c | 556 | if(type(o4) == OT_INTEGER) { |
jhnwkmn | 0:97a4f8cc534c | 557 | idx = _integer(o4) + 1; |
jhnwkmn | 0:97a4f8cc534c | 558 | } |
jhnwkmn | 0:97a4f8cc534c | 559 | o2 = idx; |
jhnwkmn | 0:97a4f8cc534c | 560 | o4 = idx; |
jhnwkmn | 0:97a4f8cc534c | 561 | _generator(o1)->Resume(this, o3); |
jhnwkmn | 0:97a4f8cc534c | 562 | _FINISH(0); |
jhnwkmn | 0:97a4f8cc534c | 563 | } |
jhnwkmn | 0:97a4f8cc534c | 564 | default: |
jhnwkmn | 0:97a4f8cc534c | 565 | Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); |
jhnwkmn | 0:97a4f8cc534c | 566 | } |
jhnwkmn | 0:97a4f8cc534c | 567 | return false; //cannot be hit(just to avoid warnings) |
jhnwkmn | 0:97a4f8cc534c | 568 | } |
jhnwkmn | 0:97a4f8cc534c | 569 | |
jhnwkmn | 0:97a4f8cc534c | 570 | #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1)) |
jhnwkmn | 0:97a4f8cc534c | 571 | |
jhnwkmn | 0:97a4f8cc534c | 572 | #define SQ_THROW() { goto exception_trap; } |
jhnwkmn | 0:97a4f8cc534c | 573 | |
jhnwkmn | 0:97a4f8cc534c | 574 | #define _GUARD(exp) { if(!exp) { SQ_THROW();} } |
jhnwkmn | 0:97a4f8cc534c | 575 | |
jhnwkmn | 0:97a4f8cc534c | 576 | bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) |
jhnwkmn | 0:97a4f8cc534c | 577 | { |
jhnwkmn | 0:97a4f8cc534c | 578 | SQInteger nouters; |
jhnwkmn | 0:97a4f8cc534c | 579 | SQClosure *closure = SQClosure::Create(_ss(this), func); |
jhnwkmn | 0:97a4f8cc534c | 580 | if((nouters = func->_noutervalues)) { |
jhnwkmn | 0:97a4f8cc534c | 581 | for(SQInteger i = 0; i<nouters; i++) { |
jhnwkmn | 0:97a4f8cc534c | 582 | SQOuterVar &v = func->_outervalues[i]; |
jhnwkmn | 0:97a4f8cc534c | 583 | switch(v._type){ |
jhnwkmn | 0:97a4f8cc534c | 584 | case otLOCAL: |
jhnwkmn | 0:97a4f8cc534c | 585 | FindOuter(closure->_outervalues[i], &STK(_integer(v._src))); |
jhnwkmn | 0:97a4f8cc534c | 586 | break; |
jhnwkmn | 0:97a4f8cc534c | 587 | case otOUTER: |
jhnwkmn | 0:97a4f8cc534c | 588 | closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)]; |
jhnwkmn | 0:97a4f8cc534c | 589 | break; |
jhnwkmn | 0:97a4f8cc534c | 590 | } |
jhnwkmn | 0:97a4f8cc534c | 591 | } |
jhnwkmn | 0:97a4f8cc534c | 592 | } |
jhnwkmn | 0:97a4f8cc534c | 593 | SQInteger ndefparams; |
jhnwkmn | 0:97a4f8cc534c | 594 | if((ndefparams = func->_ndefaultparams)) { |
jhnwkmn | 0:97a4f8cc534c | 595 | for(SQInteger i = 0; i < ndefparams; i++) { |
jhnwkmn | 0:97a4f8cc534c | 596 | SQInteger spos = func->_defaultparams[i]; |
jhnwkmn | 0:97a4f8cc534c | 597 | closure->_defaultparams[i] = _stack._vals[_stackbase + spos]; |
jhnwkmn | 0:97a4f8cc534c | 598 | } |
jhnwkmn | 0:97a4f8cc534c | 599 | } |
jhnwkmn | 0:97a4f8cc534c | 600 | target = closure; |
jhnwkmn | 0:97a4f8cc534c | 601 | return true; |
jhnwkmn | 0:97a4f8cc534c | 602 | |
jhnwkmn | 0:97a4f8cc534c | 603 | } |
jhnwkmn | 0:97a4f8cc534c | 604 | |
jhnwkmn | 0:97a4f8cc534c | 605 | |
jhnwkmn | 0:97a4f8cc534c | 606 | bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) |
jhnwkmn | 0:97a4f8cc534c | 607 | { |
jhnwkmn | 0:97a4f8cc534c | 608 | SQClass *base = NULL; |
jhnwkmn | 0:97a4f8cc534c | 609 | SQObjectPtr attrs; |
jhnwkmn | 0:97a4f8cc534c | 610 | if(baseclass != -1) { |
jhnwkmn | 0:97a4f8cc534c | 611 | if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } |
jhnwkmn | 0:97a4f8cc534c | 612 | base = _class(_stack._vals[_stackbase + baseclass]); |
jhnwkmn | 0:97a4f8cc534c | 613 | } |
jhnwkmn | 0:97a4f8cc534c | 614 | if(attributes != MAX_FUNC_STACKSIZE) { |
jhnwkmn | 0:97a4f8cc534c | 615 | attrs = _stack._vals[_stackbase+attributes]; |
jhnwkmn | 0:97a4f8cc534c | 616 | } |
jhnwkmn | 0:97a4f8cc534c | 617 | target = SQClass::Create(_ss(this),base); |
jhnwkmn | 0:97a4f8cc534c | 618 | if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) { |
jhnwkmn | 0:97a4f8cc534c | 619 | int nparams = 2; |
jhnwkmn | 0:97a4f8cc534c | 620 | SQObjectPtr ret; |
jhnwkmn | 0:97a4f8cc534c | 621 | Push(target); Push(attrs); |
jhnwkmn | 0:97a4f8cc534c | 622 | Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false); |
jhnwkmn | 0:97a4f8cc534c | 623 | Pop(nparams); |
jhnwkmn | 0:97a4f8cc534c | 624 | } |
jhnwkmn | 0:97a4f8cc534c | 625 | _class(target)->_attributes = attrs; |
jhnwkmn | 0:97a4f8cc534c | 626 | return true; |
jhnwkmn | 0:97a4f8cc534c | 627 | } |
jhnwkmn | 0:97a4f8cc534c | 628 | |
jhnwkmn | 0:97a4f8cc534c | 629 | bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res) |
jhnwkmn | 0:97a4f8cc534c | 630 | { |
jhnwkmn | 0:97a4f8cc534c | 631 | if(type(o1) == type(o2)) { |
jhnwkmn | 0:97a4f8cc534c | 632 | res = (_rawval(o1) == _rawval(o2)); |
jhnwkmn | 0:97a4f8cc534c | 633 | } |
jhnwkmn | 0:97a4f8cc534c | 634 | else { |
jhnwkmn | 0:97a4f8cc534c | 635 | if(sq_isnumeric(o1) && sq_isnumeric(o2)) { |
jhnwkmn | 0:97a4f8cc534c | 636 | res = (tofloat(o1) == tofloat(o2)); |
jhnwkmn | 0:97a4f8cc534c | 637 | } |
jhnwkmn | 0:97a4f8cc534c | 638 | else { |
jhnwkmn | 0:97a4f8cc534c | 639 | res = false; |
jhnwkmn | 0:97a4f8cc534c | 640 | } |
jhnwkmn | 0:97a4f8cc534c | 641 | } |
jhnwkmn | 0:97a4f8cc534c | 642 | return true; |
jhnwkmn | 0:97a4f8cc534c | 643 | } |
jhnwkmn | 0:97a4f8cc534c | 644 | |
jhnwkmn | 0:97a4f8cc534c | 645 | bool SQVM::IsFalse(SQObjectPtr &o) |
jhnwkmn | 0:97a4f8cc534c | 646 | { |
jhnwkmn | 0:97a4f8cc534c | 647 | if(((type(o) & SQOBJECT_CANBEFALSE) |
jhnwkmn | 0:97a4f8cc534c | 648 | && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) )) |
jhnwkmn | 0:97a4f8cc534c | 649 | #if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64)) |
jhnwkmn | 0:97a4f8cc534c | 650 | || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL |
jhnwkmn | 0:97a4f8cc534c | 651 | #else |
jhnwkmn | 0:97a4f8cc534c | 652 | || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL |
jhnwkmn | 0:97a4f8cc534c | 653 | #endif |
jhnwkmn | 0:97a4f8cc534c | 654 | { |
jhnwkmn | 0:97a4f8cc534c | 655 | return true; |
jhnwkmn | 0:97a4f8cc534c | 656 | } |
jhnwkmn | 0:97a4f8cc534c | 657 | return false; |
jhnwkmn | 0:97a4f8cc534c | 658 | } |
jhnwkmn | 0:97a4f8cc534c | 659 | |
jhnwkmn | 0:97a4f8cc534c | 660 | bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) |
jhnwkmn | 0:97a4f8cc534c | 661 | { |
jhnwkmn | 0:97a4f8cc534c | 662 | if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } |
jhnwkmn | 0:97a4f8cc534c | 663 | _nnativecalls++; |
jhnwkmn | 0:97a4f8cc534c | 664 | AutoDec ad(&_nnativecalls); |
jhnwkmn | 0:97a4f8cc534c | 665 | SQInteger traps = 0; |
jhnwkmn | 0:97a4f8cc534c | 666 | CallInfo *prevci = ci; |
jhnwkmn | 0:97a4f8cc534c | 667 | |
jhnwkmn | 0:97a4f8cc534c | 668 | switch(et) { |
jhnwkmn | 0:97a4f8cc534c | 669 | case ET_CALL: { |
jhnwkmn | 0:97a4f8cc534c | 670 | temp_reg = closure; |
jhnwkmn | 0:97a4f8cc534c | 671 | if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { |
jhnwkmn | 0:97a4f8cc534c | 672 | //call the handler if there are no calls in the stack, if not relies on the previous node |
jhnwkmn | 0:97a4f8cc534c | 673 | if(ci == NULL) CallErrorHandler(_lasterror); |
jhnwkmn | 0:97a4f8cc534c | 674 | return false; |
jhnwkmn | 0:97a4f8cc534c | 675 | } |
jhnwkmn | 0:97a4f8cc534c | 676 | if(ci == prevci) { |
jhnwkmn | 0:97a4f8cc534c | 677 | outres = STK(_top-nargs); |
jhnwkmn | 0:97a4f8cc534c | 678 | return true; |
jhnwkmn | 0:97a4f8cc534c | 679 | } |
jhnwkmn | 0:97a4f8cc534c | 680 | ci->_root = SQTrue; |
jhnwkmn | 0:97a4f8cc534c | 681 | } |
jhnwkmn | 0:97a4f8cc534c | 682 | break; |
jhnwkmn | 0:97a4f8cc534c | 683 | case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break; |
jhnwkmn | 0:97a4f8cc534c | 684 | case ET_RESUME_VM: |
jhnwkmn | 0:97a4f8cc534c | 685 | case ET_RESUME_THROW_VM: |
jhnwkmn | 0:97a4f8cc534c | 686 | traps = _suspended_traps; |
jhnwkmn | 0:97a4f8cc534c | 687 | ci->_root = _suspended_root; |
jhnwkmn | 0:97a4f8cc534c | 688 | _suspended = SQFalse; |
jhnwkmn | 0:97a4f8cc534c | 689 | if(et == ET_RESUME_THROW_VM) { SQ_THROW(); } |
jhnwkmn | 0:97a4f8cc534c | 690 | break; |
jhnwkmn | 0:97a4f8cc534c | 691 | } |
jhnwkmn | 0:97a4f8cc534c | 692 | |
jhnwkmn | 0:97a4f8cc534c | 693 | exception_restore: |
jhnwkmn | 0:97a4f8cc534c | 694 | // |
jhnwkmn | 0:97a4f8cc534c | 695 | { |
jhnwkmn | 0:97a4f8cc534c | 696 | for(;;) |
jhnwkmn | 0:97a4f8cc534c | 697 | { |
jhnwkmn | 0:97a4f8cc534c | 698 | const SQInstruction &_i_ = *ci->_ip++; |
jhnwkmn | 0:97a4f8cc534c | 699 | //dumpstack(_stackbase); |
jhnwkmn | 0:97a4f8cc534c | 700 | //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); |
jhnwkmn | 0:97a4f8cc534c | 701 | switch(_i_.op) |
jhnwkmn | 0:97a4f8cc534c | 702 | { |
jhnwkmn | 0:97a4f8cc534c | 703 | case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 704 | case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; |
jhnwkmn | 0:97a4f8cc534c | 705 | case _OP_LOADINT: |
jhnwkmn | 0:97a4f8cc534c | 706 | #ifndef _SQ64 |
jhnwkmn | 0:97a4f8cc534c | 707 | TARGET = (SQInteger)arg1; continue; |
jhnwkmn | 0:97a4f8cc534c | 708 | #else |
jhnwkmn | 0:97a4f8cc534c | 709 | TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 710 | #endif |
jhnwkmn | 0:97a4f8cc534c | 711 | case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 712 | case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; |
jhnwkmn | 0:97a4f8cc534c | 713 | case _OP_TAILCALL:{ |
jhnwkmn | 0:97a4f8cc534c | 714 | SQObjectPtr &t = STK(arg1); |
jhnwkmn | 0:97a4f8cc534c | 715 | if (type(t) == OT_CLOSURE |
jhnwkmn | 0:97a4f8cc534c | 716 | && (!_closure(t)->_function->_bgenerator)){ |
jhnwkmn | 0:97a4f8cc534c | 717 | SQObjectPtr clo = t; |
jhnwkmn | 0:97a4f8cc534c | 718 | if(_openouters) CloseOuters(&(_stack._vals[_stackbase])); |
jhnwkmn | 0:97a4f8cc534c | 719 | for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); |
jhnwkmn | 0:97a4f8cc534c | 720 | _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true)); |
jhnwkmn | 0:97a4f8cc534c | 721 | continue; |
jhnwkmn | 0:97a4f8cc534c | 722 | } |
jhnwkmn | 0:97a4f8cc534c | 723 | } |
jhnwkmn | 0:97a4f8cc534c | 724 | case _OP_CALL: { |
jhnwkmn | 0:97a4f8cc534c | 725 | SQObjectPtr clo = STK(arg1); |
jhnwkmn | 0:97a4f8cc534c | 726 | switch (type(clo)) { |
jhnwkmn | 0:97a4f8cc534c | 727 | case OT_CLOSURE: |
jhnwkmn | 0:97a4f8cc534c | 728 | _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false)); |
jhnwkmn | 0:97a4f8cc534c | 729 | continue; |
jhnwkmn | 0:97a4f8cc534c | 730 | case OT_NATIVECLOSURE: { |
jhnwkmn | 0:97a4f8cc534c | 731 | bool suspend; |
jhnwkmn | 0:97a4f8cc534c | 732 | _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend)); |
jhnwkmn | 0:97a4f8cc534c | 733 | if(suspend){ |
jhnwkmn | 0:97a4f8cc534c | 734 | _suspended = SQTrue; |
jhnwkmn | 0:97a4f8cc534c | 735 | _suspended_target = sarg0; |
jhnwkmn | 0:97a4f8cc534c | 736 | _suspended_root = ci->_root; |
jhnwkmn | 0:97a4f8cc534c | 737 | _suspended_traps = traps; |
jhnwkmn | 0:97a4f8cc534c | 738 | outres = clo; |
jhnwkmn | 0:97a4f8cc534c | 739 | return true; |
jhnwkmn | 0:97a4f8cc534c | 740 | } |
jhnwkmn | 0:97a4f8cc534c | 741 | if(sarg0 != -1) { |
jhnwkmn | 0:97a4f8cc534c | 742 | STK(arg0) = clo; |
jhnwkmn | 0:97a4f8cc534c | 743 | } |
jhnwkmn | 0:97a4f8cc534c | 744 | } |
jhnwkmn | 0:97a4f8cc534c | 745 | continue; |
jhnwkmn | 0:97a4f8cc534c | 746 | case OT_CLASS:{ |
jhnwkmn | 0:97a4f8cc534c | 747 | SQObjectPtr inst; |
jhnwkmn | 0:97a4f8cc534c | 748 | _GUARD(CreateClassInstance(_class(clo),inst,clo)); |
jhnwkmn | 0:97a4f8cc534c | 749 | if(sarg0 != -1) { |
jhnwkmn | 0:97a4f8cc534c | 750 | STK(arg0) = inst; |
jhnwkmn | 0:97a4f8cc534c | 751 | } |
jhnwkmn | 0:97a4f8cc534c | 752 | SQInteger stkbase; |
jhnwkmn | 0:97a4f8cc534c | 753 | switch(type(clo)) { |
jhnwkmn | 0:97a4f8cc534c | 754 | case OT_CLOSURE: |
jhnwkmn | 0:97a4f8cc534c | 755 | stkbase = _stackbase+arg2; |
jhnwkmn | 0:97a4f8cc534c | 756 | _stack._vals[stkbase] = inst; |
jhnwkmn | 0:97a4f8cc534c | 757 | _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false)); |
jhnwkmn | 0:97a4f8cc534c | 758 | break; |
jhnwkmn | 0:97a4f8cc534c | 759 | case OT_NATIVECLOSURE: |
jhnwkmn | 0:97a4f8cc534c | 760 | bool suspend; |
jhnwkmn | 0:97a4f8cc534c | 761 | stkbase = _stackbase+arg2; |
jhnwkmn | 0:97a4f8cc534c | 762 | _stack._vals[stkbase] = inst; |
jhnwkmn | 0:97a4f8cc534c | 763 | _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend)); |
jhnwkmn | 0:97a4f8cc534c | 764 | break; |
jhnwkmn | 0:97a4f8cc534c | 765 | default: break; //shutup GCC 4.x |
jhnwkmn | 0:97a4f8cc534c | 766 | } |
jhnwkmn | 0:97a4f8cc534c | 767 | } |
jhnwkmn | 0:97a4f8cc534c | 768 | break; |
jhnwkmn | 0:97a4f8cc534c | 769 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 770 | case OT_USERDATA: |
jhnwkmn | 0:97a4f8cc534c | 771 | case OT_INSTANCE:{ |
jhnwkmn | 0:97a4f8cc534c | 772 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 773 | if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) { |
jhnwkmn | 0:97a4f8cc534c | 774 | Push(clo); |
jhnwkmn | 0:97a4f8cc534c | 775 | for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); |
jhnwkmn | 0:97a4f8cc534c | 776 | if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW(); |
jhnwkmn | 0:97a4f8cc534c | 777 | if(sarg0 != -1) { |
jhnwkmn | 0:97a4f8cc534c | 778 | STK(arg0) = clo; |
jhnwkmn | 0:97a4f8cc534c | 779 | } |
jhnwkmn | 0:97a4f8cc534c | 780 | break; |
jhnwkmn | 0:97a4f8cc534c | 781 | } |
jhnwkmn | 0:97a4f8cc534c | 782 | |
jhnwkmn | 0:97a4f8cc534c | 783 | //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); |
jhnwkmn | 0:97a4f8cc534c | 784 | //SQ_THROW(); |
jhnwkmn | 0:97a4f8cc534c | 785 | } |
jhnwkmn | 0:97a4f8cc534c | 786 | default: |
jhnwkmn | 0:97a4f8cc534c | 787 | Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); |
jhnwkmn | 0:97a4f8cc534c | 788 | SQ_THROW(); |
jhnwkmn | 0:97a4f8cc534c | 789 | } |
jhnwkmn | 0:97a4f8cc534c | 790 | } |
jhnwkmn | 0:97a4f8cc534c | 791 | continue; |
jhnwkmn | 0:97a4f8cc534c | 792 | case _OP_PREPCALL: |
jhnwkmn | 0:97a4f8cc534c | 793 | case _OP_PREPCALLK: { |
jhnwkmn | 0:97a4f8cc534c | 794 | SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1); |
jhnwkmn | 0:97a4f8cc534c | 795 | SQObjectPtr &o = STK(arg2); |
jhnwkmn | 0:97a4f8cc534c | 796 | if (!Get(o, key, temp_reg,false,arg2)) { |
jhnwkmn | 0:97a4f8cc534c | 797 | SQ_THROW(); |
jhnwkmn | 0:97a4f8cc534c | 798 | } |
jhnwkmn | 0:97a4f8cc534c | 799 | STK(arg3) = o; |
jhnwkmn | 0:97a4f8cc534c | 800 | _Swap(TARGET,temp_reg);//TARGET = temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 801 | } |
jhnwkmn | 0:97a4f8cc534c | 802 | continue; |
jhnwkmn | 0:97a4f8cc534c | 803 | case _OP_GETK: |
jhnwkmn | 0:97a4f8cc534c | 804 | if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();} |
jhnwkmn | 0:97a4f8cc534c | 805 | _Swap(TARGET,temp_reg);//TARGET = temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 806 | continue; |
jhnwkmn | 0:97a4f8cc534c | 807 | case _OP_MOVE: TARGET = STK(arg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 808 | case _OP_NEWSLOT: |
jhnwkmn | 0:97a4f8cc534c | 809 | _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); |
jhnwkmn | 0:97a4f8cc534c | 810 | if(arg0 != 0xFF) TARGET = STK(arg3); |
jhnwkmn | 0:97a4f8cc534c | 811 | continue; |
jhnwkmn | 0:97a4f8cc534c | 812 | case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; |
jhnwkmn | 0:97a4f8cc534c | 813 | case _OP_SET: |
jhnwkmn | 0:97a4f8cc534c | 814 | if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); } |
jhnwkmn | 0:97a4f8cc534c | 815 | if (arg0 != 0xFF) TARGET = STK(arg3); |
jhnwkmn | 0:97a4f8cc534c | 816 | continue; |
jhnwkmn | 0:97a4f8cc534c | 817 | case _OP_GET: |
jhnwkmn | 0:97a4f8cc534c | 818 | if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); } |
jhnwkmn | 0:97a4f8cc534c | 819 | _Swap(TARGET,temp_reg);//TARGET = temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 820 | continue; |
jhnwkmn | 0:97a4f8cc534c | 821 | case _OP_EQ:{ |
jhnwkmn | 0:97a4f8cc534c | 822 | bool res; |
jhnwkmn | 0:97a4f8cc534c | 823 | if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } |
jhnwkmn | 0:97a4f8cc534c | 824 | TARGET = res?true:false; |
jhnwkmn | 0:97a4f8cc534c | 825 | }continue; |
jhnwkmn | 0:97a4f8cc534c | 826 | case _OP_NE:{ |
jhnwkmn | 0:97a4f8cc534c | 827 | bool res; |
jhnwkmn | 0:97a4f8cc534c | 828 | if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } |
jhnwkmn | 0:97a4f8cc534c | 829 | TARGET = (!res)?true:false; |
jhnwkmn | 0:97a4f8cc534c | 830 | } continue; |
jhnwkmn | 0:97a4f8cc534c | 831 | case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue; |
jhnwkmn | 0:97a4f8cc534c | 832 | case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue; |
jhnwkmn | 0:97a4f8cc534c | 833 | case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue; |
jhnwkmn | 0:97a4f8cc534c | 834 | case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue; |
jhnwkmn | 0:97a4f8cc534c | 835 | case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue; |
jhnwkmn | 0:97a4f8cc534c | 836 | case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; |
jhnwkmn | 0:97a4f8cc534c | 837 | case _OP_RETURN: |
jhnwkmn | 0:97a4f8cc534c | 838 | if((ci)->_generator) { |
jhnwkmn | 0:97a4f8cc534c | 839 | (ci)->_generator->Kill(); |
jhnwkmn | 0:97a4f8cc534c | 840 | } |
jhnwkmn | 0:97a4f8cc534c | 841 | if(Return(arg0, arg1, temp_reg)){ |
jhnwkmn | 0:97a4f8cc534c | 842 | assert(traps==0); |
jhnwkmn | 0:97a4f8cc534c | 843 | //outres = temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 844 | _Swap(outres,temp_reg); |
jhnwkmn | 0:97a4f8cc534c | 845 | return true; |
jhnwkmn | 0:97a4f8cc534c | 846 | } |
jhnwkmn | 0:97a4f8cc534c | 847 | continue; |
jhnwkmn | 0:97a4f8cc534c | 848 | case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue; |
jhnwkmn | 0:97a4f8cc534c | 849 | case _OP_LOADROOT: TARGET = _roottable; continue; |
jhnwkmn | 0:97a4f8cc534c | 850 | case _OP_LOADBOOL: TARGET = arg1?true:false; continue; |
jhnwkmn | 0:97a4f8cc534c | 851 | case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; |
jhnwkmn | 0:97a4f8cc534c | 852 | case _OP_JMP: ci->_ip += (sarg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 853 | //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 854 | case _OP_JCMP: |
jhnwkmn | 0:97a4f8cc534c | 855 | _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg)); |
jhnwkmn | 0:97a4f8cc534c | 856 | if(IsFalse(temp_reg)) ci->_ip+=(sarg1); |
jhnwkmn | 0:97a4f8cc534c | 857 | continue; |
jhnwkmn | 0:97a4f8cc534c | 858 | case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 859 | case _OP_GETOUTER: { |
jhnwkmn | 0:97a4f8cc534c | 860 | SQClosure *cur_cls = _closure(ci->_closure); |
jhnwkmn | 0:97a4f8cc534c | 861 | SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); |
jhnwkmn | 0:97a4f8cc534c | 862 | TARGET = *(otr->_valptr); |
jhnwkmn | 0:97a4f8cc534c | 863 | } |
jhnwkmn | 0:97a4f8cc534c | 864 | continue; |
jhnwkmn | 0:97a4f8cc534c | 865 | case _OP_SETOUTER: { |
jhnwkmn | 0:97a4f8cc534c | 866 | SQClosure *cur_cls = _closure(ci->_closure); |
jhnwkmn | 0:97a4f8cc534c | 867 | SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); |
jhnwkmn | 0:97a4f8cc534c | 868 | *(otr->_valptr) = STK(arg2); |
jhnwkmn | 0:97a4f8cc534c | 869 | if(arg0 != 0xFF) { |
jhnwkmn | 0:97a4f8cc534c | 870 | TARGET = STK(arg2); |
jhnwkmn | 0:97a4f8cc534c | 871 | } |
jhnwkmn | 0:97a4f8cc534c | 872 | } |
jhnwkmn | 0:97a4f8cc534c | 873 | continue; |
jhnwkmn | 0:97a4f8cc534c | 874 | case _OP_NEWOBJ: |
jhnwkmn | 0:97a4f8cc534c | 875 | switch(arg3) { |
jhnwkmn | 0:97a4f8cc534c | 876 | case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 877 | case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; |
jhnwkmn | 0:97a4f8cc534c | 878 | case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; |
jhnwkmn | 0:97a4f8cc534c | 879 | default: assert(0); continue; |
jhnwkmn | 0:97a4f8cc534c | 880 | } |
jhnwkmn | 0:97a4f8cc534c | 881 | case _OP_APPENDARRAY: |
jhnwkmn | 0:97a4f8cc534c | 882 | { |
jhnwkmn | 0:97a4f8cc534c | 883 | SQObject val; |
jhnwkmn | 0:97a4f8cc534c | 884 | val._unVal.raw = 0; |
jhnwkmn | 0:97a4f8cc534c | 885 | switch(arg2) { |
jhnwkmn | 0:97a4f8cc534c | 886 | case AAT_STACK: |
jhnwkmn | 0:97a4f8cc534c | 887 | val = STK(arg1); break; |
jhnwkmn | 0:97a4f8cc534c | 888 | case AAT_LITERAL: |
jhnwkmn | 0:97a4f8cc534c | 889 | val = ci->_literals[arg1]; break; |
jhnwkmn | 0:97a4f8cc534c | 890 | case AAT_INT: |
jhnwkmn | 0:97a4f8cc534c | 891 | val._type = OT_INTEGER; |
jhnwkmn | 0:97a4f8cc534c | 892 | #ifndef _SQ64 |
jhnwkmn | 0:97a4f8cc534c | 893 | val._unVal.nInteger = (SQInteger)arg1; |
jhnwkmn | 0:97a4f8cc534c | 894 | #else |
jhnwkmn | 0:97a4f8cc534c | 895 | val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1); |
jhnwkmn | 0:97a4f8cc534c | 896 | #endif |
jhnwkmn | 0:97a4f8cc534c | 897 | break; |
jhnwkmn | 0:97a4f8cc534c | 898 | case AAT_FLOAT: |
jhnwkmn | 0:97a4f8cc534c | 899 | val._type = OT_FLOAT; |
jhnwkmn | 0:97a4f8cc534c | 900 | val._unVal.fFloat = *((SQFloat *)&arg1); |
jhnwkmn | 0:97a4f8cc534c | 901 | break; |
jhnwkmn | 0:97a4f8cc534c | 902 | case AAT_BOOL: |
jhnwkmn | 0:97a4f8cc534c | 903 | val._type = OT_BOOL; |
jhnwkmn | 0:97a4f8cc534c | 904 | val._unVal.nInteger = arg1; |
jhnwkmn | 0:97a4f8cc534c | 905 | break; |
jhnwkmn | 0:97a4f8cc534c | 906 | default: assert(0); break; |
jhnwkmn | 0:97a4f8cc534c | 907 | |
jhnwkmn | 0:97a4f8cc534c | 908 | } |
jhnwkmn | 0:97a4f8cc534c | 909 | _array(STK(arg0))->Append(val); continue; |
jhnwkmn | 0:97a4f8cc534c | 910 | } |
jhnwkmn | 0:97a4f8cc534c | 911 | case _OP_COMPARITH: { |
jhnwkmn | 0:97a4f8cc534c | 912 | SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16); |
jhnwkmn | 0:97a4f8cc534c | 913 | _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); |
jhnwkmn | 0:97a4f8cc534c | 914 | } |
jhnwkmn | 0:97a4f8cc534c | 915 | continue; |
jhnwkmn | 0:97a4f8cc534c | 916 | case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue; |
jhnwkmn | 0:97a4f8cc534c | 917 | case _OP_INCL: { |
jhnwkmn | 0:97a4f8cc534c | 918 | SQObjectPtr &a = STK(arg1); |
jhnwkmn | 0:97a4f8cc534c | 919 | if(type(a) == OT_INTEGER) { |
jhnwkmn | 0:97a4f8cc534c | 920 | a._unVal.nInteger = _integer(a) + sarg3; |
jhnwkmn | 0:97a4f8cc534c | 921 | } |
jhnwkmn | 0:97a4f8cc534c | 922 | else { |
jhnwkmn | 0:97a4f8cc534c | 923 | SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o)); |
jhnwkmn | 0:97a4f8cc534c | 924 | _ARITH_(+,a,a,o); |
jhnwkmn | 0:97a4f8cc534c | 925 | } |
jhnwkmn | 0:97a4f8cc534c | 926 | } continue; |
jhnwkmn | 0:97a4f8cc534c | 927 | case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue; |
jhnwkmn | 0:97a4f8cc534c | 928 | case _OP_PINCL: { |
jhnwkmn | 0:97a4f8cc534c | 929 | SQObjectPtr &a = STK(arg1); |
jhnwkmn | 0:97a4f8cc534c | 930 | if(type(a) == OT_INTEGER) { |
jhnwkmn | 0:97a4f8cc534c | 931 | TARGET = a; |
jhnwkmn | 0:97a4f8cc534c | 932 | a._unVal.nInteger = _integer(a) + sarg3; |
jhnwkmn | 0:97a4f8cc534c | 933 | } |
jhnwkmn | 0:97a4f8cc534c | 934 | else { |
jhnwkmn | 0:97a4f8cc534c | 935 | SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o)); |
jhnwkmn | 0:97a4f8cc534c | 936 | } |
jhnwkmn | 0:97a4f8cc534c | 937 | |
jhnwkmn | 0:97a4f8cc534c | 938 | } continue; |
jhnwkmn | 0:97a4f8cc534c | 939 | case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; |
jhnwkmn | 0:97a4f8cc534c | 940 | case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue; |
jhnwkmn | 0:97a4f8cc534c | 941 | case _OP_INSTANCEOF: |
jhnwkmn | 0:97a4f8cc534c | 942 | if(type(STK(arg1)) != OT_CLASS) |
jhnwkmn | 0:97a4f8cc534c | 943 | {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} |
jhnwkmn | 0:97a4f8cc534c | 944 | TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false; |
jhnwkmn | 0:97a4f8cc534c | 945 | continue; |
jhnwkmn | 0:97a4f8cc534c | 946 | case _OP_AND: |
jhnwkmn | 0:97a4f8cc534c | 947 | if(IsFalse(STK(arg2))) { |
jhnwkmn | 0:97a4f8cc534c | 948 | TARGET = STK(arg2); |
jhnwkmn | 0:97a4f8cc534c | 949 | ci->_ip += (sarg1); |
jhnwkmn | 0:97a4f8cc534c | 950 | } |
jhnwkmn | 0:97a4f8cc534c | 951 | continue; |
jhnwkmn | 0:97a4f8cc534c | 952 | case _OP_OR: |
jhnwkmn | 0:97a4f8cc534c | 953 | if(!IsFalse(STK(arg2))) { |
jhnwkmn | 0:97a4f8cc534c | 954 | TARGET = STK(arg2); |
jhnwkmn | 0:97a4f8cc534c | 955 | ci->_ip += (sarg1); |
jhnwkmn | 0:97a4f8cc534c | 956 | } |
jhnwkmn | 0:97a4f8cc534c | 957 | continue; |
jhnwkmn | 0:97a4f8cc534c | 958 | case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; |
jhnwkmn | 0:97a4f8cc534c | 959 | case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue; |
jhnwkmn | 0:97a4f8cc534c | 960 | case _OP_BWNOT: |
jhnwkmn | 0:97a4f8cc534c | 961 | if(type(STK(arg1)) == OT_INTEGER) { |
jhnwkmn | 0:97a4f8cc534c | 962 | SQInteger t = _integer(STK(arg1)); |
jhnwkmn | 0:97a4f8cc534c | 963 | TARGET = SQInteger(~t); |
jhnwkmn | 0:97a4f8cc534c | 964 | continue; |
jhnwkmn | 0:97a4f8cc534c | 965 | } |
jhnwkmn | 0:97a4f8cc534c | 966 | Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1))); |
jhnwkmn | 0:97a4f8cc534c | 967 | SQ_THROW(); |
jhnwkmn | 0:97a4f8cc534c | 968 | case _OP_CLOSURE: { |
jhnwkmn | 0:97a4f8cc534c | 969 | SQClosure *c = ci->_closure._unVal.pClosure; |
jhnwkmn | 0:97a4f8cc534c | 970 | SQFunctionProto *fp = c->_function; |
jhnwkmn | 0:97a4f8cc534c | 971 | if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } |
jhnwkmn | 0:97a4f8cc534c | 972 | continue; |
jhnwkmn | 0:97a4f8cc534c | 973 | } |
jhnwkmn | 0:97a4f8cc534c | 974 | case _OP_YIELD:{ |
jhnwkmn | 0:97a4f8cc534c | 975 | if(ci->_generator) { |
jhnwkmn | 0:97a4f8cc534c | 976 | if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); |
jhnwkmn | 0:97a4f8cc534c | 977 | _GUARD(ci->_generator->Yield(this,arg2)); |
jhnwkmn | 0:97a4f8cc534c | 978 | traps -= ci->_etraps; |
jhnwkmn | 0:97a4f8cc534c | 979 | if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 980 | } |
jhnwkmn | 0:97a4f8cc534c | 981 | else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} |
jhnwkmn | 0:97a4f8cc534c | 982 | if(Return(arg0, arg1, temp_reg)){ |
jhnwkmn | 0:97a4f8cc534c | 983 | assert(traps == 0); |
jhnwkmn | 0:97a4f8cc534c | 984 | outres = temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 985 | return true; |
jhnwkmn | 0:97a4f8cc534c | 986 | } |
jhnwkmn | 0:97a4f8cc534c | 987 | |
jhnwkmn | 0:97a4f8cc534c | 988 | } |
jhnwkmn | 0:97a4f8cc534c | 989 | continue; |
jhnwkmn | 0:97a4f8cc534c | 990 | case _OP_RESUME: |
jhnwkmn | 0:97a4f8cc534c | 991 | if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} |
jhnwkmn | 0:97a4f8cc534c | 992 | _GUARD(_generator(STK(arg1))->Resume(this, TARGET)); |
jhnwkmn | 0:97a4f8cc534c | 993 | traps += ci->_etraps; |
jhnwkmn | 0:97a4f8cc534c | 994 | continue; |
jhnwkmn | 0:97a4f8cc534c | 995 | case _OP_FOREACH:{ int tojump; |
jhnwkmn | 0:97a4f8cc534c | 996 | _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump)); |
jhnwkmn | 0:97a4f8cc534c | 997 | ci->_ip += tojump; } |
jhnwkmn | 0:97a4f8cc534c | 998 | continue; |
jhnwkmn | 0:97a4f8cc534c | 999 | case _OP_POSTFOREACH: |
jhnwkmn | 0:97a4f8cc534c | 1000 | assert(type(STK(arg0)) == OT_GENERATOR); |
jhnwkmn | 0:97a4f8cc534c | 1001 | if(_generator(STK(arg0))->_state == SQGenerator::eDead) |
jhnwkmn | 0:97a4f8cc534c | 1002 | ci->_ip += (sarg1 - 1); |
jhnwkmn | 0:97a4f8cc534c | 1003 | continue; |
jhnwkmn | 0:97a4f8cc534c | 1004 | case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue; |
jhnwkmn | 0:97a4f8cc534c | 1005 | case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue; |
jhnwkmn | 0:97a4f8cc534c | 1006 | case _OP_PUSHTRAP:{ |
jhnwkmn | 0:97a4f8cc534c | 1007 | SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions; |
jhnwkmn | 0:97a4f8cc534c | 1008 | _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++; |
jhnwkmn | 0:97a4f8cc534c | 1009 | ci->_etraps++; |
jhnwkmn | 0:97a4f8cc534c | 1010 | } |
jhnwkmn | 0:97a4f8cc534c | 1011 | continue; |
jhnwkmn | 0:97a4f8cc534c | 1012 | case _OP_POPTRAP: { |
jhnwkmn | 0:97a4f8cc534c | 1013 | for(SQInteger i = 0; i < arg0; i++) { |
jhnwkmn | 0:97a4f8cc534c | 1014 | _etraps.pop_back(); traps--; |
jhnwkmn | 0:97a4f8cc534c | 1015 | ci->_etraps--; |
jhnwkmn | 0:97a4f8cc534c | 1016 | } |
jhnwkmn | 0:97a4f8cc534c | 1017 | } |
jhnwkmn | 0:97a4f8cc534c | 1018 | continue; |
jhnwkmn | 0:97a4f8cc534c | 1019 | case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; |
jhnwkmn | 0:97a4f8cc534c | 1020 | case _OP_NEWSLOTA: |
jhnwkmn | 0:97a4f8cc534c | 1021 | _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false)); |
jhnwkmn | 0:97a4f8cc534c | 1022 | continue; |
jhnwkmn | 0:97a4f8cc534c | 1023 | case _OP_GETBASE:{ |
jhnwkmn | 0:97a4f8cc534c | 1024 | SQClosure *clo = _closure(ci->_closure); |
jhnwkmn | 0:97a4f8cc534c | 1025 | if(clo->_base) { |
jhnwkmn | 0:97a4f8cc534c | 1026 | TARGET = clo->_base; |
jhnwkmn | 0:97a4f8cc534c | 1027 | } |
jhnwkmn | 0:97a4f8cc534c | 1028 | else { |
jhnwkmn | 0:97a4f8cc534c | 1029 | TARGET.Null(); |
jhnwkmn | 0:97a4f8cc534c | 1030 | } |
jhnwkmn | 0:97a4f8cc534c | 1031 | continue; |
jhnwkmn | 0:97a4f8cc534c | 1032 | } |
jhnwkmn | 0:97a4f8cc534c | 1033 | case _OP_CLOSE: |
jhnwkmn | 0:97a4f8cc534c | 1034 | if(_openouters) CloseOuters(&(STK(arg1))); |
jhnwkmn | 0:97a4f8cc534c | 1035 | continue; |
jhnwkmn | 0:97a4f8cc534c | 1036 | } |
jhnwkmn | 0:97a4f8cc534c | 1037 | |
jhnwkmn | 0:97a4f8cc534c | 1038 | } |
jhnwkmn | 0:97a4f8cc534c | 1039 | } |
jhnwkmn | 0:97a4f8cc534c | 1040 | exception_trap: |
jhnwkmn | 0:97a4f8cc534c | 1041 | { |
jhnwkmn | 0:97a4f8cc534c | 1042 | SQObjectPtr currerror = _lasterror; |
jhnwkmn | 0:97a4f8cc534c | 1043 | // dumpstack(_stackbase); |
jhnwkmn | 0:97a4f8cc534c | 1044 | // SQInteger n = 0; |
jhnwkmn | 0:97a4f8cc534c | 1045 | SQInteger last_top = _top; |
jhnwkmn | 0:97a4f8cc534c | 1046 | |
jhnwkmn | 0:97a4f8cc534c | 1047 | if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror); |
jhnwkmn | 0:97a4f8cc534c | 1048 | |
jhnwkmn | 0:97a4f8cc534c | 1049 | while( ci ) { |
jhnwkmn | 0:97a4f8cc534c | 1050 | if(ci->_etraps > 0) { |
jhnwkmn | 0:97a4f8cc534c | 1051 | SQExceptionTrap &et = _etraps.top(); |
jhnwkmn | 0:97a4f8cc534c | 1052 | ci->_ip = et._ip; |
jhnwkmn | 0:97a4f8cc534c | 1053 | _top = et._stacksize; |
jhnwkmn | 0:97a4f8cc534c | 1054 | _stackbase = et._stackbase; |
jhnwkmn | 0:97a4f8cc534c | 1055 | _stack._vals[_stackbase + et._extarget] = currerror; |
jhnwkmn | 0:97a4f8cc534c | 1056 | _etraps.pop_back(); traps--; ci->_etraps--; |
jhnwkmn | 0:97a4f8cc534c | 1057 | while(last_top >= _top) _stack._vals[last_top--].Null(); |
jhnwkmn | 0:97a4f8cc534c | 1058 | goto exception_restore; |
jhnwkmn | 0:97a4f8cc534c | 1059 | } |
jhnwkmn | 0:97a4f8cc534c | 1060 | else if (_debughook) { |
jhnwkmn | 0:97a4f8cc534c | 1061 | //notify debugger of a "return" |
jhnwkmn | 0:97a4f8cc534c | 1062 | //even if it really an exception unwinding the stack |
jhnwkmn | 0:97a4f8cc534c | 1063 | for(SQInteger i = 0; i < ci->_ncalls; i++) { |
jhnwkmn | 0:97a4f8cc534c | 1064 | CallDebugHook(_SC('r')); |
jhnwkmn | 0:97a4f8cc534c | 1065 | } |
jhnwkmn | 0:97a4f8cc534c | 1066 | } |
jhnwkmn | 0:97a4f8cc534c | 1067 | if(ci->_generator) ci->_generator->Kill(); |
jhnwkmn | 0:97a4f8cc534c | 1068 | bool mustbreak = ci && ci->_root; |
jhnwkmn | 0:97a4f8cc534c | 1069 | LeaveFrame(); |
jhnwkmn | 0:97a4f8cc534c | 1070 | if(mustbreak) break; |
jhnwkmn | 0:97a4f8cc534c | 1071 | } |
jhnwkmn | 0:97a4f8cc534c | 1072 | |
jhnwkmn | 0:97a4f8cc534c | 1073 | _lasterror = currerror; |
jhnwkmn | 0:97a4f8cc534c | 1074 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1075 | } |
jhnwkmn | 0:97a4f8cc534c | 1076 | assert(0); |
jhnwkmn | 0:97a4f8cc534c | 1077 | } |
jhnwkmn | 0:97a4f8cc534c | 1078 | |
jhnwkmn | 0:97a4f8cc534c | 1079 | bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) |
jhnwkmn | 0:97a4f8cc534c | 1080 | { |
jhnwkmn | 0:97a4f8cc534c | 1081 | inst = theclass->CreateInstance(); |
jhnwkmn | 0:97a4f8cc534c | 1082 | if(!theclass->GetConstructor(constructor)) { |
jhnwkmn | 0:97a4f8cc534c | 1083 | constructor.Null(); |
jhnwkmn | 0:97a4f8cc534c | 1084 | } |
jhnwkmn | 0:97a4f8cc534c | 1085 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1086 | } |
jhnwkmn | 0:97a4f8cc534c | 1087 | |
jhnwkmn | 0:97a4f8cc534c | 1088 | void SQVM::CallErrorHandler(SQObjectPtr &error) |
jhnwkmn | 0:97a4f8cc534c | 1089 | { |
jhnwkmn | 0:97a4f8cc534c | 1090 | if(type(_errorhandler) != OT_NULL) { |
jhnwkmn | 0:97a4f8cc534c | 1091 | SQObjectPtr out; |
jhnwkmn | 0:97a4f8cc534c | 1092 | Push(_roottable); Push(error); |
jhnwkmn | 0:97a4f8cc534c | 1093 | Call(_errorhandler, 2, _top-2, out,SQFalse); |
jhnwkmn | 0:97a4f8cc534c | 1094 | Pop(2); |
jhnwkmn | 0:97a4f8cc534c | 1095 | } |
jhnwkmn | 0:97a4f8cc534c | 1096 | } |
jhnwkmn | 0:97a4f8cc534c | 1097 | |
jhnwkmn | 0:97a4f8cc534c | 1098 | |
jhnwkmn | 0:97a4f8cc534c | 1099 | void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) |
jhnwkmn | 0:97a4f8cc534c | 1100 | { |
jhnwkmn | 0:97a4f8cc534c | 1101 | _debughook = false; |
jhnwkmn | 0:97a4f8cc534c | 1102 | SQFunctionProto *func=_closure(ci->_closure)->_function; |
jhnwkmn | 0:97a4f8cc534c | 1103 | if(_debughook_native) { |
jhnwkmn | 0:97a4f8cc534c | 1104 | const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL; |
jhnwkmn | 0:97a4f8cc534c | 1105 | const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL; |
jhnwkmn | 0:97a4f8cc534c | 1106 | SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip); |
jhnwkmn | 0:97a4f8cc534c | 1107 | _debughook_native(this,type,src,line,fname); |
jhnwkmn | 0:97a4f8cc534c | 1108 | } |
jhnwkmn | 0:97a4f8cc534c | 1109 | else { |
jhnwkmn | 0:97a4f8cc534c | 1110 | SQObjectPtr temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 1111 | SQInteger nparams=5; |
jhnwkmn | 0:97a4f8cc534c | 1112 | Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); |
jhnwkmn | 0:97a4f8cc534c | 1113 | Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse); |
jhnwkmn | 0:97a4f8cc534c | 1114 | Pop(nparams); |
jhnwkmn | 0:97a4f8cc534c | 1115 | } |
jhnwkmn | 0:97a4f8cc534c | 1116 | _debughook = true; |
jhnwkmn | 0:97a4f8cc534c | 1117 | } |
jhnwkmn | 0:97a4f8cc534c | 1118 | |
jhnwkmn | 0:97a4f8cc534c | 1119 | bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend) |
jhnwkmn | 0:97a4f8cc534c | 1120 | { |
jhnwkmn | 0:97a4f8cc534c | 1121 | SQInteger nparamscheck = nclosure->_nparamscheck; |
jhnwkmn | 0:97a4f8cc534c | 1122 | SQInteger newtop = newbase + nargs + nclosure->_noutervalues; |
jhnwkmn | 0:97a4f8cc534c | 1123 | |
jhnwkmn | 0:97a4f8cc534c | 1124 | if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { |
jhnwkmn | 0:97a4f8cc534c | 1125 | Raise_Error(_SC("Native stack overflow")); |
jhnwkmn | 0:97a4f8cc534c | 1126 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1127 | } |
jhnwkmn | 0:97a4f8cc534c | 1128 | |
jhnwkmn | 0:97a4f8cc534c | 1129 | if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) || |
jhnwkmn | 0:97a4f8cc534c | 1130 | ((nparamscheck < 0) && (nargs < (-nparamscheck))))) |
jhnwkmn | 0:97a4f8cc534c | 1131 | { |
jhnwkmn | 0:97a4f8cc534c | 1132 | Raise_Error(_SC("wrong number of parameters")); |
jhnwkmn | 0:97a4f8cc534c | 1133 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1134 | } |
jhnwkmn | 0:97a4f8cc534c | 1135 | |
jhnwkmn | 0:97a4f8cc534c | 1136 | SQInteger tcs; |
jhnwkmn | 0:97a4f8cc534c | 1137 | SQIntVec &tc = nclosure->_typecheck; |
jhnwkmn | 0:97a4f8cc534c | 1138 | if((tcs = tc.size())) { |
jhnwkmn | 0:97a4f8cc534c | 1139 | for(SQInteger i = 0; i < nargs && i < tcs; i++) { |
jhnwkmn | 0:97a4f8cc534c | 1140 | if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) { |
jhnwkmn | 0:97a4f8cc534c | 1141 | Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i])); |
jhnwkmn | 0:97a4f8cc534c | 1142 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1143 | } |
jhnwkmn | 0:97a4f8cc534c | 1144 | } |
jhnwkmn | 0:97a4f8cc534c | 1145 | } |
jhnwkmn | 0:97a4f8cc534c | 1146 | |
jhnwkmn | 0:97a4f8cc534c | 1147 | if(!EnterFrame(newbase, newtop, false)) return false; |
jhnwkmn | 0:97a4f8cc534c | 1148 | ci->_closure = nclosure; |
jhnwkmn | 0:97a4f8cc534c | 1149 | |
jhnwkmn | 0:97a4f8cc534c | 1150 | SQInteger outers = nclosure->_noutervalues; |
jhnwkmn | 0:97a4f8cc534c | 1151 | for (SQInteger i = 0; i < outers; i++) { |
jhnwkmn | 0:97a4f8cc534c | 1152 | _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i]; |
jhnwkmn | 0:97a4f8cc534c | 1153 | } |
jhnwkmn | 0:97a4f8cc534c | 1154 | if(nclosure->_env) { |
jhnwkmn | 0:97a4f8cc534c | 1155 | _stack._vals[newbase] = nclosure->_env->_obj; |
jhnwkmn | 0:97a4f8cc534c | 1156 | } |
jhnwkmn | 0:97a4f8cc534c | 1157 | |
jhnwkmn | 0:97a4f8cc534c | 1158 | _nnativecalls++; |
jhnwkmn | 0:97a4f8cc534c | 1159 | SQInteger ret = (nclosure->_function)(this); |
jhnwkmn | 0:97a4f8cc534c | 1160 | _nnativecalls--; |
jhnwkmn | 0:97a4f8cc534c | 1161 | |
jhnwkmn | 0:97a4f8cc534c | 1162 | suspend = false; |
jhnwkmn | 0:97a4f8cc534c | 1163 | if (ret == SQ_SUSPEND_FLAG) { |
jhnwkmn | 0:97a4f8cc534c | 1164 | suspend = true; |
jhnwkmn | 0:97a4f8cc534c | 1165 | } |
jhnwkmn | 0:97a4f8cc534c | 1166 | else if (ret < 0) { |
jhnwkmn | 0:97a4f8cc534c | 1167 | LeaveFrame(); |
jhnwkmn | 0:97a4f8cc534c | 1168 | Raise_Error(_lasterror); |
jhnwkmn | 0:97a4f8cc534c | 1169 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1170 | } |
jhnwkmn | 0:97a4f8cc534c | 1171 | if(ret) { |
jhnwkmn | 0:97a4f8cc534c | 1172 | retval = _stack._vals[_top-1]; |
jhnwkmn | 0:97a4f8cc534c | 1173 | } |
jhnwkmn | 0:97a4f8cc534c | 1174 | else { |
jhnwkmn | 0:97a4f8cc534c | 1175 | retval.Null(); |
jhnwkmn | 0:97a4f8cc534c | 1176 | } |
jhnwkmn | 0:97a4f8cc534c | 1177 | //retval = ret ? _stack._vals[_top-1] : _null_; |
jhnwkmn | 0:97a4f8cc534c | 1178 | LeaveFrame(); |
jhnwkmn | 0:97a4f8cc534c | 1179 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1180 | } |
jhnwkmn | 0:97a4f8cc534c | 1181 | |
jhnwkmn | 0:97a4f8cc534c | 1182 | #define FALLBACK_OK 0 |
jhnwkmn | 0:97a4f8cc534c | 1183 | #define FALLBACK_NO_MATCH 1 |
jhnwkmn | 0:97a4f8cc534c | 1184 | #define FALLBACK_ERROR 2 |
jhnwkmn | 0:97a4f8cc534c | 1185 | |
jhnwkmn | 0:97a4f8cc534c | 1186 | bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx) |
jhnwkmn | 0:97a4f8cc534c | 1187 | { |
jhnwkmn | 0:97a4f8cc534c | 1188 | switch(type(self)){ |
jhnwkmn | 0:97a4f8cc534c | 1189 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 1190 | if(_table(self)->Get(key,dest))return true; |
jhnwkmn | 0:97a4f8cc534c | 1191 | break; |
jhnwkmn | 0:97a4f8cc534c | 1192 | case OT_ARRAY: |
jhnwkmn | 0:97a4f8cc534c | 1193 | if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; } |
jhnwkmn | 0:97a4f8cc534c | 1194 | break; |
jhnwkmn | 0:97a4f8cc534c | 1195 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 1196 | if(_instance(self)->Get(key,dest)) return true; |
jhnwkmn | 0:97a4f8cc534c | 1197 | break; |
jhnwkmn | 0:97a4f8cc534c | 1198 | case OT_CLASS: |
jhnwkmn | 0:97a4f8cc534c | 1199 | if(_class(self)->Get(key,dest)) return true; |
jhnwkmn | 0:97a4f8cc534c | 1200 | break; |
jhnwkmn | 0:97a4f8cc534c | 1201 | case OT_STRING: |
jhnwkmn | 0:97a4f8cc534c | 1202 | if(sq_isnumeric(key)){ |
jhnwkmn | 0:97a4f8cc534c | 1203 | SQInteger n = tointeger(key); |
jhnwkmn | 0:97a4f8cc534c | 1204 | if(abs((int)n) < _string(self)->_len) { |
jhnwkmn | 0:97a4f8cc534c | 1205 | if(n < 0) n = _string(self)->_len - n; |
jhnwkmn | 0:97a4f8cc534c | 1206 | dest = SQInteger(_stringval(self)[n]); |
jhnwkmn | 0:97a4f8cc534c | 1207 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1208 | } |
jhnwkmn | 0:97a4f8cc534c | 1209 | Raise_IdxError(key); |
jhnwkmn | 0:97a4f8cc534c | 1210 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1211 | } |
jhnwkmn | 0:97a4f8cc534c | 1212 | break; |
jhnwkmn | 0:97a4f8cc534c | 1213 | default:break; //shut up compiler |
jhnwkmn | 0:97a4f8cc534c | 1214 | } |
jhnwkmn | 0:97a4f8cc534c | 1215 | if(!raw) { |
jhnwkmn | 0:97a4f8cc534c | 1216 | switch(FallBackGet(self,key,dest)) { |
jhnwkmn | 0:97a4f8cc534c | 1217 | case FALLBACK_OK: return true; //okie |
jhnwkmn | 0:97a4f8cc534c | 1218 | case FALLBACK_NO_MATCH: break; //keep falling back |
jhnwkmn | 0:97a4f8cc534c | 1219 | case FALLBACK_ERROR: return false; // the metamethod failed |
jhnwkmn | 0:97a4f8cc534c | 1220 | } |
jhnwkmn | 0:97a4f8cc534c | 1221 | if(InvokeDefaultDelegate(self,key,dest)) { |
jhnwkmn | 0:97a4f8cc534c | 1222 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1223 | } |
jhnwkmn | 0:97a4f8cc534c | 1224 | } |
jhnwkmn | 0:97a4f8cc534c | 1225 | //#ifdef ROOT_FALLBACK |
jhnwkmn | 0:97a4f8cc534c | 1226 | if(selfidx == 0) { |
jhnwkmn | 0:97a4f8cc534c | 1227 | if(_table(_roottable)->Get(key,dest)) return true; |
jhnwkmn | 0:97a4f8cc534c | 1228 | } |
jhnwkmn | 0:97a4f8cc534c | 1229 | //#endif |
jhnwkmn | 0:97a4f8cc534c | 1230 | Raise_IdxError(key); |
jhnwkmn | 0:97a4f8cc534c | 1231 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1232 | } |
jhnwkmn | 0:97a4f8cc534c | 1233 | |
jhnwkmn | 0:97a4f8cc534c | 1234 | bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) |
jhnwkmn | 0:97a4f8cc534c | 1235 | { |
jhnwkmn | 0:97a4f8cc534c | 1236 | SQTable *ddel = NULL; |
jhnwkmn | 0:97a4f8cc534c | 1237 | switch(type(self)) { |
jhnwkmn | 0:97a4f8cc534c | 1238 | case OT_CLASS: ddel = _class_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1239 | case OT_TABLE: ddel = _table_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1240 | case OT_ARRAY: ddel = _array_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1241 | case OT_STRING: ddel = _string_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1242 | case OT_INSTANCE: ddel = _instance_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1243 | case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1244 | case OT_GENERATOR: ddel = _generator_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1245 | case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1246 | case OT_THREAD: ddel = _thread_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1247 | case OT_WEAKREF: ddel = _weakref_ddel; break; |
jhnwkmn | 0:97a4f8cc534c | 1248 | default: return false; |
jhnwkmn | 0:97a4f8cc534c | 1249 | } |
jhnwkmn | 0:97a4f8cc534c | 1250 | return ddel->Get(key,dest); |
jhnwkmn | 0:97a4f8cc534c | 1251 | } |
jhnwkmn | 0:97a4f8cc534c | 1252 | |
jhnwkmn | 0:97a4f8cc534c | 1253 | |
jhnwkmn | 0:97a4f8cc534c | 1254 | SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) |
jhnwkmn | 0:97a4f8cc534c | 1255 | { |
jhnwkmn | 0:97a4f8cc534c | 1256 | switch(type(self)){ |
jhnwkmn | 0:97a4f8cc534c | 1257 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 1258 | case OT_USERDATA: |
jhnwkmn | 0:97a4f8cc534c | 1259 | //delegation |
jhnwkmn | 0:97a4f8cc534c | 1260 | if(_delegable(self)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 1261 | if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK; |
jhnwkmn | 0:97a4f8cc534c | 1262 | } |
jhnwkmn | 0:97a4f8cc534c | 1263 | else { |
jhnwkmn | 0:97a4f8cc534c | 1264 | return FALLBACK_NO_MATCH; |
jhnwkmn | 0:97a4f8cc534c | 1265 | } |
jhnwkmn | 0:97a4f8cc534c | 1266 | //go through |
jhnwkmn | 0:97a4f8cc534c | 1267 | case OT_INSTANCE: { |
jhnwkmn | 0:97a4f8cc534c | 1268 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 1269 | if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 1270 | Push(self);Push(key); |
jhnwkmn | 0:97a4f8cc534c | 1271 | _nmetamethodscall++; |
jhnwkmn | 0:97a4f8cc534c | 1272 | AutoDec ad(&_nmetamethodscall); |
jhnwkmn | 0:97a4f8cc534c | 1273 | if(Call(closure, 2, _top - 2, dest, SQFalse)) { |
jhnwkmn | 0:97a4f8cc534c | 1274 | Pop(2); |
jhnwkmn | 0:97a4f8cc534c | 1275 | return FALLBACK_OK; |
jhnwkmn | 0:97a4f8cc534c | 1276 | } |
jhnwkmn | 0:97a4f8cc534c | 1277 | else { |
jhnwkmn | 0:97a4f8cc534c | 1278 | Pop(2); |
jhnwkmn | 0:97a4f8cc534c | 1279 | if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) |
jhnwkmn | 0:97a4f8cc534c | 1280 | return FALLBACK_ERROR; |
jhnwkmn | 0:97a4f8cc534c | 1281 | } |
jhnwkmn | 0:97a4f8cc534c | 1282 | } |
jhnwkmn | 0:97a4f8cc534c | 1283 | } |
jhnwkmn | 0:97a4f8cc534c | 1284 | } |
jhnwkmn | 0:97a4f8cc534c | 1285 | break; |
jhnwkmn | 0:97a4f8cc534c | 1286 | default: break;//shutup GCC 4.x |
jhnwkmn | 0:97a4f8cc534c | 1287 | } |
jhnwkmn | 0:97a4f8cc534c | 1288 | // no metamethod or no fallback type |
jhnwkmn | 0:97a4f8cc534c | 1289 | return FALLBACK_NO_MATCH; |
jhnwkmn | 0:97a4f8cc534c | 1290 | } |
jhnwkmn | 0:97a4f8cc534c | 1291 | |
jhnwkmn | 0:97a4f8cc534c | 1292 | bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx) |
jhnwkmn | 0:97a4f8cc534c | 1293 | { |
jhnwkmn | 0:97a4f8cc534c | 1294 | switch(type(self)){ |
jhnwkmn | 0:97a4f8cc534c | 1295 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 1296 | if(_table(self)->Set(key,val)) return true; |
jhnwkmn | 0:97a4f8cc534c | 1297 | break; |
jhnwkmn | 0:97a4f8cc534c | 1298 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 1299 | if(_instance(self)->Set(key,val)) return true; |
jhnwkmn | 0:97a4f8cc534c | 1300 | break; |
jhnwkmn | 0:97a4f8cc534c | 1301 | case OT_ARRAY: |
jhnwkmn | 0:97a4f8cc534c | 1302 | if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } |
jhnwkmn | 0:97a4f8cc534c | 1303 | if(!_array(self)->Set(tointeger(key),val)) { |
jhnwkmn | 0:97a4f8cc534c | 1304 | Raise_IdxError(key); |
jhnwkmn | 0:97a4f8cc534c | 1305 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1306 | } |
jhnwkmn | 0:97a4f8cc534c | 1307 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1308 | default: |
jhnwkmn | 0:97a4f8cc534c | 1309 | Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); |
jhnwkmn | 0:97a4f8cc534c | 1310 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1311 | } |
jhnwkmn | 0:97a4f8cc534c | 1312 | |
jhnwkmn | 0:97a4f8cc534c | 1313 | switch(FallBackSet(self,key,val)) { |
jhnwkmn | 0:97a4f8cc534c | 1314 | case FALLBACK_OK: return true; //okie |
jhnwkmn | 0:97a4f8cc534c | 1315 | case FALLBACK_NO_MATCH: break; //keep falling back |
jhnwkmn | 0:97a4f8cc534c | 1316 | case FALLBACK_ERROR: return false; // the metamethod failed |
jhnwkmn | 0:97a4f8cc534c | 1317 | } |
jhnwkmn | 0:97a4f8cc534c | 1318 | if(selfidx == 0) { |
jhnwkmn | 0:97a4f8cc534c | 1319 | if(_table(_roottable)->Set(key,val)) |
jhnwkmn | 0:97a4f8cc534c | 1320 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1321 | } |
jhnwkmn | 0:97a4f8cc534c | 1322 | Raise_IdxError(key); |
jhnwkmn | 0:97a4f8cc534c | 1323 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1324 | } |
jhnwkmn | 0:97a4f8cc534c | 1325 | |
jhnwkmn | 0:97a4f8cc534c | 1326 | SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val) |
jhnwkmn | 0:97a4f8cc534c | 1327 | { |
jhnwkmn | 0:97a4f8cc534c | 1328 | switch(type(self)) { |
jhnwkmn | 0:97a4f8cc534c | 1329 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 1330 | if(_table(self)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 1331 | if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK; |
jhnwkmn | 0:97a4f8cc534c | 1332 | } |
jhnwkmn | 0:97a4f8cc534c | 1333 | //keps on going |
jhnwkmn | 0:97a4f8cc534c | 1334 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 1335 | case OT_USERDATA:{ |
jhnwkmn | 0:97a4f8cc534c | 1336 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 1337 | SQObjectPtr t; |
jhnwkmn | 0:97a4f8cc534c | 1338 | if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) { |
jhnwkmn | 0:97a4f8cc534c | 1339 | Push(self);Push(key);Push(val); |
jhnwkmn | 0:97a4f8cc534c | 1340 | _nmetamethodscall++; |
jhnwkmn | 0:97a4f8cc534c | 1341 | AutoDec ad(&_nmetamethodscall); |
jhnwkmn | 0:97a4f8cc534c | 1342 | if(Call(closure, 3, _top - 3, t, SQFalse)) { |
jhnwkmn | 0:97a4f8cc534c | 1343 | Pop(3); |
jhnwkmn | 0:97a4f8cc534c | 1344 | return FALLBACK_OK; |
jhnwkmn | 0:97a4f8cc534c | 1345 | } |
jhnwkmn | 0:97a4f8cc534c | 1346 | else { |
jhnwkmn | 0:97a4f8cc534c | 1347 | if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) |
jhnwkmn | 0:97a4f8cc534c | 1348 | //error |
jhnwkmn | 0:97a4f8cc534c | 1349 | Pop(3); |
jhnwkmn | 0:97a4f8cc534c | 1350 | return FALLBACK_ERROR; |
jhnwkmn | 0:97a4f8cc534c | 1351 | } |
jhnwkmn | 0:97a4f8cc534c | 1352 | } |
jhnwkmn | 0:97a4f8cc534c | 1353 | } |
jhnwkmn | 0:97a4f8cc534c | 1354 | } |
jhnwkmn | 0:97a4f8cc534c | 1355 | break; |
jhnwkmn | 0:97a4f8cc534c | 1356 | default: break;//shutup GCC 4.x |
jhnwkmn | 0:97a4f8cc534c | 1357 | } |
jhnwkmn | 0:97a4f8cc534c | 1358 | // no metamethod or no fallback type |
jhnwkmn | 0:97a4f8cc534c | 1359 | return FALLBACK_NO_MATCH; |
jhnwkmn | 0:97a4f8cc534c | 1360 | } |
jhnwkmn | 0:97a4f8cc534c | 1361 | |
jhnwkmn | 0:97a4f8cc534c | 1362 | bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) |
jhnwkmn | 0:97a4f8cc534c | 1363 | { |
jhnwkmn | 0:97a4f8cc534c | 1364 | SQObjectPtr temp_reg; |
jhnwkmn | 0:97a4f8cc534c | 1365 | SQObjectPtr newobj; |
jhnwkmn | 0:97a4f8cc534c | 1366 | switch(type(self)){ |
jhnwkmn | 0:97a4f8cc534c | 1367 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 1368 | newobj = _table(self)->Clone(); |
jhnwkmn | 0:97a4f8cc534c | 1369 | goto cloned_mt; |
jhnwkmn | 0:97a4f8cc534c | 1370 | case OT_INSTANCE: { |
jhnwkmn | 0:97a4f8cc534c | 1371 | newobj = _instance(self)->Clone(_ss(this)); |
jhnwkmn | 0:97a4f8cc534c | 1372 | cloned_mt: |
jhnwkmn | 0:97a4f8cc534c | 1373 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 1374 | if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) { |
jhnwkmn | 0:97a4f8cc534c | 1375 | Push(newobj); |
jhnwkmn | 0:97a4f8cc534c | 1376 | Push(self); |
jhnwkmn | 0:97a4f8cc534c | 1377 | if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg)) |
jhnwkmn | 0:97a4f8cc534c | 1378 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1379 | } |
jhnwkmn | 0:97a4f8cc534c | 1380 | } |
jhnwkmn | 0:97a4f8cc534c | 1381 | target = newobj; |
jhnwkmn | 0:97a4f8cc534c | 1382 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1383 | case OT_ARRAY: |
jhnwkmn | 0:97a4f8cc534c | 1384 | target = _array(self)->Clone(); |
jhnwkmn | 0:97a4f8cc534c | 1385 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1386 | default: |
jhnwkmn | 0:97a4f8cc534c | 1387 | Raise_Error(_SC("cloning a %s"), GetTypeName(self)); |
jhnwkmn | 0:97a4f8cc534c | 1388 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1389 | } |
jhnwkmn | 0:97a4f8cc534c | 1390 | } |
jhnwkmn | 0:97a4f8cc534c | 1391 | |
jhnwkmn | 0:97a4f8cc534c | 1392 | bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw) |
jhnwkmn | 0:97a4f8cc534c | 1393 | { |
jhnwkmn | 0:97a4f8cc534c | 1394 | if(type(self) != OT_CLASS) { |
jhnwkmn | 0:97a4f8cc534c | 1395 | Raise_Error(_SC("object must be a class")); |
jhnwkmn | 0:97a4f8cc534c | 1396 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1397 | } |
jhnwkmn | 0:97a4f8cc534c | 1398 | SQClass *c = _class(self); |
jhnwkmn | 0:97a4f8cc534c | 1399 | if(!raw) { |
jhnwkmn | 0:97a4f8cc534c | 1400 | SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER]; |
jhnwkmn | 0:97a4f8cc534c | 1401 | if(type(mm) != OT_NULL ) { |
jhnwkmn | 0:97a4f8cc534c | 1402 | Push(self); Push(key); Push(val); |
jhnwkmn | 0:97a4f8cc534c | 1403 | Push(attrs); |
jhnwkmn | 0:97a4f8cc534c | 1404 | Push(bstatic); |
jhnwkmn | 0:97a4f8cc534c | 1405 | return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg); |
jhnwkmn | 0:97a4f8cc534c | 1406 | } |
jhnwkmn | 0:97a4f8cc534c | 1407 | } |
jhnwkmn | 0:97a4f8cc534c | 1408 | if(!NewSlot(self, key, val,bstatic)) |
jhnwkmn | 0:97a4f8cc534c | 1409 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1410 | if(type(attrs) != OT_NULL) { |
jhnwkmn | 0:97a4f8cc534c | 1411 | c->SetAttributes(key,attrs); |
jhnwkmn | 0:97a4f8cc534c | 1412 | } |
jhnwkmn | 0:97a4f8cc534c | 1413 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1414 | } |
jhnwkmn | 0:97a4f8cc534c | 1415 | |
jhnwkmn | 0:97a4f8cc534c | 1416 | bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) |
jhnwkmn | 0:97a4f8cc534c | 1417 | { |
jhnwkmn | 0:97a4f8cc534c | 1418 | if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } |
jhnwkmn | 0:97a4f8cc534c | 1419 | switch(type(self)) { |
jhnwkmn | 0:97a4f8cc534c | 1420 | case OT_TABLE: { |
jhnwkmn | 0:97a4f8cc534c | 1421 | bool rawcall = true; |
jhnwkmn | 0:97a4f8cc534c | 1422 | if(_table(self)->_delegate) { |
jhnwkmn | 0:97a4f8cc534c | 1423 | SQObjectPtr res; |
jhnwkmn | 0:97a4f8cc534c | 1424 | if(!_table(self)->Get(key,res)) { |
jhnwkmn | 0:97a4f8cc534c | 1425 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 1426 | if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { |
jhnwkmn | 0:97a4f8cc534c | 1427 | Push(self);Push(key);Push(val); |
jhnwkmn | 0:97a4f8cc534c | 1428 | if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { |
jhnwkmn | 0:97a4f8cc534c | 1429 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1430 | } |
jhnwkmn | 0:97a4f8cc534c | 1431 | rawcall = false; |
jhnwkmn | 0:97a4f8cc534c | 1432 | } |
jhnwkmn | 0:97a4f8cc534c | 1433 | else { |
jhnwkmn | 0:97a4f8cc534c | 1434 | rawcall = true; |
jhnwkmn | 0:97a4f8cc534c | 1435 | } |
jhnwkmn | 0:97a4f8cc534c | 1436 | } |
jhnwkmn | 0:97a4f8cc534c | 1437 | } |
jhnwkmn | 0:97a4f8cc534c | 1438 | if(rawcall) _table(self)->NewSlot(key,val); //cannot fail |
jhnwkmn | 0:97a4f8cc534c | 1439 | |
jhnwkmn | 0:97a4f8cc534c | 1440 | break;} |
jhnwkmn | 0:97a4f8cc534c | 1441 | case OT_INSTANCE: { |
jhnwkmn | 0:97a4f8cc534c | 1442 | SQObjectPtr res; |
jhnwkmn | 0:97a4f8cc534c | 1443 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 1444 | if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { |
jhnwkmn | 0:97a4f8cc534c | 1445 | Push(self);Push(key);Push(val); |
jhnwkmn | 0:97a4f8cc534c | 1446 | if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { |
jhnwkmn | 0:97a4f8cc534c | 1447 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1448 | } |
jhnwkmn | 0:97a4f8cc534c | 1449 | break; |
jhnwkmn | 0:97a4f8cc534c | 1450 | } |
jhnwkmn | 0:97a4f8cc534c | 1451 | Raise_Error(_SC("class instances do not support the new slot operator")); |
jhnwkmn | 0:97a4f8cc534c | 1452 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1453 | break;} |
jhnwkmn | 0:97a4f8cc534c | 1454 | case OT_CLASS: |
jhnwkmn | 0:97a4f8cc534c | 1455 | if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { |
jhnwkmn | 0:97a4f8cc534c | 1456 | if(_class(self)->_locked) { |
jhnwkmn | 0:97a4f8cc534c | 1457 | Raise_Error(_SC("trying to modify a class that has already been instantiated")); |
jhnwkmn | 0:97a4f8cc534c | 1458 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1459 | } |
jhnwkmn | 0:97a4f8cc534c | 1460 | else { |
jhnwkmn | 0:97a4f8cc534c | 1461 | SQObjectPtr oval = PrintObjVal(key); |
jhnwkmn | 0:97a4f8cc534c | 1462 | Raise_Error(_SC("the property '%s' already exists"),_stringval(oval)); |
jhnwkmn | 0:97a4f8cc534c | 1463 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1464 | } |
jhnwkmn | 0:97a4f8cc534c | 1465 | } |
jhnwkmn | 0:97a4f8cc534c | 1466 | break; |
jhnwkmn | 0:97a4f8cc534c | 1467 | default: |
jhnwkmn | 0:97a4f8cc534c | 1468 | Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); |
jhnwkmn | 0:97a4f8cc534c | 1469 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1470 | break; |
jhnwkmn | 0:97a4f8cc534c | 1471 | } |
jhnwkmn | 0:97a4f8cc534c | 1472 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1473 | } |
jhnwkmn | 0:97a4f8cc534c | 1474 | |
jhnwkmn | 0:97a4f8cc534c | 1475 | |
jhnwkmn | 0:97a4f8cc534c | 1476 | |
jhnwkmn | 0:97a4f8cc534c | 1477 | bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) |
jhnwkmn | 0:97a4f8cc534c | 1478 | { |
jhnwkmn | 0:97a4f8cc534c | 1479 | switch(type(self)) { |
jhnwkmn | 0:97a4f8cc534c | 1480 | case OT_TABLE: |
jhnwkmn | 0:97a4f8cc534c | 1481 | case OT_INSTANCE: |
jhnwkmn | 0:97a4f8cc534c | 1482 | case OT_USERDATA: { |
jhnwkmn | 0:97a4f8cc534c | 1483 | SQObjectPtr t; |
jhnwkmn | 0:97a4f8cc534c | 1484 | //bool handled = false; |
jhnwkmn | 0:97a4f8cc534c | 1485 | SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 1486 | if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) { |
jhnwkmn | 0:97a4f8cc534c | 1487 | Push(self);Push(key); |
jhnwkmn | 0:97a4f8cc534c | 1488 | return CallMetaMethod(closure,MT_DELSLOT,2,res); |
jhnwkmn | 0:97a4f8cc534c | 1489 | } |
jhnwkmn | 0:97a4f8cc534c | 1490 | else { |
jhnwkmn | 0:97a4f8cc534c | 1491 | if(type(self) == OT_TABLE) { |
jhnwkmn | 0:97a4f8cc534c | 1492 | if(_table(self)->Get(key,t)) { |
jhnwkmn | 0:97a4f8cc534c | 1493 | _table(self)->Remove(key); |
jhnwkmn | 0:97a4f8cc534c | 1494 | } |
jhnwkmn | 0:97a4f8cc534c | 1495 | else { |
jhnwkmn | 0:97a4f8cc534c | 1496 | Raise_IdxError((SQObject &)key); |
jhnwkmn | 0:97a4f8cc534c | 1497 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1498 | } |
jhnwkmn | 0:97a4f8cc534c | 1499 | } |
jhnwkmn | 0:97a4f8cc534c | 1500 | else { |
jhnwkmn | 0:97a4f8cc534c | 1501 | Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self)); |
jhnwkmn | 0:97a4f8cc534c | 1502 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1503 | } |
jhnwkmn | 0:97a4f8cc534c | 1504 | } |
jhnwkmn | 0:97a4f8cc534c | 1505 | res = t; |
jhnwkmn | 0:97a4f8cc534c | 1506 | } |
jhnwkmn | 0:97a4f8cc534c | 1507 | break; |
jhnwkmn | 0:97a4f8cc534c | 1508 | default: |
jhnwkmn | 0:97a4f8cc534c | 1509 | Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self)); |
jhnwkmn | 0:97a4f8cc534c | 1510 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1511 | } |
jhnwkmn | 0:97a4f8cc534c | 1512 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1513 | } |
jhnwkmn | 0:97a4f8cc534c | 1514 | |
jhnwkmn | 0:97a4f8cc534c | 1515 | bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror) |
jhnwkmn | 0:97a4f8cc534c | 1516 | { |
jhnwkmn | 0:97a4f8cc534c | 1517 | #ifdef _DEBUG |
jhnwkmn | 0:97a4f8cc534c | 1518 | SQInteger prevstackbase = _stackbase; |
jhnwkmn | 0:97a4f8cc534c | 1519 | #endif |
jhnwkmn | 0:97a4f8cc534c | 1520 | switch(type(closure)) { |
jhnwkmn | 0:97a4f8cc534c | 1521 | case OT_CLOSURE: |
jhnwkmn | 0:97a4f8cc534c | 1522 | return Execute(closure, nparams, stackbase, outres, raiseerror); |
jhnwkmn | 0:97a4f8cc534c | 1523 | break; |
jhnwkmn | 0:97a4f8cc534c | 1524 | case OT_NATIVECLOSURE:{ |
jhnwkmn | 0:97a4f8cc534c | 1525 | bool suspend; |
jhnwkmn | 0:97a4f8cc534c | 1526 | return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend); |
jhnwkmn | 0:97a4f8cc534c | 1527 | |
jhnwkmn | 0:97a4f8cc534c | 1528 | } |
jhnwkmn | 0:97a4f8cc534c | 1529 | break; |
jhnwkmn | 0:97a4f8cc534c | 1530 | case OT_CLASS: { |
jhnwkmn | 0:97a4f8cc534c | 1531 | SQObjectPtr constr; |
jhnwkmn | 0:97a4f8cc534c | 1532 | SQObjectPtr temp; |
jhnwkmn | 0:97a4f8cc534c | 1533 | CreateClassInstance(_class(closure),outres,constr); |
jhnwkmn | 0:97a4f8cc534c | 1534 | if(type(constr) != OT_NULL) { |
jhnwkmn | 0:97a4f8cc534c | 1535 | _stack[stackbase] = outres; |
jhnwkmn | 0:97a4f8cc534c | 1536 | return Call(constr,nparams,stackbase,temp,raiseerror); |
jhnwkmn | 0:97a4f8cc534c | 1537 | } |
jhnwkmn | 0:97a4f8cc534c | 1538 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1539 | } |
jhnwkmn | 0:97a4f8cc534c | 1540 | break; |
jhnwkmn | 0:97a4f8cc534c | 1541 | default: |
jhnwkmn | 0:97a4f8cc534c | 1542 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1543 | } |
jhnwkmn | 0:97a4f8cc534c | 1544 | #ifdef _DEBUG |
jhnwkmn | 0:97a4f8cc534c | 1545 | if(!_suspended) { |
jhnwkmn | 0:97a4f8cc534c | 1546 | assert(_stackbase == prevstackbase); |
jhnwkmn | 0:97a4f8cc534c | 1547 | } |
jhnwkmn | 0:97a4f8cc534c | 1548 | #endif |
jhnwkmn | 0:97a4f8cc534c | 1549 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1550 | } |
jhnwkmn | 0:97a4f8cc534c | 1551 | |
jhnwkmn | 0:97a4f8cc534c | 1552 | bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) |
jhnwkmn | 0:97a4f8cc534c | 1553 | { |
jhnwkmn | 0:97a4f8cc534c | 1554 | //SQObjectPtr closure; |
jhnwkmn | 0:97a4f8cc534c | 1555 | |
jhnwkmn | 0:97a4f8cc534c | 1556 | _nmetamethodscall++; |
jhnwkmn | 0:97a4f8cc534c | 1557 | if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { |
jhnwkmn | 0:97a4f8cc534c | 1558 | _nmetamethodscall--; |
jhnwkmn | 0:97a4f8cc534c | 1559 | Pop(nparams); |
jhnwkmn | 0:97a4f8cc534c | 1560 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1561 | } |
jhnwkmn | 0:97a4f8cc534c | 1562 | _nmetamethodscall--; |
jhnwkmn | 0:97a4f8cc534c | 1563 | //} |
jhnwkmn | 0:97a4f8cc534c | 1564 | Pop(nparams); |
jhnwkmn | 0:97a4f8cc534c | 1565 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1566 | } |
jhnwkmn | 0:97a4f8cc534c | 1567 | |
jhnwkmn | 0:97a4f8cc534c | 1568 | void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex) |
jhnwkmn | 0:97a4f8cc534c | 1569 | { |
jhnwkmn | 0:97a4f8cc534c | 1570 | SQOuter **pp = &_openouters; |
jhnwkmn | 0:97a4f8cc534c | 1571 | SQOuter *p; |
jhnwkmn | 0:97a4f8cc534c | 1572 | SQOuter *otr; |
jhnwkmn | 0:97a4f8cc534c | 1573 | |
jhnwkmn | 0:97a4f8cc534c | 1574 | while ((p = *pp) != NULL && p->_valptr >= stackindex) { |
jhnwkmn | 0:97a4f8cc534c | 1575 | if (p->_valptr == stackindex) { |
jhnwkmn | 0:97a4f8cc534c | 1576 | target = SQObjectPtr(p); |
jhnwkmn | 0:97a4f8cc534c | 1577 | return; |
jhnwkmn | 0:97a4f8cc534c | 1578 | } |
jhnwkmn | 0:97a4f8cc534c | 1579 | pp = &p->_next; |
jhnwkmn | 0:97a4f8cc534c | 1580 | } |
jhnwkmn | 0:97a4f8cc534c | 1581 | otr = SQOuter::Create(_ss(this), stackindex); |
jhnwkmn | 0:97a4f8cc534c | 1582 | otr->_next = *pp; |
jhnwkmn | 0:97a4f8cc534c | 1583 | otr->_idx = (stackindex - _stack._vals); |
jhnwkmn | 0:97a4f8cc534c | 1584 | __ObjAddRef(otr); |
jhnwkmn | 0:97a4f8cc534c | 1585 | *pp = otr; |
jhnwkmn | 0:97a4f8cc534c | 1586 | target = SQObjectPtr(otr); |
jhnwkmn | 0:97a4f8cc534c | 1587 | } |
jhnwkmn | 0:97a4f8cc534c | 1588 | |
jhnwkmn | 0:97a4f8cc534c | 1589 | bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall) |
jhnwkmn | 0:97a4f8cc534c | 1590 | { |
jhnwkmn | 0:97a4f8cc534c | 1591 | if( !tailcall ) { |
jhnwkmn | 0:97a4f8cc534c | 1592 | if( _callsstacksize == _alloccallsstacksize ) { |
jhnwkmn | 0:97a4f8cc534c | 1593 | GrowCallStack(); |
jhnwkmn | 0:97a4f8cc534c | 1594 | } |
jhnwkmn | 0:97a4f8cc534c | 1595 | ci = &_callsstack[_callsstacksize++]; |
jhnwkmn | 0:97a4f8cc534c | 1596 | ci->_prevstkbase = (SQInt32)(newbase - _stackbase); |
jhnwkmn | 0:97a4f8cc534c | 1597 | ci->_prevtop = (SQInt32)(_top - _stackbase); |
jhnwkmn | 0:97a4f8cc534c | 1598 | ci->_etraps = 0; |
jhnwkmn | 0:97a4f8cc534c | 1599 | ci->_ncalls = 1; |
jhnwkmn | 0:97a4f8cc534c | 1600 | ci->_generator = NULL; |
jhnwkmn | 0:97a4f8cc534c | 1601 | ci->_root = SQFalse; |
jhnwkmn | 0:97a4f8cc534c | 1602 | } |
jhnwkmn | 0:97a4f8cc534c | 1603 | else { |
jhnwkmn | 0:97a4f8cc534c | 1604 | ci->_ncalls++; |
jhnwkmn | 0:97a4f8cc534c | 1605 | } |
jhnwkmn | 0:97a4f8cc534c | 1606 | |
jhnwkmn | 0:97a4f8cc534c | 1607 | _stackbase = newbase; |
jhnwkmn | 0:97a4f8cc534c | 1608 | _top = newtop; |
jhnwkmn | 0:97a4f8cc534c | 1609 | if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) { |
jhnwkmn | 0:97a4f8cc534c | 1610 | if(_nmetamethodscall) { |
jhnwkmn | 0:97a4f8cc534c | 1611 | Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod")); |
jhnwkmn | 0:97a4f8cc534c | 1612 | return false; |
jhnwkmn | 0:97a4f8cc534c | 1613 | } |
jhnwkmn | 0:97a4f8cc534c | 1614 | _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2)); |
jhnwkmn | 0:97a4f8cc534c | 1615 | RelocateOuters(); |
jhnwkmn | 0:97a4f8cc534c | 1616 | } |
jhnwkmn | 0:97a4f8cc534c | 1617 | return true; |
jhnwkmn | 0:97a4f8cc534c | 1618 | } |
jhnwkmn | 0:97a4f8cc534c | 1619 | |
jhnwkmn | 0:97a4f8cc534c | 1620 | void SQVM::LeaveFrame() { |
jhnwkmn | 0:97a4f8cc534c | 1621 | SQInteger last_top = _top; |
jhnwkmn | 0:97a4f8cc534c | 1622 | SQInteger last_stackbase = _stackbase; |
jhnwkmn | 0:97a4f8cc534c | 1623 | SQInteger css = --_callsstacksize; |
jhnwkmn | 0:97a4f8cc534c | 1624 | |
jhnwkmn | 0:97a4f8cc534c | 1625 | /* First clean out the call stack frame */ |
jhnwkmn | 0:97a4f8cc534c | 1626 | ci->_closure.Null(); |
jhnwkmn | 0:97a4f8cc534c | 1627 | _stackbase -= ci->_prevstkbase; |
jhnwkmn | 0:97a4f8cc534c | 1628 | _top = _stackbase + ci->_prevtop; |
jhnwkmn | 0:97a4f8cc534c | 1629 | ci = (css) ? &_callsstack[css-1] : NULL; |
jhnwkmn | 0:97a4f8cc534c | 1630 | |
jhnwkmn | 0:97a4f8cc534c | 1631 | if(_openouters) CloseOuters(&(_stack._vals[last_stackbase])); |
jhnwkmn | 0:97a4f8cc534c | 1632 | while (last_top >= _top) { |
jhnwkmn | 0:97a4f8cc534c | 1633 | _stack._vals[last_top--].Null(); |
jhnwkmn | 0:97a4f8cc534c | 1634 | } |
jhnwkmn | 0:97a4f8cc534c | 1635 | } |
jhnwkmn | 0:97a4f8cc534c | 1636 | |
jhnwkmn | 0:97a4f8cc534c | 1637 | void SQVM::RelocateOuters() |
jhnwkmn | 0:97a4f8cc534c | 1638 | { |
jhnwkmn | 0:97a4f8cc534c | 1639 | SQOuter *p = _openouters; |
jhnwkmn | 0:97a4f8cc534c | 1640 | while (p) { |
jhnwkmn | 0:97a4f8cc534c | 1641 | p->_valptr = _stack._vals + p->_idx; |
jhnwkmn | 0:97a4f8cc534c | 1642 | p = p->_next; |
jhnwkmn | 0:97a4f8cc534c | 1643 | } |
jhnwkmn | 0:97a4f8cc534c | 1644 | } |
jhnwkmn | 0:97a4f8cc534c | 1645 | |
jhnwkmn | 0:97a4f8cc534c | 1646 | void SQVM::CloseOuters(SQObjectPtr *stackindex) { |
jhnwkmn | 0:97a4f8cc534c | 1647 | SQOuter *p; |
jhnwkmn | 0:97a4f8cc534c | 1648 | while ((p = _openouters) != NULL && p->_valptr >= stackindex) { |
jhnwkmn | 0:97a4f8cc534c | 1649 | p->_value = *(p->_valptr); |
jhnwkmn | 0:97a4f8cc534c | 1650 | p->_valptr = &p->_value; |
jhnwkmn | 0:97a4f8cc534c | 1651 | _openouters = p->_next; |
jhnwkmn | 0:97a4f8cc534c | 1652 | __ObjRelease(p); |
jhnwkmn | 0:97a4f8cc534c | 1653 | } |
jhnwkmn | 0:97a4f8cc534c | 1654 | } |
jhnwkmn | 0:97a4f8cc534c | 1655 | |
jhnwkmn | 0:97a4f8cc534c | 1656 | void SQVM::Remove(SQInteger n) { |
jhnwkmn | 0:97a4f8cc534c | 1657 | n = (n >= 0)?n + _stackbase - 1:_top + n; |
jhnwkmn | 0:97a4f8cc534c | 1658 | for(SQInteger i = n; i < _top; i++){ |
jhnwkmn | 0:97a4f8cc534c | 1659 | _stack[i] = _stack[i+1]; |
jhnwkmn | 0:97a4f8cc534c | 1660 | } |
jhnwkmn | 0:97a4f8cc534c | 1661 | _stack[_top].Null(); |
jhnwkmn | 0:97a4f8cc534c | 1662 | _top--; |
jhnwkmn | 0:97a4f8cc534c | 1663 | } |
jhnwkmn | 0:97a4f8cc534c | 1664 | |
jhnwkmn | 0:97a4f8cc534c | 1665 | void SQVM::Pop() { |
jhnwkmn | 0:97a4f8cc534c | 1666 | _stack[--_top].Null(); |
jhnwkmn | 0:97a4f8cc534c | 1667 | } |
jhnwkmn | 0:97a4f8cc534c | 1668 | |
jhnwkmn | 0:97a4f8cc534c | 1669 | void SQVM::Pop(SQInteger n) { |
jhnwkmn | 0:97a4f8cc534c | 1670 | for(SQInteger i = 0; i < n; i++){ |
jhnwkmn | 0:97a4f8cc534c | 1671 | _stack[--_top].Null(); |
jhnwkmn | 0:97a4f8cc534c | 1672 | } |
jhnwkmn | 0:97a4f8cc534c | 1673 | } |
jhnwkmn | 0:97a4f8cc534c | 1674 | |
jhnwkmn | 0:97a4f8cc534c | 1675 | void SQVM::PushNull() { _stack[_top++].Null(); } |
jhnwkmn | 0:97a4f8cc534c | 1676 | void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; } |
jhnwkmn | 0:97a4f8cc534c | 1677 | SQObjectPtr &SQVM::Top() { return _stack[_top-1]; } |
jhnwkmn | 0:97a4f8cc534c | 1678 | SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; } |
jhnwkmn | 0:97a4f8cc534c | 1679 | SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; } |
jhnwkmn | 0:97a4f8cc534c | 1680 | SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; } |
jhnwkmn | 0:97a4f8cc534c | 1681 | |
jhnwkmn | 0:97a4f8cc534c | 1682 | #ifdef _DEBUG_DUMP |
jhnwkmn | 0:97a4f8cc534c | 1683 | void SQVM::dumpstack(SQInteger stackbase,bool dumpall) |
jhnwkmn | 0:97a4f8cc534c | 1684 | { |
jhnwkmn | 0:97a4f8cc534c | 1685 | SQInteger size=dumpall?_stack.size():_top; |
jhnwkmn | 0:97a4f8cc534c | 1686 | SQInteger n=0; |
jhnwkmn | 0:97a4f8cc534c | 1687 | scprintf(_SC("\n>>>>stack dump<<<<\n")); |
jhnwkmn | 0:97a4f8cc534c | 1688 | CallInfo &ci=_callsstack[_callsstacksize-1]; |
jhnwkmn | 0:97a4f8cc534c | 1689 | scprintf(_SC("IP: %p\n"),ci._ip); |
jhnwkmn | 0:97a4f8cc534c | 1690 | scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); |
jhnwkmn | 0:97a4f8cc534c | 1691 | scprintf(_SC("prev top: %d\n"),ci._prevtop); |
jhnwkmn | 0:97a4f8cc534c | 1692 | for(SQInteger i=0;i<size;i++){ |
jhnwkmn | 0:97a4f8cc534c | 1693 | SQObjectPtr &obj=_stack[i]; |
jhnwkmn | 0:97a4f8cc534c | 1694 | if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" ")); |
jhnwkmn | 0:97a4f8cc534c | 1695 | scprintf(_SC("[%d]:"),n); |
jhnwkmn | 0:97a4f8cc534c | 1696 | switch(type(obj)){ |
jhnwkmn | 0:97a4f8cc534c | 1697 | case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1698 | case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1699 | case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break; |
jhnwkmn | 0:97a4f8cc534c | 1700 | case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1701 | case OT_NULL: scprintf(_SC("NULL")); break; |
jhnwkmn | 0:97a4f8cc534c | 1702 | case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break; |
jhnwkmn | 0:97a4f8cc534c | 1703 | case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1704 | case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1705 | case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break; |
jhnwkmn | 0:97a4f8cc534c | 1706 | case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break; |
jhnwkmn | 0:97a4f8cc534c | 1707 | case OT_GENERATOR: scprintf(_SC("GENERATOR %p"),_generator(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1708 | case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1709 | case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1710 | case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1711 | case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1712 | case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break; |
jhnwkmn | 0:97a4f8cc534c | 1713 | default: |
jhnwkmn | 0:97a4f8cc534c | 1714 | assert(0); |
jhnwkmn | 0:97a4f8cc534c | 1715 | break; |
jhnwkmn | 0:97a4f8cc534c | 1716 | }; |
jhnwkmn | 0:97a4f8cc534c | 1717 | scprintf(_SC("\n")); |
jhnwkmn | 0:97a4f8cc534c | 1718 | ++n; |
jhnwkmn | 0:97a4f8cc534c | 1719 | } |
jhnwkmn | 0:97a4f8cc534c | 1720 | } |
jhnwkmn | 0:97a4f8cc534c | 1721 | |
jhnwkmn | 0:97a4f8cc534c | 1722 | |
jhnwkmn | 0:97a4f8cc534c | 1723 | |
jhnwkmn | 0:97a4f8cc534c | 1724 | #endif |