- More work on scripting interface
[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(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
18         int _stackbase;\r
19         int _stacksize;\r
20         SQInstruction *_ip;\r
21         int _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                 int size;\r
35                 int base;\r
36         };\r
37 \r
38         struct CallInfo{\r
39                 //CallInfo() {}\r
40                 //CallInfo(const CallInfo& ci) {  }\r
41                 SQInstructionVec *_iv;\r
42                 SQObjectPtrVec *_literals;\r
43                 SQObject _closure;\r
44                 SQObject _generator;\r
45                 int _etraps;\r
46                 int _prevstkbase;\r
47                 int _prevtop;\r
48                 int _target;\r
49                 SQInstruction *_ip;\r
50                 int _ncalls;\r
51                 bool _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, 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
69         SQRESULT Suspend();\r
70 \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
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(int nparam,int typemask,int type);\r
91 \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
97         //new stuff\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
112 #ifdef _DEBUG_DUMP\r
113         void dumpstack(int stackbase=-1, bool dumpall = false);\r
114 #endif\r
115 \r
116 #ifndef NO_GARBAGE_COLLECTOR\r
117         void Mark(SQCollectable **chain);\r
118 #endif\r
119         void Finalize();\r
120 \r
121         void Release(){ sq_delete(this,SQVM); } //does nothing\r
122 ////////////////////////////////////////////////////////////////////////////\r
123         //stack functions for the api\r
124         void Pop();\r
125         void Pop(int n);\r
126         void Remove(int n);\r
127 \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
133 \r
134         SQObjectPtrVec _stack;\r
135         SQObjectPtrVec _vargsstack;\r
136         int _top;\r
137         int _stackbase;\r
138         SQObjectPtr _roottable;\r
139         //SQObjectPtr _thrownerror;\r
140         SQObjectPtr _lasterror;\r
141         SQObjectPtr _errorhandler;\r
142         SQObjectPtr _debughook;\r
143 \r
144         SQObjectPtr temp_reg;\r
145         CallInfoVec _callsstack;\r
146         ExceptionsTraps _etraps;\r
147         CallInfo *ci;\r
148         void *_foreignptr;\r
149         //VMs sharing the same state\r
150         SQSharedState *_sharedstate;\r
151         int _nnativecalls;\r
152         //suspend infos\r
153         bool _suspended;\r
154         bool _suspended_root;\r
155         int _suspended_target;\r
156         int _suspended_traps;\r
157 };\r
158 \r
159 struct AutoDec{\r
160         AutoDec(int *n) { _n = n; }\r
161         ~AutoDec() { (*_n)--; }\r
162         int *_n;\r
163 };\r
164 \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
168 \r
169 #define _ss(_vm_) (_vm_)->_sharedstate\r
170 \r
171 #ifndef NO_GARBAGE_COLLECTOR\r
172 #define _opt_ss(_vm_) (_vm_)->_sharedstate\r
173 #else\r
174 #define _opt_ss(_vm_) NULL\r
175 #endif\r
176 \r
177 #define PUSH_CALLINFO(v,nci){ \\r
178         v->_callsstack.push_back(nci); \\r
179         v->ci = &v->_callsstack.back(); \\r
180 }\r
181 \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
186         else    \\r
187                 v->ci = NULL; \\r
188 }\r
189 #endif //_SQVM_H_\r