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