1 /* see copyright notice in squirrel.h */
\r
5 #include "sqopcodes.h"
\r
6 #include "sqobject.h"
\r
7 #define MAX_NATIVE_CALLS 100
\r
8 #define MIN_STACK_OVERHEAD 15
\r
10 #define SQ_SUSPEND_FLAG -666
\r
11 #define DONT_FALL_BACK 666
\r
13 void sq_base_register(HSQUIRRELVM v);
\r
15 struct SQExceptionTrap{
\r
16 SQExceptionTrap() {}
\r
17 SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
\r
18 SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }
\r
19 SQInteger _stackbase;
\r
20 SQInteger _stacksize;
\r
22 SQInteger _extarget;
\r
27 #define STK(a) _stack._vals[_stackbase+(a)]
\r
28 #define TARGET _stack._vals[_stackbase+arg0]
\r
30 typedef sqvector<SQExceptionTrap> ExceptionsTraps;
\r
32 struct SQVM : public CHAINABLE_OBJ
\r
35 //CallInfo() { _generator = NULL;}
\r
37 SQObjectPtr *_literals;
\r
38 SQObjectPtr _closure;
\r
39 SQGenerator *_generator;
\r
41 SQInt32 _prevstkbase;
\r
48 typedef sqvector<CallInfo> CallInfoVec;
\r
50 void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
\r
51 static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
\r
52 enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM };
\r
53 SQVM(SQSharedState *ss);
\r
55 bool Init(SQVM *friendvm, SQInteger stacksize);
\r
56 bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
\r
57 //starts a native call return when the NATIVE closure returns
\r
58 bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval,bool &suspend);
\r
59 //starts a SQUIRREL call in the same "Execution loop"
\r
60 bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
\r
61 bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
\r
62 //call a generic closure pure SQUIRREL or NATIVE
\r
63 bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror);
\r
66 void CallDebugHook(SQInteger type,SQInteger forcedline=0);
\r
67 void CallErrorHandler(SQObjectPtr &e);
\r
68 bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, SQInteger selfidx);
\r
69 SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
\r
70 bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
\r
71 bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx);
\r
72 SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val);
\r
73 bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic);
\r
74 bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw);
\r
75 bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
\r
76 bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
\r
77 bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res);
\r
78 bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
\r
79 static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res);
\r
80 bool ToString(const SQObjectPtr &o,SQObjectPtr &res);
\r
81 SQString *PrintObjVal(const SQObjectPtr &o);
\r
84 void Raise_Error(const SQChar *s, ...);
\r
85 void Raise_Error(const SQObjectPtr &desc);
\r
86 void Raise_IdxError(const SQObjectPtr &o);
\r
87 void Raise_CompareError(const SQObject &o1, const SQObject &o2);
\r
88 void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);
\r
90 void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex);
\r
91 void RelocateOuters();
\r
92 void CloseOuters(SQObjectPtr *stackindex);
\r
94 bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
\r
95 bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);
\r
96 bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
\r
97 bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);
\r
99 _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
\r
100 _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
\r
101 _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
\r
102 _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
\r
103 bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
\r
104 bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
\r
105 //return true if the loop is finished
\r
106 bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);
\r
107 //_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
\r
108 _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
\r
109 _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0);
\r
111 void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
\r
114 #ifndef NO_GARBAGE_COLLECTOR
\r
115 void Mark(SQCollectable **chain);
\r
116 SQObjectType GetType() {return OT_THREAD;}
\r
119 void GrowCallStack() {
\r
120 SQInteger newsize = _alloccallsstacksize*2;
\r
121 _callstackdata.resize(newsize);
\r
122 _callsstack = &_callstackdata[0];
\r
123 _alloccallsstacksize = newsize;
\r
125 bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall);
\r
127 void Release(){ sq_delete(this,SQVM); }
\r
128 ////////////////////////////////////////////////////////////////////////////
\r
129 //stack functions for the api
\r
130 void Remove(SQInteger n);
\r
132 static bool IsFalse(SQObjectPtr &o);
\r
135 void Pop(SQInteger n);
\r
136 void Push(const SQObjectPtr &o);
\r
138 SQObjectPtr &Top();
\r
139 SQObjectPtr &PopGet();
\r
140 SQObjectPtr &GetUp(SQInteger n);
\r
141 SQObjectPtr &GetAt(SQInteger n);
\r
143 SQObjectPtrVec _stack;
\r
146 SQInteger _stackbase;
\r
147 SQOuter *_openouters;
\r
148 SQObjectPtr _roottable;
\r
149 SQObjectPtr _lasterror;
\r
150 SQObjectPtr _errorhandler;
\r
153 SQDEBUGHOOK _debughook_native;
\r
154 SQObjectPtr _debughook_closure;
\r
156 SQObjectPtr temp_reg;
\r
159 CallInfo* _callsstack;
\r
160 SQInteger _callsstacksize;
\r
161 SQInteger _alloccallsstacksize;
\r
162 sqvector<CallInfo> _callstackdata;
\r
164 ExceptionsTraps _etraps;
\r
167 //VMs sharing the same state
\r
168 SQSharedState *_sharedstate;
\r
169 SQInteger _nnativecalls;
\r
170 SQInteger _nmetamethodscall;
\r
173 SQBool _suspended_root;
\r
174 SQInteger _suspended_target;
\r
175 SQInteger _suspended_traps;
\r
179 AutoDec(SQInteger *n) { _n = n; }
\r
180 ~AutoDec() { (*_n)--; }
\r
184 inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
\r
186 #define _ss(_vm_) (_vm_)->_sharedstate
\r
188 #ifndef NO_GARBAGE_COLLECTOR
\r
189 #define _opt_ss(_vm_) (_vm_)->_sharedstate
\r
191 #define _opt_ss(_vm_) NULL
\r
194 #define PUSH_CALLINFO(v,nci){ \
\r
195 SQInteger css = v->_callsstacksize; \
\r
196 if(css == v->_alloccallsstacksize) { \
\r
197 v->GrowCallStack(); \
\r
199 v->ci = &v->_callsstack[css]; \
\r
201 v->_callsstacksize++; \
\r
204 #define POP_CALLINFO(v){ \
\r
205 SQInteger css = --v->_callsstacksize; \
\r
206 v->ci->_closure.Null(); \
\r
207 v->ci = css?&v->_callsstack[css-1]:NULL; \
\r