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 10
\r
10 #define SQ_SUSPEND_FLAG -666
\r
12 void sq_base_register(HSQUIRRELVM v);
\r
14 struct SQExceptionTrap{
\r
15 SQExceptionTrap() {}
\r
16 SQExceptionTrap(int ss, int stackbase,SQInstruction *ip, int ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
\r
17 SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }
\r
25 #define STK(a) _stack._vals[_stackbase+(a)]
\r
26 #define TARGET _stack._vals[_stackbase+arg0]
\r
28 typedef sqvector<SQExceptionTrap> ExceptionsTraps;
\r
30 struct SQVM : public CHAINABLE_OBJ
\r
33 VarArgs() { size = 0; base = 0; }
\r
40 //CallInfo(const CallInfo& ci) { }
\r
41 SQInstructionVec *_iv;
\r
42 SQObjectPtrVec *_literals;
\r
44 SQObject _generator;
\r
55 typedef sqvector<CallInfo> CallInfoVec;
\r
57 enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM };
\r
58 SQVM(SQSharedState *ss);
\r
60 bool Init(SQVM *friendvm, int stacksize);
\r
61 bool Execute(SQObjectPtr &func, int target, int nargs, int stackbase, SQObjectPtr &outres, ExecutionType et = ET_CALL);
\r
62 //start a native call return when the NATIVE closure returns(returns true if the vm has been suspended)
\r
63 bool CallNative(SQNativeClosure *nclosure, int nargs, int stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend);
\r
64 //start a SQUIRREL call in the same "Execution loop"
\r
65 bool StartCall(SQClosure *closure, int target, int nargs, int stackbase, bool tailcall);
\r
66 bool CreateClassInstance(SQClass *theclass, int nargs, int stackbase, SQObjectPtr &retval);
\r
67 //call a generic closure pure SQUIRREL or NATIVE
\r
68 bool Call(SQObjectPtr &closure, int nparams, int stackbase, SQObjectPtr &outres);
\r
71 void CallDebugHook(int type,int forcedline=0);
\r
72 void CallErrorHandler(SQObjectPtr &e);
\r
73 bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot);
\r
74 bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw);
\r
75 bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot);
\r
76 bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val);
\r
77 bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
\r
78 bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
\r
79 bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,int &res);
\r
80 bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
\r
81 bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);
\r
82 bool IsFalse(SQObjectPtr &o);
\r
83 SQString *PrintObjVal(const SQObject &o);
\r
86 void Raise_Error(const SQChar *s, ...);
\r
87 void Raise_Error(SQObjectPtr &desc);
\r
88 void Raise_IdxError(SQObject &o);
\r
89 void Raise_CompareError(const SQObject &o1, const SQObject &o2);
\r
90 void Raise_ParamTypeError(int nparam,int typemask,int type);
\r
92 void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
\r
93 bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, int nparams, SQObjectPtr &outres);
\r
94 bool ArithMetaMethod(int op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
\r
95 //void Modulo(const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
\r
96 bool Return(int _arg0, int _arg1, SQObjectPtr &retval);
\r
98 bool ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
\r
99 bool BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
\r
100 bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
\r
101 bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
\r
102 bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
\r
103 bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);
\r
104 bool CLASS_OP(SQObjectPtr &target,int base,int attrs);
\r
105 //return true if the loop is finished
\r
106 bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,int arg_2,bool &finished);
\r
107 bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);
\r
108 bool LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
\r
109 bool PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
\r
110 bool DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);
\r
111 void PopVarArgs(VarArgs &vargs);
\r
113 void dumpstack(int stackbase=-1, bool dumpall = false);
\r
116 #ifndef NO_GARBAGE_COLLECTOR
\r
117 void Mark(SQCollectable **chain);
\r
121 void Release(){ sq_delete(this,SQVM); } //does nothing
\r
122 ////////////////////////////////////////////////////////////////////////////
\r
123 //stack functions for the api
\r
126 void Remove(int n);
\r
128 void Push(const SQObjectPtr &o);
\r
129 SQObjectPtr &Top();
\r
130 SQObjectPtr &PopGet();
\r
131 SQObjectPtr &GetUp(int n);
\r
132 SQObjectPtr &GetAt(int n);
\r
134 SQObjectPtrVec _stack;
\r
135 SQObjectPtrVec _vargsstack;
\r
138 SQObjectPtr _roottable;
\r
139 //SQObjectPtr _thrownerror;
\r
140 SQObjectPtr _lasterror;
\r
141 SQObjectPtr _errorhandler;
\r
142 SQObjectPtr _debughook;
\r
144 SQObjectPtr temp_reg;
\r
145 CallInfoVec _callsstack;
\r
146 ExceptionsTraps _etraps;
\r
149 //VMs sharing the same state
\r
150 SQSharedState *_sharedstate;
\r
154 bool _suspended_root;
\r
155 int _suspended_target;
\r
156 int _suspended_traps;
\r
160 AutoDec(int *n) { _n = n; }
\r
161 ~AutoDec() { (*_n)--; }
\r
165 SQObjectPtr &stack_get(HSQUIRRELVM v, int idx);
\r
166 const SQChar *GetTypeName(const SQObjectPtr &obj1);
\r
167 const SQChar *IdType2Name(SQObjectType type);
\r
169 #define _ss(_vm_) (_vm_)->_sharedstate
\r
171 #ifndef NO_GARBAGE_COLLECTOR
\r
172 #define _opt_ss(_vm_) (_vm_)->_sharedstate
\r
174 #define _opt_ss(_vm_) NULL
\r
177 #define PUSH_CALLINFO(v,nci){ \
\r
178 v->_callsstack.push_back(nci); \
\r
179 v->ci = &v->_callsstack.back(); \
\r
182 #define POP_CALLINFO(v){ \
\r
183 v->_callsstack.pop_back(); \
\r
184 if(v->_callsstack.size()) \
\r
185 v->ci = &v->_callsstack.back() ; \
\r