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