squirrel update
[supertux.git] / src / squirrel / squirrel / sqvm.h
1 /*      see copyright notice in squirrel.h */\r
2 #ifndef _SQVM_H_\r
3 #define _SQVM_H_\r
4 \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
9 \r
10 #define SQ_SUSPEND_FLAG -666\r
11 //base lib\r
12 void sq_base_register(HSQUIRRELVM v);\r
13 \r
14 struct SQExceptionTrap{\r
15         SQExceptionTrap() {}\r
16         SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}\r
17         SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et;      }\r
18         SQInteger _stackbase;\r
19         SQInteger _stacksize;\r
20         SQInstruction *_ip;\r
21         SQInteger _extarget;\r
22 };\r
23 \r
24 \r
25 #define STK(a) _stack._vals[_stackbase+(a)]\r
26 #define TARGET _stack._vals[_stackbase+arg0]\r
27 \r
28 typedef sqvector<SQExceptionTrap> ExceptionsTraps;\r
29 \r
30 struct SQVM : public CHAINABLE_OBJ\r
31 {\r
32         struct VarArgs {\r
33                 VarArgs() { size = 0; base = 0; }\r
34                 SQInteger size;\r
35                 SQInteger base;\r
36         };\r
37 \r
38         struct CallInfo{\r
39                 CallInfo() { _generator._type = OT_NULL;}\r
40                 //CallInfo(const CallInfo& ci) {  }\r
41                 SQInstructionVec *_iv;\r
42                 SQObjectPtrVec *_literals;\r
43                 SQObject _closure;\r
44                 SQObject _generator;\r
45                 SQInteger _etraps;\r
46                 SQInteger _prevstkbase;\r
47                 SQInteger _prevtop;\r
48                 SQInteger _target;\r
49                 SQInstruction *_ip;\r
50                 SQInteger _ncalls;\r
51                 SQBool _root;\r
52                 VarArgs _vargs;\r
53         };\r
54 \r
55 typedef sqvector<CallInfo> CallInfoVec;\r
56 public:\r
57         enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM };\r
58         SQVM(SQSharedState *ss);\r
59         ~SQVM();\r
60         bool Init(SQVM *friendvm, SQInteger stacksize);\r
61         bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger 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, SQInteger nargs, SQInteger stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend);\r
64         //start a SQUIRREL call in the same "Execution loop"\r
65         bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);\r
66         bool CreateClassInstance(SQClass *theclass, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval);\r
67         //call a generic closure pure SQUIRREL or NATIVE\r
68         bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres);\r
69         SQRESULT Suspend();\r
70 \r
71         void CallDebugHook(SQInteger type,SQInteger 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,SQInteger &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         void ToString(const SQObjectPtr &o,SQObjectPtr &res);\r
83         SQString *PrintObjVal(const SQObject &o);\r
84 \r
85  \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(SQInteger nparam,SQInteger typemask,SQInteger type);\r
91 \r
92         void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);\r
93         bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);\r
94         bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);\r
95         bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);\r
96         //new stuff\r
97         inline bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
98         inline bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
99         inline bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);\r
100         inline bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);\r
101         bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);\r
102         bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);\r
103         bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);\r
104         //return true if the loop is finished\r
105         bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished);\r
106         bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);\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);\r
110         void PopVarArgs(VarArgs &vargs);\r
111 #ifdef _DEBUG_DUMP\r
112         void dumpstack(SQInteger stackbase=-1, bool dumpall = false);\r
113 #endif\r
114 \r
115 #ifndef NO_GARBAGE_COLLECTOR\r
116         void Mark(SQCollectable **chain);\r
117 #endif\r
118         void Finalize();\r
119 \r
120         void Release(){ sq_delete(this,SQVM); } //does nothing\r
121 ////////////////////////////////////////////////////////////////////////////\r
122         //stack functions for the api\r
123         void Remove(SQInteger n);\r
124 \r
125         inline bool IsFalse(SQObjectPtr &o)\r
126         {\r
127                 if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) )\r
128                         || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL\r
129                         return true;\r
130                 }\r
131                 return false;\r
132         }\r
133         inline void Pop() {\r
134                 _stack[--_top] = _null_;\r
135         }\r
136 \r
137         inline void Pop(SQInteger n) {\r
138                 for(SQInteger i = 0; i < n; i++){\r
139                         _stack[--_top] = _null_;\r
140                 }\r
141         }\r
142 \r
143         inline void Push(const SQObjectPtr &o) { _stack[_top++] = o; }\r
144         inline SQObjectPtr &Top() { return _stack[_top-1]; }\r
145         inline SQObjectPtr &PopGet() { return _stack[--_top]; }\r
146         inline SQObjectPtr &GetUp(SQInteger n) { return _stack[_top+n]; }\r
147         inline SQObjectPtr &GetAt(SQInteger n) { return _stack[n]; }\r
148 \r
149         SQObjectPtrVec _stack;\r
150         SQObjectPtrVec _vargsstack;\r
151         SQInteger _top;\r
152         SQInteger _stackbase;\r
153         SQObjectPtr _roottable;\r
154         //SQObjectPtr _thrownerror;\r
155         SQObjectPtr _lasterror;\r
156         SQObjectPtr _errorhandler;\r
157         SQObjectPtr _debughook;\r
158 \r
159         SQObjectPtr temp_reg;\r
160         CallInfoVec _callsstack;\r
161         ExceptionsTraps _etraps;\r
162         CallInfo *ci;\r
163         void *_foreignptr;\r
164         //VMs sharing the same state\r
165         SQSharedState *_sharedstate;\r
166         SQInteger _nnativecalls;\r
167         //suspend infos\r
168         SQBool _suspended;\r
169         SQBool _suspended_root;\r
170         SQInteger _suspended_target;\r
171         SQInteger _suspended_traps;\r
172 };\r
173 \r
174 struct AutoDec{\r
175         AutoDec(SQInteger *n) { _n = n; }\r
176         ~AutoDec() { (*_n)--; }\r
177         SQInteger *_n;\r
178 };\r
179 \r
180 inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}\r
181 const SQChar *GetTypeName(const SQObjectPtr &obj1);\r
182 const SQChar *IdType2Name(SQObjectType type);\r
183 \r
184 #define _ss(_vm_) (_vm_)->_sharedstate\r
185 \r
186 #ifndef NO_GARBAGE_COLLECTOR\r
187 #define _opt_ss(_vm_) (_vm_)->_sharedstate\r
188 #else\r
189 #define _opt_ss(_vm_) NULL\r
190 #endif\r
191 \r
192 #define PUSH_CALLINFO(v,nci){ \\r
193         v->ci = &v->_callsstack.push_back(nci); \\r
194 }\r
195 \r
196 #define POP_CALLINFO(v){ \\r
197         v->_callsstack.pop_back(); \\r
198         if(v->_callsstack.size())       \\r
199                 v->ci = &v->_callsstack.back() ; \\r
200         else    \\r
201                 v->ci = NULL; \\r
202 }\r
203 #endif //_SQVM_H_\r