From f2a227936c9bc89ec5bd53f362c9fc2dd74eacf5 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Sun, 24 Apr 2016 18:45:56 +0200 Subject: [PATCH 01/16] [NOT COMPILE] Update Squirrel Update squirrel from 2.2.5 to 3.0.4 stable does not update project files will not compile --- src/include/scripting/include/sqrdbg.h | 51 - src/include/scripting/squirrel/sqarray.h | 11 +- src/include/scripting/squirrel/sqclass.h | 20 +- src/include/scripting/squirrel/sqclosure.h | 131 +- src/include/scripting/squirrel/sqcompiler.h | 8 +- .../{include => squirrel}/sqdbgserver.h | 99 +- src/include/scripting/squirrel/sqfuncproto.h | 38 +- src/include/scripting/squirrel/sqfuncstate.h | 8 +- src/include/scripting/squirrel/sqlexer.h | 2 + src/include/scripting/squirrel/sqobject.h | 277 ++- src/include/scripting/squirrel/sqopcodes.h | 73 +- src/include/scripting/squirrel/sqrdbg.h | 24 + src/include/scripting/squirrel/sqstate.h | 37 +- .../{include => squirrel}/sqstdaux.h | 0 .../{include => squirrel}/sqstdblob.h | 0 .../scripting/{include => squirrel}/sqstdio.h | 2 - .../{include => squirrel}/sqstdmath.h | 0 .../{include => squirrel}/sqstdstring.h | 0 .../{include => squirrel}/sqstdsystem.h | 0 src/include/scripting/squirrel/sqtable.h | 1 + .../{include => squirrel}/squirrel.h | 175 +- src/include/scripting/squirrel/squserdata.h | 12 +- src/include/scripting/squirrel/squtils.h | 15 +- src/include/scripting/squirrel/sqvm.h | 101 +- src/sdk/scripting/sqstdlib/Makefile.am | 2 +- src/sdk/scripting/squirrel/Makefile.am | 3 +- .../scripting/squirrel/serialize_state.inl | 410 +++++ .../scripting/squirrel/serialize_state.nut | 262 +++ src/sdk/scripting/squirrel/sqapi.cpp | 421 ++++- src/sdk/scripting/squirrel/sqbaselib.cpp | 350 +++- src/sdk/scripting/squirrel/sqclass.cpp | 54 +- src/sdk/scripting/squirrel/sqcompiler.cpp | 951 ++++++----- src/sdk/scripting/squirrel/sqdbgserver.cpp | 687 ++++++++ src/sdk/scripting/squirrel/sqdebug.cpp | 24 +- src/sdk/scripting/squirrel/sqfuncstate.cpp | 199 ++- src/sdk/scripting/squirrel/sqlexer.cpp | 66 +- src/sdk/scripting/squirrel/sqmem.cpp | 6 +- src/sdk/scripting/squirrel/sqobject.cpp | 191 ++- src/sdk/scripting/squirrel/sqrdbg.cpp | 183 ++ src/sdk/scripting/squirrel/sqstate.cpp | 196 ++- src/sdk/scripting/squirrel/sqtable.cpp | 37 +- src/sdk/scripting/squirrel/sqvm.cpp | 1500 ++++++++++------- 42 files changed, 4699 insertions(+), 1928 deletions(-) delete mode 100644 src/include/scripting/include/sqrdbg.h rename src/include/scripting/{include => squirrel}/sqdbgserver.h (59%) create mode 100644 src/include/scripting/squirrel/sqrdbg.h rename src/include/scripting/{include => squirrel}/sqstdaux.h (100%) rename src/include/scripting/{include => squirrel}/sqstdblob.h (100%) rename src/include/scripting/{include => squirrel}/sqstdio.h (95%) rename src/include/scripting/{include => squirrel}/sqstdmath.h (100%) rename src/include/scripting/{include => squirrel}/sqstdstring.h (100%) rename src/include/scripting/{include => squirrel}/sqstdsystem.h (100%) rename src/include/scripting/{include => squirrel}/squirrel.h (75%) create mode 100644 src/sdk/scripting/squirrel/serialize_state.inl create mode 100644 src/sdk/scripting/squirrel/serialize_state.nut create mode 100644 src/sdk/scripting/squirrel/sqdbgserver.cpp create mode 100644 src/sdk/scripting/squirrel/sqrdbg.cpp diff --git a/src/include/scripting/include/sqrdbg.h b/src/include/scripting/include/sqrdbg.h deleted file mode 100644 index 893552f0ec..0000000000 --- a/src/include/scripting/include/sqrdbg.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright (c) 2003-2005 Alberto Demichelis - -This software is provided 'as-is', without any -express or implied warranty. In no event will the -authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software -for any purpose, including commercial applications, -and to alter it and redistribute it freely, subject -to the following restrictions: - - 1. The origin of this software must not be - misrepresented; you must not claim that - you wrote the original software. If you - use this software in a product, an - acknowledgment in the product - documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly - marked as such, and must not be - misrepresented as being the original - software. - - 3. This notice may not be removed or - altered from any source distribution. - -*/ -#ifndef _SQ_RDBG_H_ -#define _SQ_RDBG_H_ - -#ifdef __cplusplus -extern "C" { -#endif -#pragma comment(lib, "WSOCK32.LIB") - -struct SQDbgServer; -typedef SQDbgServer* HSQREMOTEDBG; - -HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate); -SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg); -SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg); -SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif //_SQ_RDBG_H_ diff --git a/src/include/scripting/squirrel/sqarray.h b/src/include/scripting/squirrel/sqarray.h index 5c26352079..e9b7466573 100644 --- a/src/include/scripting/squirrel/sqarray.h +++ b/src/include/scripting/squirrel/sqarray.h @@ -18,6 +18,7 @@ struct SQArray : public CHAINABLE_OBJ } #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); + SQObjectType GetType() {return OT_ARRAY;} #endif void Finalize(){ _values.resize(0); @@ -53,9 +54,14 @@ struct SQArray : public CHAINABLE_OBJ //nothing to iterate anymore return -1; } - SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; } + SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),0); anew->_values.copy(_values); return anew; } SQInteger Size() const {return _values.size();} - void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); } + void Resize(SQInteger size) + { + SQObjectPtr _null; + Resize(size,_null); + } + void Resize(SQInteger size,SQObjectPtr &fill) { _values.resize(size,fill); ShrinkIfNeeded(); } void Reserve(SQInteger size) { _values.reserve(size); } void Append(const SQObject &o){_values.push_back(o);} void Extend(const SQArray *a); @@ -82,6 +88,7 @@ struct SQArray : public CHAINABLE_OBJ { sq_delete(this,SQArray); } + SQObjectPtrVec _values; }; #endif //_SQARRAY_H_ diff --git a/src/include/scripting/squirrel/sqclass.h b/src/include/scripting/squirrel/sqclass.h index 4faff8395e..5c1fe2d205 100644 --- a/src/include/scripting/squirrel/sqclass.h +++ b/src/include/scripting/squirrel/sqclass.h @@ -5,11 +5,6 @@ struct SQInstance; struct SQClassMember { - SQClassMember(){} - SQClassMember(const SQClassMember &o) { - val = o.val; - attrs = o.attrs; - } SQObjectPtr val; SQObjectPtr attrs; }; @@ -50,6 +45,14 @@ struct SQClass : public CHAINABLE_OBJ } return false; } + bool GetConstructor(SQObjectPtr &ctor) + { + if(_constructoridx != -1) { + ctor = _methods[_constructoridx].val; + return true; + } + return false; + } bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val); bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval); void Lock() { _locked = true; if(_base) _base->Lock(); } @@ -60,6 +63,7 @@ struct SQClass : public CHAINABLE_OBJ void Finalize(); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable ** ); + SQObjectType GetType() {return OT_CLASS;} #endif SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); SQInstance *CreateInstance(); @@ -67,16 +71,17 @@ struct SQClass : public CHAINABLE_OBJ SQClass *_base; SQClassMemberVec _defaultvalues; SQClassMemberVec _methods; - SQObjectPtrVec _metamethods; + SQObjectPtr _metamethods[MT_LAST]; SQObjectPtr _attributes; SQUserPointer _typetag; SQRELEASEHOOK _hook; bool _locked; + SQInteger _constructoridx; SQInteger _udsize; }; #define calcinstancesize(_theclass_) \ - (_theclass_->_udsize + sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))) + (_theclass_->_udsize + sq_aligning(sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))) struct SQInstance : public SQDelegable { @@ -138,6 +143,7 @@ struct SQInstance : public SQDelegable void Finalize(); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable ** ); + SQObjectType GetType() {return OT_INSTANCE;} #endif bool InstanceOf(SQClass *trg); bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); diff --git a/src/include/scripting/squirrel/sqclosure.h b/src/include/scripting/squirrel/sqclosure.h index de70ee02ef..353eb50415 100644 --- a/src/include/scripting/squirrel/sqclosure.h +++ b/src/include/scripting/squirrel/sqclosure.h @@ -2,44 +2,100 @@ #ifndef _SQCLOSURE_H_ #define _SQCLOSURE_H_ -struct SQFunctionProto; +#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(SQObjectPtr)) + (func->_ndefaultparams*sizeof(SQObjectPtr))) + +struct SQFunctionProto; +struct SQClass; struct SQClosure : public CHAINABLE_OBJ { private: - SQClosure(SQSharedState *ss,SQFunctionProto *func){_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} + SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;} public: static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){ - SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure)); + SQInteger size = _CALC_CLOSURE_SIZE(func); + SQClosure *nc=(SQClosure*)SQ_MALLOC(size); new (nc) SQClosure(ss,func); + nc->_outervalues = (SQObjectPtr *)(nc + 1); + nc->_defaultparams = &nc->_outervalues[func->_noutervalues]; + _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues); + _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams); return nc; } void Release(){ - sq_delete(this,SQClosure); + SQFunctionProto *f = _function; + SQInteger size = _CALC_CLOSURE_SIZE(f); + _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues); + _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams); + __ObjRelease(_function); + this->~SQClosure(); + sq_vm_free(this,size); } + SQClosure *Clone() { - SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function)); + SQFunctionProto *f = _function; + SQClosure * ret = SQClosure::Create(_opt_ss(this),f); ret->_env = _env; - ret->_outervalues.copy(_outervalues); - ret->_defaultparams.copy(_defaultparams); + if(ret->_env) __ObjAddRef(ret->_env); + _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues); + _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams); return ret; } - ~SQClosure() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } + ~SQClosure(); + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); - void Finalize(){_outervalues.resize(0); } + void Finalize(){ + SQFunctionProto *f = _function; + _NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues); + _NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams); + } + SQObjectType GetType() {return OT_CLOSURE;} #endif - SQObjectPtr _env; - SQObjectPtr _function; - SQObjectPtrVec _outervalues; - SQObjectPtrVec _defaultparams; + SQWeakRef *_env; + SQClass *_base; + SQFunctionProto *_function; + SQObjectPtr *_outervalues; + SQObjectPtr *_defaultparams; }; + +////////////////////////////////////////////// +struct SQOuter : public CHAINABLE_OBJ +{ + +private: + SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } + +public: + static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer) + { + SQOuter *nc = (SQOuter*)SQ_MALLOC(sizeof(SQOuter)); + new (nc) SQOuter(ss, outer); + return nc; + } + ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } + + void Release() + { + this->~SQOuter(); + sq_vm_free(this,sizeof(SQOuter)); + } + +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize() { _value.Null(); } + SQObjectType GetType() {return OT_OUTER;} +#endif + + SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */ + SQInteger _idx; /* idx in stack array, for relocation */ + SQObjectPtr _value; /* value of outer after stack frame is closed */ + SQOuter *_next; /* pointer to next outer when frame is open */ +}; + ////////////////////////////////////////////// struct SQGenerator : public CHAINABLE_OBJ { @@ -59,60 +115,75 @@ struct SQGenerator : public CHAINABLE_OBJ void Kill(){ _state=eDead; _stack.resize(0); - _closure=_null_;} + _closure.Null();} void Release(){ sq_delete(this,SQGenerator); } - bool Yield(SQVM *v); - bool Resume(SQVM *v,SQInteger target); + + bool Yield(SQVM *v,SQInteger target); + bool Resume(SQVM *v,SQObjectPtr &dest); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); - void Finalize(){_stack.resize(0);_closure=_null_;} + void Finalize(){_stack.resize(0);_closure.Null();} + SQObjectType GetType() {return OT_GENERATOR;} #endif SQObjectPtr _closure; SQObjectPtrVec _stack; - SQObjectPtrVec _vargsstack; SQVM::CallInfo _ci; ExceptionsTraps _etraps; SQGeneratorState _state; }; +#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr))) + struct SQNativeClosure : public CHAINABLE_OBJ { private: - SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } + SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;} public: - static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func) + static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters) { - SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure)); + SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters); + SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size); new (nc) SQNativeClosure(ss,func); + nc->_outervalues = (SQObjectPtr *)(nc + 1); + nc->_noutervalues = nouters; + _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues); return nc; } SQNativeClosure *Clone() { - SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function); + SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function,_noutervalues); ret->_env = _env; + if(ret->_env) __ObjAddRef(ret->_env); ret->_name = _name; - ret->_outervalues.copy(_outervalues); + _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues); ret->_typecheck.copy(_typecheck); ret->_nparamscheck = _nparamscheck; return ret; } ~SQNativeClosure() { + __ObjRelease(_env); REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } void Release(){ - sq_delete(this,SQNativeClosure); + SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues); + _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues); + this->~SQNativeClosure(); + sq_free(this,size); } + #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); - void Finalize(){_outervalues.resize(0);} + void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); } + SQObjectType GetType() {return OT_NATIVECLOSURE;} #endif SQInteger _nparamscheck; SQIntVec _typecheck; - SQObjectPtrVec _outervalues; - SQObjectPtr _env; + SQObjectPtr *_outervalues; + SQUnsignedInteger _noutervalues; + SQWeakRef *_env; SQFUNCTION _function; SQObjectPtr _name; }; diff --git a/src/include/scripting/squirrel/sqcompiler.h b/src/include/scripting/squirrel/sqcompiler.h index dd55888b6e..de5983b462 100644 --- a/src/include/scripting/squirrel/sqcompiler.h +++ b/src/include/scripting/squirrel/sqcompiler.h @@ -8,7 +8,7 @@ struct SQVM; #define TK_STRING_LITERAL 259 #define TK_INTEGER 260 #define TK_FLOAT 261 -#define TK_DELEGATE 262 +#define TK_BASE 262 #define TK_DELETE 263 #define TK_EQ 264 #define TK_NE 265 @@ -51,15 +51,15 @@ struct SQVM; #define TK_THIS 302 #define TK_PLUSPLUS 303 #define TK_MINUSMINUS 304 -#define TK_PARENT 305 +#define TK_3WAYSCMP 305 #define TK_USHIFTR 306 #define TK_CLASS 307 #define TK_EXTENDS 308 #define TK_CONSTRUCTOR 310 #define TK_INSTANCEOF 311 #define TK_VARPARAMS 312 -#define TK_VARGC 313 -#define TK_VARGV 314 +//#define TK_VARGC 313 +//#define TK_VARGV 314 #define TK_TRUE 315 #define TK_FALSE 316 #define TK_MULEQ 317 diff --git a/src/include/scripting/include/sqdbgserver.h b/src/include/scripting/squirrel/sqdbgserver.h similarity index 59% rename from src/include/scripting/include/sqdbgserver.h rename to src/include/scripting/squirrel/sqdbgserver.h index eac753525f..d4a6552f52 100644 --- a/src/include/scripting/include/sqdbgserver.h +++ b/src/include/scripting/squirrel/sqdbgserver.h @@ -5,57 +5,78 @@ #define MAX_MSG_LEN 2049 #include +#include #include #include -/* - see copyright notice in sqrdbg.h -*/ -#include -typedef std::basic_string SQDBGString; +#ifdef _WIN32 + #include + #include + #include +#else + #include + #include + #include + #include + #include + #include + + #include + + #define SOCKET int + #define SOCKET_ERROR -1 + #define INVALID_SOCKET -1 + + #include + #define Sleep(x) usleep((x)*1000) +#endif + + -inline bool dbg_less(const SQChar *x,const SQChar *y) -{ - int n = 0; - do { - int xl = *x == '\\' ? '/' : tolower(*x); - int yl = *y == '\\' ? '/' : tolower(*y); - int diff = xl - yl; - if(diff != 0) - return diff > 0?true:false; - x++; y++; - }while(*x != 0 && *y != 0); - return false; -} +typedef std::basic_string SQDBGString; struct BreakPoint{ BreakPoint(){_line=0;} - BreakPoint(int line, const SQChar *src){ _line = line; _src = src; } + BreakPoint(SQInteger line, const SQChar *src){ _line = line; _src = src; } BreakPoint(const BreakPoint& bp){ _line = bp._line; _src=bp._src; } - inline bool operator<(const BreakPoint& bp) const + bool operator<(const BreakPoint& bp) const { if(_line VMStateMap; typedef std::set BreakPointSet; typedef BreakPointSet::iterator BreakPointSetItor; @@ -81,28 +102,30 @@ struct SQDbgServer{ bool WaitForClient(); bool ReadMsg(); void BusyWait(); - void Hook(int type,int line,const SQChar *src,const SQChar *func); + void Hook(HSQUIRRELVM v,SQInteger type,SQInteger line,const SQChar *src,const SQChar *func); void ParseMsg(const char *msg); bool ParseBreakpoint(const char *msg,BreakPoint &out); bool ParseWatch(const char *msg,Watch &out); - bool ParseRemoveWatch(const char *msg,int &id); + bool ParseRemoveWatch(const char *msg,SQInteger &id); void Terminated(); // void BreakExecution(); void Send(const SQChar *s,...); void SendChunk(const SQChar *chunk); - void Break(int line,const SQChar *src,const SQChar *type,const SQChar *error=NULL); + void Break(HSQUIRRELVM v,SQInteger line,const SQChar *src,const SQChar *type,const SQChar *error=NULL); + void InformNewFileLoaded(HSQUIRRELVM v,const SQChar *src); - void SerializeState(); + void SerializeState(HSQUIRRELVM v); //COMMANDS void AddBreakpoint(BreakPoint &bp); void AddWatch(Watch &w); - void RemoveWatch(int id); + void RemoveWatch(SQInteger id); void RemoveBreakpoint(BreakPoint &bp); // - void SetErrorHandlers(); + void SetErrorHandlers(HSQUIRRELVM v); + VMState *GetVMState(HSQUIRRELVM v); //XML RELATED STUFF/////////////////////// #define MAX_NESTING 10 @@ -112,9 +135,9 @@ struct SQDbgServer{ }; XMLElementState xmlstate[MAX_NESTING]; - int _xmlcurrentement; + SQInteger _xmlcurrentement; - void BeginDocument() { _xmlcurrentement = -1; } + void BeginDocument(); void BeginElement(const SQChar *name); void Attribute(const SQChar *name, const SQChar *value); void EndElement(const SQChar *name); @@ -129,14 +152,18 @@ struct SQDbgServer{ SOCKET _endpoint; BreakPointSet _breakpoints; WatchSet _watches; - int _recursionlevel; - int _maxrecursion; - int _nestedcalls; + //int _recursionlevel; + //int _maxrecursion; + bool _ready; bool _autoupdate; HSQOBJECT _serializefunc; SQCharVec _scratchstring; + SQInteger _line; + SQDBGString _src; + SQDBGString _break_type; + VMStateMap _vmstate; }; #ifdef _WIN32 diff --git a/src/include/scripting/squirrel/sqfuncproto.h b/src/include/scripting/squirrel/sqfuncproto.h index 6092dbe302..e6e9529ec9 100644 --- a/src/include/scripting/squirrel/sqfuncproto.h +++ b/src/include/scripting/squirrel/sqfuncproto.h @@ -6,8 +6,7 @@ enum SQOuterType { otLOCAL = 0, - otSYMBOL = 1, - otOUTER = 2 + otOUTER = 1 }; struct SQOuterVar @@ -33,7 +32,7 @@ struct SQOuterVar struct SQLocalVarInfo { - SQLocalVarInfo():_start_op(0),_end_op(0){} + SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){} SQLocalVarInfo(const SQLocalVarInfo &lvi) { _name=lvi._name; @@ -59,25 +58,15 @@ typedef sqvector SQLineInfoVec; +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \ +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger))) -#define _CONSTRUCT_VECTOR(type,size,ptr) { \ - for(SQInteger n = 0; n < size; n++) { \ - new (&ptr[n]) type(); \ - } \ -} - -#define _DESTRUCT_VECTOR(type,size,ptr) { \ - for(SQInteger nl = 0; nl < size; nl++) { \ - ptr[nl].~type(); \ - } \ -} -struct SQFunctionProto : public SQRefCounted + +struct SQFunctionProto : public CHAINABLE_OBJ { private: - SQFunctionProto(){ - _stacksize=0; - _bgenerator=false;} + SQFunctionProto(SQSharedState *ss); + ~SQFunctionProto(); + public: - static SQFunctionProto *Create(SQInteger ninstructions, + static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions, SQInteger nliterals,SQInteger nparameters, SQInteger nfunctions,SQInteger noutervalues, SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams) @@ -85,7 +74,7 @@ struct SQFunctionProto : public SQRefCounted SQFunctionProto *f; //I compact the whole class and members in a single memory allocation f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams)); - new (f) SQFunctionProto; + new (f) SQFunctionProto(ss); f->_ninstructions = ninstructions; f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions]; f->_nliterals = nliterals; @@ -121,16 +110,21 @@ struct SQFunctionProto : public SQRefCounted this->~SQFunctionProto(); sq_vm_free(this,size); } + const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop); SQInteger GetLine(SQInstruction *curr); bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); - +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); } + SQObjectType GetType() {return OT_FUNCPROTO;} +#endif SQObjectPtr _sourcename; SQObjectPtr _name; SQInteger _stacksize; bool _bgenerator; - bool _varparams; + SQInteger _varparams; SQInteger _nlocalvarinfos; SQLocalVarInfo *_localvarinfos; diff --git a/src/include/scripting/squirrel/sqfuncstate.h b/src/include/scripting/squirrel/sqfuncstate.h index c0bf1e5e9e..2ae2200879 100644 --- a/src/include/scripting/squirrel/sqfuncstate.h +++ b/src/include/scripting/squirrel/sqfuncstate.h @@ -21,6 +21,7 @@ struct SQFuncState SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];} void PopInstructions(SQInteger size){for(SQInteger i=0;i _childstates; @@ -78,6 +83,7 @@ struct SQFuncState private: CompilerErrorFunc _errfunc; void *_errtarget; + SQSharedState *_ss; }; diff --git a/src/include/scripting/squirrel/sqlexer.h b/src/include/scripting/squirrel/sqlexer.h index eb3bc87378..49fadd90a3 100644 --- a/src/include/scripting/squirrel/sqlexer.h +++ b/src/include/scripting/squirrel/sqlexer.h @@ -21,10 +21,12 @@ struct SQLexer SQInteger ReadString(SQInteger ndelim,bool verbatim); SQInteger ReadNumber(); void LexBlockComment(); + void LexLineComment(); SQInteger ReadID(); void Next(); SQInteger _curtoken; SQTable *_keywords; + SQBool _reached_eof; public: SQInteger _prevtoken; SQInteger _currentline; diff --git a/src/include/scripting/squirrel/sqobject.h b/src/include/scripting/squirrel/sqobject.h index ac367ae02c..ee53ac5038 100644 --- a/src/include/scripting/squirrel/sqobject.h +++ b/src/include/scripting/squirrel/sqobject.h @@ -4,6 +4,12 @@ #include "squtils.h" +#ifdef _SQ64 +#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF) +#else +#define UINT_MINUS_ONE (0xFFFFFFFF) +#endif + #define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R')) #define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T')) #define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L')) @@ -51,16 +57,42 @@ enum SQMetaMethod{ #define MM_NEWMEMBER _SC("_newmember") #define MM_INHERITED _SC("_inherited") + +#define _CONSTRUCT_VECTOR(type,size,ptr) { \ + for(SQInteger n = 0; n < ((SQInteger)size); n++) { \ + new (&ptr[n]) type(); \ + } \ +} + +#define _DESTRUCT_VECTOR(type,size,ptr) { \ + for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \ + ptr[nl].~type(); \ + } \ +} + +#define _COPY_VECTOR(dest,src,size) { \ + for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ + dest[_n_] = src[_n_]; \ + } \ +} + +#define _NULL_SQOBJECT_VECTOR(vec,size) { \ + for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ + vec[_n_].Null(); \ + } \ +} + #define MINPOWER2 4 struct SQRefCounted { + SQUnsignedInteger _uiRef; + struct SQWeakRef *_weakref; SQRefCounted() { _uiRef = 0; _weakref = NULL; } virtual ~SQRefCounted(); SQWeakRef *GetWeakRef(SQObjectType type); - SQUnsignedInteger _uiRef; - struct SQWeakRef *_weakref; virtual void Release()=0; + }; struct SQWeakRef : SQRefCounted @@ -76,9 +108,9 @@ struct SQObjectPtr; #define __AddRef(type,unval) if(ISREFCOUNTED(type)) \ { \ unval.pRefCounted->_uiRef++; \ - } + } -#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \ +#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0)) \ { \ unval.pRefCounted->Release(); \ } @@ -116,17 +148,61 @@ struct SQObjectPtr; #define _instance(obj) ((obj)._unVal.pInstance) #define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable) #define _weakref(obj) ((obj)._unVal.pWeakRef) +#define _outer(obj) ((obj)._unVal.pOuter) #define _refcounted(obj) ((obj)._unVal.pRefCounted) #define _rawval(obj) ((obj)._unVal.raw) #define _stringval(obj) (obj)._unVal.pString->_val -#define _userdataval(obj) (obj)._unVal.pUserData->_val +#define _userdataval(obj) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1)) #define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num)) -#define tointeger(num) ( (type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num)) - +#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num)) ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// +#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64) +#define SQ_REFOBJECT_INIT() SQ_OBJECT_RAWINIT() +#else +#define SQ_REFOBJECT_INIT() +#endif + +#define _REF_TYPE_DECL(type,_class,sym) \ + SQObjectPtr(_class * x) \ + { \ + SQ_OBJECT_RAWINIT() \ + _type=type; \ + _unVal.sym = x; \ + assert(_unVal.pTable); \ + _unVal.pRefCounted->_uiRef++; \ + } \ + inline SQObjectPtr& operator=(_class *x) \ + { \ + SQObjectType tOldType; \ + SQObjectValue unOldVal; \ + tOldType=_type; \ + unOldVal=_unVal; \ + _type = type; \ + SQ_REFOBJECT_INIT() \ + _unVal.sym = x; \ + _unVal.pRefCounted->_uiRef++; \ + __Release(tOldType,unOldVal); \ + return *this; \ + } + +#define _SCALAR_TYPE_DECL(type,_class,sym) \ + SQObjectPtr(_class x) \ + { \ + SQ_OBJECT_RAWINIT() \ + _type=type; \ + _unVal.sym = x; \ + } \ + inline SQObjectPtr& operator=(_class x) \ + { \ + __Release(_type,_unVal); \ + _type = type; \ + SQ_OBJECT_RAWINIT() \ + _unVal.sym = x; \ + return *this; \ + } struct SQObjectPtr : public SQObject { SQObjectPtr() @@ -137,170 +213,56 @@ struct SQObjectPtr : public SQObject } SQObjectPtr(const SQObjectPtr &o) { - SQ_OBJECT_RAWINIT() - _type=o._type; - _unVal=o._unVal; + _type = o._type; + _unVal = o._unVal; __AddRef(_type,_unVal); } SQObjectPtr(const SQObject &o) { - SQ_OBJECT_RAWINIT() - _type=o._type; - _unVal=o._unVal; - __AddRef(_type,_unVal); - } - SQObjectPtr(SQTable *pTable) - { - SQ_OBJECT_RAWINIT() - _type=OT_TABLE; - _unVal.pTable=pTable; - assert(_unVal.pTable); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQClass *pClass) - { - SQ_OBJECT_RAWINIT() - _type=OT_CLASS; - _unVal.pClass=pClass; - assert(_unVal.pClass); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQInstance *pInstance) - { - SQ_OBJECT_RAWINIT() - _type=OT_INSTANCE; - _unVal.pInstance=pInstance; - assert(_unVal.pInstance); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQArray *pArray) - { - SQ_OBJECT_RAWINIT() - _type=OT_ARRAY; - _unVal.pArray=pArray; - assert(_unVal.pArray); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQClosure *pClosure) - { - SQ_OBJECT_RAWINIT() - _type=OT_CLOSURE; - _unVal.pClosure=pClosure; - assert(_unVal.pClosure); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQGenerator *pGenerator) - { - SQ_OBJECT_RAWINIT() - _type=OT_GENERATOR; - _unVal.pGenerator=pGenerator; - assert(_unVal.pGenerator); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQNativeClosure *pNativeClosure) - { - SQ_OBJECT_RAWINIT() - _type=OT_NATIVECLOSURE; - _unVal.pNativeClosure=pNativeClosure; - assert(_unVal.pNativeClosure); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQString *pString) - { - SQ_OBJECT_RAWINIT() - _type=OT_STRING; - _unVal.pString=pString; - assert(_unVal.pString); + _type = o._type; + _unVal = o._unVal; __AddRef(_type,_unVal); } - SQObjectPtr(SQUserData *pUserData) - { - SQ_OBJECT_RAWINIT() - _type=OT_USERDATA; - _unVal.pUserData=pUserData; - assert(_unVal.pUserData); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQVM *pThread) - { - SQ_OBJECT_RAWINIT() - _type=OT_THREAD; - _unVal.pThread=pThread; - assert(_unVal.pThread); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQWeakRef *pWeakRef) - { - SQ_OBJECT_RAWINIT() - _type=OT_WEAKREF; - _unVal.pWeakRef=pWeakRef; - assert(_unVal.pWeakRef); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQFunctionProto *pFunctionProto) - { - SQ_OBJECT_RAWINIT() - _type=OT_FUNCPROTO; - _unVal.pFunctionProto=pFunctionProto; - assert(_unVal.pFunctionProto); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQInteger nInteger) - { - SQ_OBJECT_RAWINIT() - _type=OT_INTEGER; - _unVal.nInteger=nInteger; - } - SQObjectPtr(SQFloat fFloat) - { - SQ_OBJECT_RAWINIT() - _type=OT_FLOAT; - _unVal.fFloat=fFloat; - } + _REF_TYPE_DECL(OT_TABLE,SQTable,pTable) + _REF_TYPE_DECL(OT_CLASS,SQClass,pClass) + _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance) + _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray) + _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure) + _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure) + _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter) + _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator) + _REF_TYPE_DECL(OT_STRING,SQString,pString) + _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData) + _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef) + _REF_TYPE_DECL(OT_THREAD,SQVM,pThread) + _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto) + + _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger) + _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat) + _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer) + SQObjectPtr(bool bBool) { SQ_OBJECT_RAWINIT() _type = OT_BOOL; _unVal.nInteger = bBool?1:0; } - SQObjectPtr(SQUserPointer pUserPointer) - { - SQ_OBJECT_RAWINIT() - _type=OT_USERPOINTER; - _unVal.pUserPointer=pUserPointer; - } - ~SQObjectPtr() - { - __Release(_type,_unVal); - } - inline void Null() - { - SQObjectType tOldType; - SQObjectValue unOldVal; - tOldType = _type; - unOldVal = _unVal; - _type = OT_NULL; - _unVal.pUserPointer = NULL; - __Release(tOldType,unOldVal); - } - inline SQObjectPtr& operator=(SQInteger i) - { + inline SQObjectPtr& operator=(bool b) + { __Release(_type,_unVal); SQ_OBJECT_RAWINIT() - _unVal.nInteger = i; - _type = OT_INTEGER; + _type = OT_BOOL; + _unVal.nInteger = b?1:0; return *this; } - inline SQObjectPtr& operator=(SQFloat f) + + ~SQObjectPtr() { __Release(_type,_unVal); - SQ_OBJECT_RAWINIT() - _unVal.fFloat = f; - _type = OT_FLOAT; - return *this; } + inline SQObjectPtr& operator=(const SQObjectPtr& obj) - { + { SQObjectType tOldType; SQObjectValue unOldVal; tOldType=_type; @@ -312,7 +274,7 @@ struct SQObjectPtr : public SQObject return *this; } inline SQObjectPtr& operator=(const SQObject& obj) - { + { SQObjectType tOldType; SQObjectValue unOldVal; tOldType=_type; @@ -323,10 +285,19 @@ struct SQObjectPtr : public SQObject __Release(tOldType,unOldVal); return *this; } + inline void Null() + { + SQObjectType tOldType = _type; + SQObjectValue unOldVal = _unVal; + _type = OT_NULL; + _unVal.raw = (SQRawObjectVal)NULL; + __Release(tOldType ,unOldVal); + } private: SQObjectPtr(const SQChar *){} //safety }; + inline void _Swap(SQObject &a,SQObject &b) { SQObjectType tOldType = a._type; @@ -336,6 +307,7 @@ inline void _Swap(SQObject &a,SQObject &b) b._type = tOldType; b._unVal = unOldVal; } + ///////////////////////////////////////////////////////////////////////////////////// #ifndef NO_GARBAGE_COLLECTOR #define MARK_FLAG 0x80000000 @@ -343,6 +315,7 @@ struct SQCollectable : public SQRefCounted { SQCollectable *_next; SQCollectable *_prev; SQSharedState *_sharedstate; + virtual SQObjectType GetType()=0; virtual void Release()=0; virtual void Mark(SQCollectable **chain)=0; void UnMark(); diff --git a/src/include/scripting/squirrel/sqopcodes.h b/src/include/scripting/squirrel/sqopcodes.h index a05788bf21..f5f5697c93 100644 --- a/src/include/scripting/squirrel/sqopcodes.h +++ b/src/include/scripting/squirrel/sqopcodes.h @@ -18,8 +18,24 @@ enum CmpOP { CMP_G = 0, CMP_GE = 2, CMP_L = 3, - CMP_LE = 4 + CMP_LE = 4, + CMP_3W = 5 }; + +enum NewObjectType { + NOT_TABLE = 0, + NOT_ARRAY = 1, + NOT_CLASS = 2 +}; + +enum AppendArrayType { + AAT_STACK = 0, + AAT_LITERAL = 1, + AAT_INT = 2, + AAT_FLOAT = 3, + AAT_BOOL = 4 +}; + enum SQOpcode { _OP_LINE= 0x00, @@ -39,25 +55,26 @@ enum SQOpcode _OP_GET= 0x0E, _OP_EQ= 0x0F, _OP_NE= 0x10, - _OP_ARITH= 0x11, - _OP_BITW= 0x12, - _OP_RETURN= 0x13, - _OP_LOADNULLS= 0x14, - _OP_LOADROOTTABLE= 0x15, - _OP_LOADBOOL= 0x16, - _OP_DMOVE= 0x17, - _OP_JMP= 0x18, - _OP_JNZ= 0x19, - _OP_JZ= 0x1A, - _OP_LOADFREEVAR= 0x1B, - _OP_VARGC= 0x1C, - _OP_GETVARGV= 0x1D, - _OP_NEWTABLE= 0x1E, - _OP_NEWARRAY= 0x1F, - _OP_APPENDARRAY= 0x20, - _OP_GETPARENT= 0x21, - _OP_COMPARITH= 0x22, - _OP_COMPARITHL= 0x23, + _OP_ADD= 0x11, + _OP_SUB= 0x12, + _OP_MUL= 0x13, + _OP_DIV= 0x14, + _OP_MOD= 0x15, + _OP_BITW= 0x16, + _OP_RETURN= 0x17, + _OP_LOADNULLS= 0x18, + _OP_LOADROOT= 0x19, + _OP_LOADBOOL= 0x1A, + _OP_DMOVE= 0x1B, + _OP_JMP= 0x1C, + //_OP_JNZ= 0x1D, + _OP_JCMP= 0x1D, + _OP_JZ= 0x1E, + _OP_SETOUTER= 0x1F, + _OP_GETOUTER= 0x20, + _OP_NEWOBJ= 0x21, + _OP_APPENDARRAY= 0x22, + _OP_COMPARITH= 0x23, _OP_INC= 0x24, _OP_INCL= 0x25, _OP_PINC= 0x26, @@ -75,14 +92,14 @@ enum SQOpcode _OP_RESUME= 0x32, _OP_FOREACH= 0x33, _OP_POSTFOREACH= 0x34, - _OP_DELEGATE= 0x35, - _OP_CLONE= 0x36, - _OP_TYPEOF= 0x37, - _OP_PUSHTRAP= 0x38, - _OP_POPTRAP= 0x39, - _OP_THROW= 0x3A, - _OP_CLASS= 0x3B, - _OP_NEWSLOTA= 0x3C, + _OP_CLONE= 0x35, + _OP_TYPEOF= 0x36, + _OP_PUSHTRAP= 0x37, + _OP_POPTRAP= 0x38, + _OP_THROW= 0x39, + _OP_NEWSLOTA= 0x3A, + _OP_GETBASE= 0x3B, + _OP_CLOSE= 0x3C, }; struct SQInstructionDesc { diff --git a/src/include/scripting/squirrel/sqrdbg.h b/src/include/scripting/squirrel/sqrdbg.h new file mode 100644 index 0000000000..5082ac59dd --- /dev/null +++ b/src/include/scripting/squirrel/sqrdbg.h @@ -0,0 +1,24 @@ +#ifndef _SQ_RDBG_H_ +#define _SQ_RDBG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*#ifdef _WIN32 +#pragma comment(lib, "WSOCK32.LIB") +#endif // _WIN32*/ + +struct SQDbgServer; +typedef SQDbgServer* HSQREMOTEDBG; + +HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate); +SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg); +SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg); +SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif //_SQ_RDBG_H_ diff --git a/src/include/scripting/squirrel/sqstate.h b/src/include/scripting/squirrel/sqstate.h index 6b36139939..4c5d98cb9e 100644 --- a/src/include/scripting/squirrel/sqstate.h +++ b/src/include/scripting/squirrel/sqstate.h @@ -11,7 +11,7 @@ struct SQTable; struct SQStringTable { - SQStringTable(); + SQStringTable(SQSharedState*ss); ~SQStringTable(); SQString *Add(const SQChar *,SQInteger len); void Remove(SQString *); @@ -21,6 +21,7 @@ struct SQStringTable SQString **_strings; SQUnsignedInteger _numofslots; SQUnsignedInteger _slotused; + SQSharedState *_sharedstate; }; struct RefTable { @@ -33,6 +34,7 @@ struct RefTable { ~RefTable(); void AddRef(SQObject &obj); SQBool Release(SQObject &obj); + SQUnsignedInteger GetRefCount(SQObject &obj); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); #endif @@ -64,6 +66,8 @@ struct SQSharedState SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name); #ifndef NO_GARBAGE_COLLECTOR SQInteger CollectGarbage(SQVM *vm); + void RunMark(SQVM *vm,SQCollectable **tchain); + SQInteger ResurrectUnreachable(SQVM *vm); static void MarkObject(SQObjectPtr &o,SQCollectable **chain); #endif SQObjectPtrVec *_metamethods; @@ -99,9 +103,10 @@ struct SQSharedState static SQRegFunction _instance_default_delegate_funcz[]; SQObjectPtr _weakref_default_delegate; static SQRegFunction _weakref_default_delegate_funcz[]; - + SQCOMPILERERROR _compilererrorhandler; SQPRINTFUNCTION _printfunc; + SQPRINTFUNCTION _errorfunc; bool _debuginfo; bool _notifyallexceptions; private: @@ -112,16 +117,16 @@ struct SQSharedState #define _sp(s) (_sharedstate->GetScratchPad(s)) #define _spval (_sharedstate->GetScratchPad(-1)) -#define _table_ddel _table(_sharedstate->_table_default_delegate) -#define _array_ddel _table(_sharedstate->_array_default_delegate) -#define _string_ddel _table(_sharedstate->_string_default_delegate) -#define _number_ddel _table(_sharedstate->_number_default_delegate) -#define _generator_ddel _table(_sharedstate->_generator_default_delegate) -#define _closure_ddel _table(_sharedstate->_closure_default_delegate) -#define _thread_ddel _table(_sharedstate->_thread_default_delegate) -#define _class_ddel _table(_sharedstate->_class_default_delegate) -#define _instance_ddel _table(_sharedstate->_instance_default_delegate) -#define _weakref_ddel _table(_sharedstate->_weakref_default_delegate) +#define _table_ddel _table(_sharedstate->_table_default_delegate) +#define _array_ddel _table(_sharedstate->_array_default_delegate) +#define _string_ddel _table(_sharedstate->_string_default_delegate) +#define _number_ddel _table(_sharedstate->_number_default_delegate) +#define _generator_ddel _table(_sharedstate->_generator_default_delegate) +#define _closure_ddel _table(_sharedstate->_closure_default_delegate) +#define _thread_ddel _table(_sharedstate->_thread_default_delegate) +#define _class_ddel _table(_sharedstate->_class_default_delegate) +#define _instance_ddel _table(_sharedstate->_instance_default_delegate) +#define _weakref_ddel _table(_sharedstate->_weakref_default_delegate) #ifdef SQUNICODE //rsl REAL STRING LEN #define rsl(l) ((l)<<1) @@ -129,13 +134,9 @@ struct SQSharedState #define rsl(l) (l) #endif -extern SQObjectPtr _null_; -extern SQObjectPtr _true_; -extern SQObjectPtr _false_; -extern SQObjectPtr _one_; -extern SQObjectPtr _minusone_; +//extern SQObjectPtr _null_; bool CompileTypemask(SQIntVec &res,const SQChar *typemask); -// C::B patch: Moved declarations of sq_vm_malloc (...) into sqmem.h + #endif //_SQSTATE_H_ diff --git a/src/include/scripting/include/sqstdaux.h b/src/include/scripting/squirrel/sqstdaux.h similarity index 100% rename from src/include/scripting/include/sqstdaux.h rename to src/include/scripting/squirrel/sqstdaux.h diff --git a/src/include/scripting/include/sqstdblob.h b/src/include/scripting/squirrel/sqstdblob.h similarity index 100% rename from src/include/scripting/include/sqstdblob.h rename to src/include/scripting/squirrel/sqstdblob.h diff --git a/src/include/scripting/include/sqstdio.h b/src/include/scripting/squirrel/sqstdio.h similarity index 95% rename from src/include/scripting/include/sqstdio.h rename to src/include/scripting/squirrel/sqstdio.h index 244a3a316b..2cb744bcf6 100644 --- a/src/include/scripting/include/sqstdio.h +++ b/src/include/scripting/squirrel/sqstdio.h @@ -7,8 +7,6 @@ #define SQSTD_STREAM_TYPE_TAG 0x80000000 struct SQStream { - // C::B patch: Keep gcc happy with a virtual dtor - virtual ~SQStream(){} virtual SQInteger Read(void *buffer, SQInteger size) = 0; virtual SQInteger Write(void *buffer, SQInteger size) = 0; virtual SQInteger Flush() = 0; diff --git a/src/include/scripting/include/sqstdmath.h b/src/include/scripting/squirrel/sqstdmath.h similarity index 100% rename from src/include/scripting/include/sqstdmath.h rename to src/include/scripting/squirrel/sqstdmath.h diff --git a/src/include/scripting/include/sqstdstring.h b/src/include/scripting/squirrel/sqstdstring.h similarity index 100% rename from src/include/scripting/include/sqstdstring.h rename to src/include/scripting/squirrel/sqstdstring.h diff --git a/src/include/scripting/include/sqstdsystem.h b/src/include/scripting/squirrel/sqstdsystem.h similarity index 100% rename from src/include/scripting/include/sqstdsystem.h rename to src/include/scripting/squirrel/sqstdsystem.h diff --git a/src/include/scripting/squirrel/sqtable.h b/src/include/scripting/squirrel/sqtable.h index 67a88de44b..b2ba0ba98e 100644 --- a/src/include/scripting/squirrel/sqtable.h +++ b/src/include/scripting/squirrel/sqtable.h @@ -61,6 +61,7 @@ struct SQTable : public SQDelegable } #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); + SQObjectType GetType() {return OT_TABLE;} #endif inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash) { diff --git a/src/include/scripting/include/squirrel.h b/src/include/scripting/squirrel/squirrel.h similarity index 75% rename from src/include/scripting/include/squirrel.h rename to src/include/scripting/squirrel/squirrel.h index 9b1b6e9c9e..f59c5b511b 100644 --- a/src/include/scripting/include/squirrel.h +++ b/src/include/scripting/squirrel/squirrel.h @@ -1,32 +1,23 @@ /* -Copyright (c) 2003-2011 Alberto Demichelis - -This software is provided 'as-is', without any -express or implied warranty. In no event will the -authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software -for any purpose, including commercial applications, -and to alter it and redistribute it freely, subject -to the following restrictions: - - 1. The origin of this software must not be - misrepresented; you must not claim that - you wrote the original software. If you - use this software in a product, an - acknowledgment in the product - documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly - marked as such, and must not be - misrepresented as being the original - software. - - 3. This notice may not be removed or - altered from any source distribution. - +Copyright (c) 2003-2012 Alberto Demichelis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ #ifndef _SQUIRREL_H_ #define _SQUIRREL_H_ @@ -45,29 +36,25 @@ extern "C" { #endif #endif - #ifdef _SQ64 - #ifdef _MSC_VER - typedef __int64 SQInteger; - typedef unsigned __int64 SQUnsignedInteger; - typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/ - // C::B patch: For Win64 build with GCC - #elif defined(__GNUC__) && defined(_WIN64) - typedef long long SQInteger; - typedef unsigned long long SQUnsignedInteger; - typedef unsigned long long SQHash; /* should be the same size of a pointer */ - // C::B patch: All other 64-bit platforms - #else - typedef long SQInteger; - typedef unsigned long SQUnsignedInteger; - typedef unsigned long SQHash; /*should be the same size of a pointer*/ - #endif - typedef int SQInt32; + +#ifdef _MSC_VER +typedef __int64 SQInteger; +typedef unsigned __int64 SQUnsignedInteger; +typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/ #else - typedef int SQInteger; - typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/ - typedef unsigned int SQUnsignedInteger; - typedef unsigned int SQHash; /*should be the same size of a pointer*/ +typedef long long SQInteger; +typedef unsigned long long SQUnsignedInteger; +typedef unsigned long long SQHash; /*should be the same size of a pointer*/ +#endif +typedef int SQInt32; +typedef unsigned int SQUnsignedInteger32; +#else +typedef int SQInteger; +typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/ +typedef unsigned int SQUnsignedInteger32; /*must be 32 bits(also on 64bits processors)*/ +typedef unsigned int SQUnsignedInteger; +typedef unsigned int SQHash; /*should be the same size of a pointer*/ #endif @@ -89,6 +76,14 @@ typedef SQUnsignedInteger SQRawObjectVal; //is 32 bits on 32 bits builds and 64 #define SQ_OBJECT_RAWINIT() #endif +#ifndef SQ_ALIGNMENT // SQ_ALIGNMENT shall be less than or equal to SQ_MALLOC alignments, and its value shall be power of 2. +#if defined(SQUSEDOUBLE) || defined(_SQ64) +#define SQ_ALIGNMENT 8 +#else +#define SQ_ALIGNMENT 4 +#endif +#endif + typedef void* SQUserPointer; typedef SQUnsignedInteger SQBool; typedef SQInteger SQRESULT; @@ -109,8 +104,9 @@ struct SQRefCounted; struct SQClass; struct SQInstance; struct SQDelegable; +struct SQOuter; -// C::B patch: Comment out Unicode stuff +// UNICODE is not needed because we use UTF8 in scripts, and for this char can be used //#ifdef _UNICODE //#define SQUNICODE //#endif @@ -118,13 +114,12 @@ struct SQDelegable; #ifdef SQUNICODE #if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8 -#if defined(wchar_t) //this is if the compiler considers wchar_t as native type +#if !defined(_NATIVE_WCHAR_T_DEFINED) //this is if the compiler considers wchar_t as native type #define wchar_t unsigned short #endif #else -// C::B patch: Comment out typedef -//typedef unsigned short wchar_t; +typedef unsigned short wchar_t; #endif typedef wchar_t SQChar; @@ -133,7 +128,11 @@ typedef wchar_t SQChar; #define scsprintf swprintf #define scstrlen wcslen #define scstrtod wcstod +#ifdef _SQ64 +#define scstrtol _wcstoi64 +#else #define scstrtol wcstol +#endif #define scatoi _wtoi #define scstrtoul wcstoul #define scvsprintf vswprintf @@ -153,7 +152,15 @@ typedef char SQChar; #define scsprintf sprintf #define scstrlen strlen #define scstrtod strtod +#ifdef _SQ64 +#ifdef _MSC_VER +#define scstrtol _strtoi64 +#else +#define scstrtol strtoll +#endif +#else #define scstrtol strtol +#endif #define scatoi atoi #define scstrtoul strtoul #define scvsprintf vsprintf @@ -168,10 +175,17 @@ typedef char SQChar; #define MAX_CHAR 0xFF #endif -#define SQUIRREL_VERSION _SC("Squirrel 2.2.5 stable") -#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2010 Alberto Demichelis") +#ifdef _SQ64 +#define _PRINT_INT_PREC _SC("ll") +#define _PRINT_INT_FMT _SC("%lld") +#else +#define _PRINT_INT_FMT _SC("%d") +#endif + +#define SQUIRREL_VERSION _SC("Squirrel 3.0.4 stable") +#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2012 Alberto Demichelis") #define SQUIRREL_AUTHOR _SC("Alberto Demichelis") -#define SQUIRREL_VERSION_NUMBER 225 +#define SQUIRREL_VERSION_NUMBER 304 #define SQ_VMSTATE_IDLE 0 #define SQ_VMSTATE_RUNNING 1 @@ -207,6 +221,7 @@ typedef char SQChar; #define _RT_CLASS 0x00004000 #define _RT_INSTANCE 0x00008000 #define _RT_WEAKREF 0x00010000 +#define _RT_OUTER 0x00020000 typedef enum tagSQObjectType{ OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE), @@ -225,7 +240,8 @@ typedef enum tagSQObjectType{ OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED), OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED) + OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED), + OT_OUTER = (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only }SQObjectType; #define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED) @@ -236,6 +252,7 @@ typedef union tagSQObjectValue struct SQTable *pTable; struct SQArray *pArray; struct SQClosure *pClosure; + struct SQOuter *pOuter; struct SQGenerator *pGenerator; struct SQNativeClosure *pNativeClosure; struct SQString *pString; @@ -260,6 +277,11 @@ typedef struct tagSQObject SQObjectValue _unVal; }SQObject; +typedef struct tagSQMemberHandle{ + SQBool _static; + SQInteger _index; +}SQMemberHandle; + typedef struct tagSQStackInfos{ const SQChar* funcname; const SQChar* source; @@ -268,11 +290,12 @@ typedef struct tagSQStackInfos{ typedef struct SQVM* HSQUIRRELVM; typedef SQObject HSQOBJECT; +typedef SQMemberHandle HSQMEMBERHANDLE; typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM); typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size); typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/); typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...); - +typedef void (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/); typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger); typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger); @@ -291,7 +314,6 @@ typedef struct tagSQFunctionInfo { const SQChar *source; }SQFunctionInfo; - /*vm*/ SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize); SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize); @@ -299,11 +321,13 @@ SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v); SQUIRREL_API void sq_close(HSQUIRRELVM v); SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p); SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v); -SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc); +SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc); SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v); +SQUIRREL_API SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v); SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v); SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror); SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v); +SQUIRREL_API SQInteger sq_getversion(); /*compiler*/ SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror); @@ -319,13 +343,14 @@ SQUIRREL_API void sq_poptop(HSQUIRRELVM v); SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v); SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop); -SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize); +SQUIRREL_API SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize); SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v); SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx); /*object creation handling*/ SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size); SQUIRREL_API void sq_newtable(HSQUIRRELVM v); +SQUIRREL_API void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity); SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size); SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars); SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask); @@ -337,10 +362,12 @@ SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b); SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p); SQUIRREL_API void sq_pushnull(HSQUIRRELVM v); SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx); SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v); -SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b); SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c); SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i); @@ -353,8 +380,9 @@ SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer ty SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag); SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook); SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize); -SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger idx,SQFunctionInfo *fi); +SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi); SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars); +SQUIRREL_API SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name); SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p); SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag); @@ -366,6 +394,9 @@ SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t); +SQUIRREL_API SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle); +SQUIRREL_API SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle); +SQUIRREL_API SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle); /*object manipulation*/ SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v); @@ -380,6 +411,8 @@ SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic); +SQUIRREL_API SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic); SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); @@ -398,8 +431,10 @@ SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror); SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror); SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx); +SQUIRREL_API SQRESULT sq_getcallee(HSQUIRRELVM v); SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err); +SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v); SQUIRREL_API void sq_reseterror(HSQUIRRELVM v); SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v); @@ -408,15 +443,18 @@ SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po); SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj); SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po); SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po); +SQUIRREL_API SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po); SQUIRREL_API void sq_resetobject(HSQOBJECT *po); -SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o); -SQUIRREL_API SQBool sq_objtobool(HSQOBJECT *o); -SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o); -SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o); -SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag); +SQUIRREL_API const SQChar *sq_objtostring(const HSQOBJECT *o); +SQUIRREL_API SQBool sq_objtobool(const HSQOBJECT *o); +SQUIRREL_API SQInteger sq_objtointeger(const HSQOBJECT *o); +SQUIRREL_API SQFloat sq_objtofloat(const HSQOBJECT *o); +SQUIRREL_API SQUserPointer sq_objtouserpointer(const HSQOBJECT *o); +SQUIRREL_API SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag); /*GC*/ SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_resurrectunreachable(HSQUIRRELVM v); /*serialization*/ SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up); @@ -430,6 +468,7 @@ SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size); /*debug*/ SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si); SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v); +SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook); /*UTILITY MACRO*/ #define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC) diff --git a/src/include/scripting/squirrel/squserdata.h b/src/include/scripting/squirrel/squserdata.h index d19255932f..2bf1b07096 100644 --- a/src/include/scripting/squirrel/squserdata.h +++ b/src/include/scripting/squirrel/squserdata.h @@ -12,7 +12,7 @@ struct SQUserData : SQDelegable } static SQUserData* Create(SQSharedState *ss, SQInteger size) { - SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1)); + SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size); new (ud) SQUserData(ss); ud->_size = size; ud->_typetag = 0; @@ -21,18 +21,20 @@ struct SQUserData : SQDelegable #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); void Finalize(){SetDelegate(NULL);} + SQObjectType GetType(){ return OT_USERDATA;} #endif void Release() { - if (_hook) _hook(_val,_size); - SQInteger tsize = _size - 1; + if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size); + SQInteger tsize = _size; this->~SQUserData(); - SQ_FREE(this, sizeof(SQUserData) + tsize); + SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize); } + SQInteger _size; SQRELEASEHOOK _hook; SQUserPointer _typetag; - SQChar _val[1]; + //SQChar _val[1]; }; #endif //_SQUSERDATA_H_ diff --git a/src/include/scripting/squirrel/squtils.h b/src/include/scripting/squirrel/squtils.h index bfe0afec08..c5512d101f 100644 --- a/src/include/scripting/squirrel/squtils.h +++ b/src/include/scripting/squirrel/squtils.h @@ -2,8 +2,9 @@ #ifndef _SQUTILS_H_ #define _SQUTILS_H_ -// C::B patch: Refer to outsourced declarations -#include "sqmem.h" +void *sq_vm_malloc(SQUnsignedInteger size); +void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size); +void sq_vm_free(void *p,SQUnsignedInteger size); #define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;} #define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));} @@ -11,6 +12,8 @@ #define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size)); #define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size)); +#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1))) + //sqvector mini vector class, supports objects by value template class sqvector { @@ -27,7 +30,13 @@ template class sqvector } void copy(const sqvector& v) { - resize(v._size); + if(_size) { + resize(0); //destroys all previous stuff + } + //resize(v._size); + if(v._size > _allocated) { + _realloc(v._size); + } for(SQUnsignedInteger i = 0; i < v._size; i++) { new ((void *)&_vals[i]) T(v._vals[i]); } diff --git a/src/include/scripting/squirrel/sqvm.h b/src/include/scripting/squirrel/sqvm.h index db6aeeda06..fad9c88a02 100644 --- a/src/include/scripting/squirrel/sqvm.h +++ b/src/include/scripting/squirrel/sqvm.h @@ -5,9 +5,10 @@ #include "sqopcodes.h" #include "sqobject.h" #define MAX_NATIVE_CALLS 100 -#define MIN_STACK_OVERHEAD 10 +#define MIN_STACK_OVERHEAD 15 #define SQ_SUSPEND_FLAG -666 +#define DONT_FALL_BACK 666 //base lib void sq_base_register(HSQUIRRELVM v); @@ -21,7 +22,7 @@ struct SQExceptionTrap{ SQInteger _extarget; }; -#define _INLINE +#define _INLINE #define STK(a) _stack._vals[_stackbase+(a)] #define TARGET _stack._vals[_stackbase+arg0] @@ -30,19 +31,8 @@ typedef sqvector ExceptionsTraps; struct SQVM : public CHAINABLE_OBJ { - struct VarArgs { - VarArgs() { size = 0; base = 0; } - // C::B patch: Eliminate compiler warnings - /* - unsigned short size; - unsigned short base; - */ - SQInt32 size; - SQInt32 base; - }; - struct CallInfo{ - //CallInfo() { _generator._type = OT_NULL;} + //CallInfo() { _generator = NULL;} SQInstruction *_ip; SQObjectPtr *_literals; SQObjectPtr _closure; @@ -53,18 +43,19 @@ struct SQVM : public CHAINABLE_OBJ SQInt32 _target; SQInt32 _ncalls; SQBool _root; - VarArgs _vargs; }; - + typedef sqvector CallInfoVec; public: - enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM, ET_RESUME_THROW_VM }; + void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); + static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname); + enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM }; SQVM(SQSharedState *ss); ~SQVM(); bool Init(SQVM *friendvm, SQInteger stacksize); - bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); + bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); //starts a native call return when the NATIVE closure returns - bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend); + bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval,bool &suspend); //starts a SQUIRREL call in the same "Execution loop" bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall); bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor); @@ -74,27 +65,34 @@ typedef sqvector CallInfoVec; void CallDebugHook(SQInteger type,SQInteger forcedline=0); void CallErrorHandler(SQObjectPtr &e); - bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot); - bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw); - bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot); + bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, SQInteger selfidx); + SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); + bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest); + bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx); + SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val); bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic); + bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw); bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res); bool Clone(const SQObjectPtr &self, SQObjectPtr &target); bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res); bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest); - bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res); - void ToString(const SQObjectPtr &o,SQObjectPtr &res); - SQString *PrintObjVal(const SQObject &o); - + static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res); + bool ToString(const SQObjectPtr &o,SQObjectPtr &res); + SQString *PrintObjVal(const SQObjectPtr &o); + void Raise_Error(const SQChar *s, ...); - void Raise_Error(SQObjectPtr &desc); - void Raise_IdxError(SQObject &o); + void Raise_Error(const SQObjectPtr &desc); + void Raise_IdxError(const SQObjectPtr &o); void Raise_CompareError(const SQObject &o1, const SQObject &o2); void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type); - void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); - bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); + void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex); + void RelocateOuters(); + void CloseOuters(SQObjectPtr *stackindex); + + bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); + bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest); bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval); //new stuff @@ -103,23 +101,19 @@ typedef sqvector CallInfoVec; _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1); _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res); bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func); - bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci); bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs); - bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target); //return true if the loop is finished bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump); - bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2); - _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + //_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); - _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix); - void PopVarArgs(VarArgs &vargs); - void ClearStack(SQInteger last_top); + _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0); #ifdef _DEBUG_DUMP void dumpstack(SQInteger stackbase=-1, bool dumpall = false); #endif #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); + SQObjectType GetType() {return OT_THREAD;} #endif void Finalize(); void GrowCallStack() { @@ -128,32 +122,39 @@ typedef sqvector CallInfoVec; _callsstack = &_callstackdata[0]; _alloccallsstacksize = newsize; } - void Release(){ sq_delete(this,SQVM); } //does nothing + bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall); + void LeaveFrame(); + void Release(){ sq_delete(this,SQVM); } //////////////////////////////////////////////////////////////////////////// //stack functions for the api void Remove(SQInteger n); - bool IsFalse(SQObjectPtr &o); - + static bool IsFalse(SQObjectPtr &o); + void Pop(); void Pop(SQInteger n); void Push(const SQObjectPtr &o); + void PushNull(); SQObjectPtr &Top(); SQObjectPtr &PopGet(); SQObjectPtr &GetUp(SQInteger n); SQObjectPtr &GetAt(SQInteger n); SQObjectPtrVec _stack; - SQObjectPtrVec _vargsstack; + SQInteger _top; SQInteger _stackbase; + SQOuter *_openouters; SQObjectPtr _roottable; SQObjectPtr _lasterror; SQObjectPtr _errorhandler; - SQObjectPtr _debughook; - SQObjectPtr temp_reg; + bool _debughook; + SQDEBUGHOOK _debughook_native; + SQObjectPtr _debughook_closure; + SQObjectPtr temp_reg; + CallInfo* _callsstack; SQInteger _callsstacksize; @@ -166,12 +167,12 @@ typedef sqvector CallInfoVec; //VMs sharing the same state SQSharedState *_sharedstate; SQInteger _nnativecalls; + SQInteger _nmetamethodscall; //suspend infos SQBool _suspended; SQBool _suspended_root; SQInteger _suspended_target; SQInteger _suspended_traps; - VarArgs _suspend_varargs; }; struct AutoDec{ @@ -191,20 +192,18 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v-> #endif #define PUSH_CALLINFO(v,nci){ \ - if(v->_callsstacksize == v->_alloccallsstacksize) { \ + SQInteger css = v->_callsstacksize; \ + if(css == v->_alloccallsstacksize) { \ v->GrowCallStack(); \ } \ - v->ci = &v->_callsstack[v->_callsstacksize]; \ + v->ci = &v->_callsstack[css]; \ *(v->ci) = nci; \ v->_callsstacksize++; \ } #define POP_CALLINFO(v){ \ - v->_callsstacksize--; \ + SQInteger css = --v->_callsstacksize; \ v->ci->_closure.Null(); \ - if(v->_callsstacksize) \ - v->ci = &v->_callsstack[v->_callsstacksize-1] ; \ - else \ - v->ci = NULL; \ + v->ci = css?&v->_callsstack[css-1]:NULL; \ } #endif //_SQVM_H_ diff --git a/src/sdk/scripting/sqstdlib/Makefile.am b/src/sdk/scripting/sqstdlib/Makefile.am index de26a29e88..9dacfa4b29 100644 --- a/src/sdk/scripting/sqstdlib/Makefile.am +++ b/src/sdk/scripting/sqstdlib/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src/include/scripting/include \ +AM_CPPFLAGS = -I$(top_srcdir)/src/include/scripting/squirrel \ -I$(top_srcdir)/src/include/scripting/sqstdlib noinst_LTLIBRARIES = libsqstdlib.la diff --git a/src/sdk/scripting/squirrel/Makefile.am b/src/sdk/scripting/squirrel/Makefile.am index cd0e234018..c252e3c792 100644 --- a/src/sdk/scripting/squirrel/Makefile.am +++ b/src/sdk/scripting/squirrel/Makefile.am @@ -1,5 +1,4 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src/include/scripting/include \ - -I$(top_srcdir)/src/include/scripting/squirrel +AM_CPPFLAGS = -I$(top_srcdir)/src/include/scripting/squirrel noinst_LTLIBRARIES = libsquirrel.la diff --git a/src/sdk/scripting/squirrel/serialize_state.inl b/src/sdk/scripting/squirrel/serialize_state.inl new file mode 100644 index 0000000000..94229f09c2 --- /dev/null +++ b/src/sdk/scripting/squirrel/serialize_state.inl @@ -0,0 +1,410 @@ +static const SQChar serialize_state_nut[] = { + 0x74, 0x72, 0x79, 0x20, 0x7b, 0xd, 0xa, 0x9, 0xd, 0xa, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, + 0x3d, 0x7b, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x3d, 0x30, 0x2c, 0x72, 0x65, + 0x66, 0x73, 0x3d, 0x7b, 0x7d, 0x7d, 0xd, 0xa, 0xd, 0xa, 0x63, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, + 0x3c, 0x2d, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, + 0xd, 0xa, 0x9, 0x5b, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x5d, + 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0xd, 0xa, 0x9, 0x5b, + 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, + 0x75, 0x6c, 0x6c, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, + 0x6c, 0x6c, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x77, 0x65, 0x61, 0x6b, + 0x72, 0x65, 0x66, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, + 0x2c, 0xd, 0xa, 0x7d, 0xd, 0xa, 0xd, 0xa, 0x66, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, + 0x65, 0x66, 0x73, 0x28, 0x74, 0x29, 0xd, 0xa, 0x7b, 0xd, 0xa, 0x9, + 0x69, 0x66, 0x28, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x3a, 0x3a, 0x67, 0x65, + 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, + 0x29, 0xd, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, + 0xd, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x3d, 0x20, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 0x28, + 0x74, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x69, 0x66, 0x28, 0x6f, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x29, 0xd, 0xa, 0x9, 0x7b, + 0xd, 0xa, 0x9, 0x9, 0x69, 0x66, 0x28, 0x21, 0x28, 0x74, 0x20, 0x69, + 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, + 0x65, 0x66, 0x73, 0x29, 0x29, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, + 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x6f, 0x62, 0x6a, 0x73, + 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x2b, 0x2b, + 0x3b, 0xd, 0xa, 0x9, 0x9, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, + 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x28, 0x74, 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x28, 0x6f, 0x2c, 0x69, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0xd, 0xa, + 0x9, 0x9, 0x20, 0x20, 0x20, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x20, 0x20, 0x20, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, + 0x66, 0x73, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x20, 0x20, 0x20, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, + 0x65, 0x66, 0x73, 0x28, 0x69, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x20, + 0x20, 0x20, 0x20, 0x7d, 0x29, 0xd, 0xa, 0x9, 0x9, 0x7d, 0xd, 0xa, + 0x9, 0x9, 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0x7d, 0xd, 0xa, 0xd, + 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, + 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x76, 0x29, 0xd, 0xa, 0x7b, + 0xd, 0xa, 0x9, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x28, 0x3a, 0x3a, + 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x29, 0x29, 0xd, 0xa, 0x9, 0x7b, + 0xd, 0xa, 0x9, 0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x22, 0x3a, 0xd, 0xa, 0x9, 0x9, 0x63, 0x61, 0x73, + 0x65, 0x20, 0x22, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x3a, 0xd, 0xa, + 0x9, 0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x22, 0x3a, 0xd, 0xa, 0x9, 0x9, 0x63, 0x61, 0x73, 0x65, 0x20, + 0x22, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0xd, + 0xa, 0x9, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, + 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, + 0x5b, 0x76, 0x5d, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x28, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x63, 0x61, 0x73, 0x65, 0x20, + 0x22, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x3a, 0xd, 0xa, + 0x9, 0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x22, 0x3a, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b, 0xd, 0xa, 0x9, 0x9, + 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x62, 0x6f, 0x6f, 0x6c, 0x22, 0x3a, + 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x76, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x28, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x63, 0x61, 0x73, 0x65, + 0x20, 0x22, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0xd, 0xa, + 0x9, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x3b, + 0xd, 0xa, 0x9, 0x9, 0x63, 0x61, 0x73, 0x65, 0x20, 0x22, 0x6e, 0x75, + 0x6c, 0x6c, 0x22, 0x3a, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x22, 0x6e, 0x75, 0x6c, 0x6c, + 0x22, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x3a, 0xd, 0xa, 0x9, 0x9, 0x9, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a, 0x74, 0x79, 0x70, 0x65, 0x28, + 0x76, 0x29, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0x7d, 0xd, + 0xa, 0xd, 0xa, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x63, + 0x6b, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x3d, 0x7b, 0xd, + 0xa, 0x9, 0x5b, 0x22, 0x6e, 0x75, 0x6c, 0x6c, 0x22, 0x5d, 0x3d, 0x22, + 0x6e, 0x22, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x22, 0x5d, 0x3d, 0x22, 0x73, 0x22, 0x2c, 0xd, 0xa, 0x9, + 0x5b, 0x22, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x22, 0x5d, 0x3d, + 0x22, 0x69, 0x22, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x22, 0x5d, 0x3d, 0x22, 0x66, 0x22, 0x2c, 0xd, 0xa, 0x9, + 0x5b, 0x22, 0x75, 0x73, 0x65, 0x72, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5d, + 0x3d, 0x22, 0x75, 0x22, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x66, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5d, 0x3d, 0x22, 0x66, 0x6e, + 0x22, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x22, 0x5d, 0x3d, 0x22, 0x74, 0x22, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, + 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x5d, 0x3d, 0x22, 0x61, 0x22, 0x2c, + 0xd, 0xa, 0x9, 0x5b, 0x22, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x22, 0x5d, 0x3d, 0x22, 0x67, 0x22, 0x2c, 0xd, 0xa, 0x9, + 0x5b, 0x22, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x5d, 0x3d, 0x22, + 0x68, 0x22, 0x2c, 0xd, 0xa, 0x9, 0x5b, 0x22, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x22, 0x5d, 0x3d, 0x22, 0x78, 0x22, 0x2c, 0x20, + 0xd, 0xa, 0x9, 0x5b, 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x5d, + 0x3d, 0x22, 0x79, 0x22, 0x2c, 0x20, 0x20, 0xd, 0xa, 0x9, 0x5b, 0x22, + 0x62, 0x6f, 0x6f, 0x6c, 0x22, 0x5d, 0x3d, 0x22, 0x62, 0x22, 0x2c, 0xd, + 0xa, 0x9, 0x5b, 0x22, 0x77, 0x65, 0x61, 0x6b, 0x72, 0x65, 0x66, 0x22, + 0x5d, 0x3d, 0x22, 0x77, 0x22, 0x20, 0x20, 0xd, 0xa, 0x7d, 0xd, 0xa, + 0xd, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, + 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x74, 0x79, 0x70, + 0x65, 0x29, 0xd, 0xa, 0x7b, 0xd, 0xa, 0x9, 0x69, 0x66, 0x28, 0x74, + 0x79, 0x70, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, + 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x29, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x5d, 0xd, 0xa, 0x9, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0xd, + 0xa, 0x7d, 0x20, 0xd, 0xa, 0xd, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x66, 0x75, + 0x6e, 0x63, 0x29, 0xd, 0xa, 0x7b, 0xd, 0xa, 0x9, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x20, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x3a, 0x3a, 0x74, 0x79, + 0x70, 0x65, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x69, + 0x66, 0x28, 0x74, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x29, 0x20, 0x7b, 0xd, 0xa, 0x9, + 0x9, 0x74, 0x72, 0x79, 0x20, 0x7b, 0x20, 0x2f, 0x2f, 0x54, 0x52, 0x59, + 0x20, 0x54, 0x4f, 0x20, 0x55, 0x53, 0x45, 0x20, 0x5f, 0x6e, 0x65, 0x78, + 0x74, 0x69, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, + 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, + 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29, 0xd, 0xa, 0x9, + 0x9, 0x20, 0x20, 0x20, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, + 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x69, 0x64, 0x78, + 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, + 0x20, 0x20, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, + 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x29, 0x20, 0x7b, 0xd, 0xa, + 0x9, 0x9, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, + 0x28, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, + 0x6f, 0x62, 0x6a, 0x2e, 0x67, 0x65, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, + 0x28, 0x29, 0x29, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, 0x7b, 0xd, + 0xa, 0x9, 0x9, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, + 0x2c, 0x69, 0x64, 0x78, 0x2c, 0x6f, 0x62, 0x6a, 0x5b, 0x69, 0x64, 0x78, + 0x5d, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, 0x7d, 0xd, + 0xa, 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x65, + 0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x28, 0x74, 0x79, 0x20, 0x3d, 0x3d, + 0x20, 0x22, 0x77, 0x65, 0x61, 0x6b, 0x72, 0x65, 0x66, 0x22, 0x29, 0x20, + 0x7b, 0xd, 0xa, 0x9, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, + 0x6a, 0x2c, 0x22, 0x40, 0x72, 0x65, 0x66, 0x22, 0x2c, 0x6f, 0x62, 0x6a, + 0x2e, 0x72, 0x65, 0x66, 0x28, 0x29, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x7d, + 0xd, 0xa, 0x9, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0xd, 0xa, 0x9, + 0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x64, 0x78, + 0x2c, 0x76, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29, + 0xd, 0xa, 0x9, 0x9, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, + 0x20, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x69, 0x64, + 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x7d, + 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x9, 0xd, 0xa, 0x7d, + 0xd, 0xa, 0xd, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x28, + 0x29, 0xd, 0xa, 0x7b, 0xd, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, + 0x63, 0x68, 0x28, 0x69, 0x2c, 0x6f, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, + 0x6a, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x29, + 0xd, 0xa, 0x9, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x62, 0x65, 0x67, 0x69, + 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x22, + 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x28, + 0x69, 0x3d, 0x3d, 0x3a, 0x3a, 0x67, 0x65, 0x74, 0x72, 0x6f, 0x6f, 0x74, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x3f, 0x22, 0x72, 0x22, 0x3a, + 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a, + 0x74, 0x79, 0x70, 0x65, 0x28, 0x69, 0x29, 0x29, 0x29, 0x29, 0x3b, 0xd, + 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x6f, 0x66, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x6f, + 0x66, 0x20, 0x69, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x69, 0x66, 0x28, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x21, 0x3d, 0x20, 0x3a, 0x3a, + 0x74, 0x79, 0x70, 0x65, 0x28, 0x69, 0x29, 0x29, 0x20, 0x7b, 0xd, 0xa, + 0x9, 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x22, 0x2c, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x6f, 0x66, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x7d, + 0xd, 0xa, 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x28, 0x22, 0x72, 0x65, 0x66, 0x22, 0x2c, 0x6f, 0x2e, 0x74, 0x6f, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 0xd, 0xa, + 0x9, 0x9, 0x69, 0x66, 0x28, 0x69, 0x20, 0x21, 0x3d, 0x20, 0x3a, 0x3a, + 0x67, 0x65, 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x28, 0x29, 0x29, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x69, 0x74, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x69, + 0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6f, + 0x62, 0x6a, 0x2c, 0x69, 0x64, 0x78, 0x2c, 0x76, 0x61, 0x6c, 0x29, 0x20, + 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x69, 0x66, 0x28, 0x3a, 0x3a, + 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x20, 0x3d, 0x3d, + 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29, + 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0xd, 0xa, 0x9, + 0x9, 0x9, 0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x28, 0x22, 0x65, 0x22, 0x29, 0x3b, 0x9, 0xd, 0xa, + 0x9, 0x9, 0x9, 0x9, 0x9, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x28, 0x22, 0x6b, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x76, 0x22, + 0x2c, 0x69, 0x64, 0x78, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, + 0x9, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x22, + 0x76, 0x74, 0x22, 0x2c, 0x22, 0x76, 0x22, 0x2c, 0x6f, 0x62, 0x6a, 0x5b, + 0x69, 0x64, 0x78, 0x5d, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, + 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, + 0x65, 0x22, 0x29, 0x3b, 0x9, 0xd, 0xa, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x7d, 0x29, 0xd, 0xa, 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x65, + 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, + 0x22, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0x7d, 0xd, 0xa, + 0xd, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, + 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x5f, 0x77, 0x61, 0x74, 0x63, + 0x68, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x2c, 0x69, 0x64, 0x2c, + 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0xd, + 0xa, 0x7b, 0xd, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, + 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x28, 0x22, 0xd, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, + 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3d, 0x5b, 0x5d, 0x3b, 0xd, 0xa, + 0x9, 0xd, 0xa, 0x9, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, + 0x70, 0x70, 0x65, 0x6e, 0x64, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, + 0x5b, 0x22, 0x74, 0x68, 0x69, 0x73, 0x22, 0x5d, 0x29, 0xd, 0xa, 0x9, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x3d, + 0x31, 0x3b, 0xd, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, + 0x28, 0x69, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x73, 0x29, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x69, 0x66, 0x28, 0x69, + 0x21, 0x3d, 0x22, 0x74, 0x68, 0x69, 0x73, 0x22, 0x20, 0x26, 0x26, 0x20, + 0x69, 0x5b, 0x30, 0x5d, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x40, 0x27, 0x29, + 0x7b, 0x20, 0x2f, 0x2f, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x20, + 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x40, 0xd, 0xa, + 0x9, 0x9, 0x9, 0x69, 0x66, 0x28, 0x21, 0x66, 0x69, 0x72, 0x73, 0x74, + 0x29, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x66, 0x75, 0x6e, 0x63, + 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, + 0x63, 0x2b, 0x22, 0x2c, 0x22, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0xd, + 0xa, 0x9, 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x9, 0x66, 0x69, + 0x72, 0x73, 0x74, 0x3d, 0x6e, 0x75, 0x6c, 0x6c, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x61, 0x70, 0x70, 0x65, + 0x6e, 0x64, 0x28, 0x76, 0x29, 0xd, 0xa, 0x9, 0x9, 0x9, 0x66, 0x75, + 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, + 0x73, 0x72, 0x63, 0x2b, 0x69, 0xd, 0xa, 0x9, 0x9, 0x7d, 0xd, 0xa, + 0x9, 0x7d, 0xd, 0xa, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, + 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x2b, 0x22, + 0x29, 0x7b, 0x5c, 0x6e, 0x22, 0xd, 0xa, 0x9, 0x66, 0x75, 0x6e, 0x63, + 0x5f, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, + 0x63, 0x2b, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x22, + 0x2b, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2b, + 0x22, 0x29, 0x5c, 0x6e, 0x7d, 0x22, 0xd, 0xa, 0x9, 0xd, 0xa, 0x9, + 0x74, 0x72, 0x79, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x3d, 0x3a, 0x3a, 0x63, 0x6f, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, + 0x66, 0x75, 0x6e, 0x63, 0x5f, 0x73, 0x72, 0x63, 0x29, 0x3b, 0xd, 0xa, + 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x7b, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x3d, 0x22, 0x6f, 0x6b, 0x22, 0x20, 0x2c, 0x20, + 0x76, 0x61, 0x6c, 0x3d, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x29, 0x2e, 0x61, + 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, + 0x7d, 0x3b, 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x63, 0x61, 0x74, + 0x63, 0x68, 0x28, 0x65, 0x29, 0xd, 0xa, 0x9, 0x7b, 0xd, 0xa, 0x9, + 0x9, 0xd, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x7b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x22, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x22, 0x7d, 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0x7d, 0xd, + 0xa, 0xd, 0xa, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0xd, 0xa, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0xd, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, + 0x74, 0x79, 0x70, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x2c, 0x76, 0x61, 0x6c, 0x29, 0xd, 0xa, 0x7b, 0xd, 0xa, 0x9, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 0x70, 0x61, 0x63, + 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x28, 0x3a, 0x3a, 0x74, 0x79, 0x70, + 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29, 0x29, 0x29, 0x3b, 0xd, 0xa, 0x9, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x2c, 0x67, + 0x65, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x29, + 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, + 0x3b, 0xd, 0xa, 0x7d, 0xd, 0xa, 0xd, 0xa, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x3d, 0x5b, 0x5d, 0xd, 0xa, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d, + 0x33, 0x3b, 0xd, 0xa, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x69, + 0x3b, 0xd, 0xa, 0xd, 0xa, 0x2f, 0x2f, 0x74, 0x72, 0x79, 0x20, 0x7b, + 0xd, 0xa, 0x9, 0x2f, 0x2f, 0x45, 0x4e, 0x55, 0x4d, 0x45, 0x52, 0x41, + 0x54, 0x45, 0x20, 0x54, 0x48, 0x45, 0x20, 0x53, 0x54, 0x41, 0x43, 0x4b, + 0x20, 0x57, 0x41, 0x54, 0x43, 0x48, 0x45, 0x53, 0xd, 0xa, 0x9, 0x77, + 0x68, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x69, 0x3d, 0x3a, 0x3a, 0x67, 0x65, + 0x74, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x28, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x29, 0x29, 0xd, 0xa, 0x9, 0x7b, 0xd, + 0xa, 0x9, 0x9, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x61, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x28, 0x73, 0x69, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2b, 0x2b, 0x3b, 0xd, 0xa, 0x9, 0x7d, + 0xd, 0xa, 0xd, 0xa, 0x9, 0x2f, 0x2f, 0x45, 0x56, 0x41, 0x4c, 0x55, + 0x41, 0x54, 0x45, 0x20, 0x41, 0x4c, 0x4c, 0x20, 0x57, 0x41, 0x54, 0x43, + 0x48, 0x45, 0x53, 0xd, 0xa, 0x9, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, + 0x65, 0x67, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x5b, 0x3a, 0x3a, 0x67, 0x65, + 0x74, 0x72, 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, + 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, + 0x67, 0x2e, 0x6d, 0x61, 0x78, 0x69, 0x64, 0x2b, 0x2b, 0x3b, 0xd, 0xa, + 0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, + 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x29, + 0xd, 0xa, 0x9, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x69, 0x66, 0x28, 0x76, + 0x61, 0x6c, 0x2e, 0x73, 0x72, 0x63, 0x21, 0x3d, 0x22, 0x4e, 0x41, 0x54, + 0x49, 0x56, 0x45, 0x22, 0x29, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x69, 0x66, 0x28, 0x22, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, + 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x7b, 0xd, + 0xa, 0x9, 0x9, 0x9, 0x9, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x20, 0x3c, 0x2d, 0x20, 0x7b, 0x7d, 0xd, 0xa, + 0x9, 0x9, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, + 0x69, 0x2c, 0x77, 0x61, 0x74, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x77, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x29, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x9, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x69, 0x66, 0x28, + 0x76, 0x61, 0x6c, 0x2e, 0x73, 0x72, 0x63, 0x21, 0x3d, 0x22, 0x4e, 0x41, + 0x54, 0x49, 0x56, 0x45, 0x22, 0x29, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x9, 0x9, 0x9, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x20, 0x3c, 0x2d, 0x20, 0x65, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x65, 0x5f, 0x77, 0x61, 0x74, 0x63, 0x68, 0x28, + 0x76, 0x61, 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x2c, 0x69, + 0x2c, 0x77, 0x61, 0x74, 0x63, 0x68, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x9, 0x9, 0x9, 0x69, 0x66, 0x28, 0x76, 0x61, 0x6c, 0x2e, 0x77, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, 0x2e, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x21, 0x3d, 0x22, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0x29, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x28, 0x76, 0x61, + 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, + 0x2e, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, + 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x65, 0x6c, 0x73, + 0x65, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x76, 0x61, + 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, 0x5d, + 0x20, 0x3c, 0x2d, 0x20, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, + 0x22, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7d, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x76, + 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5b, 0x69, + 0x5d, 0x2e, 0x65, 0x78, 0x70, 0x20, 0x3c, 0x2d, 0x20, 0x77, 0x61, 0x74, + 0x63, 0x68, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x7d, 0xd, 0xa, + 0x9, 0x9, 0x9, 0x9, 0xd, 0xa, 0x9, 0x9, 0x9, 0x7d, 0xd, 0xa, + 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, + 0x63, 0x68, 0x28, 0x69, 0x2c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x76, 0x61, + 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x73, 0x29, 0xd, 0xa, 0x9, + 0x9, 0x9, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, + 0x28, 0x6c, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x7d, 0xd, 0xa, 0xd, 0xa, + 0xd, 0xa, 0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x62, 0x6a, 0x73, 0x22, 0x29, 0x3b, + 0xd, 0xa, 0x9, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x65, + 0x65, 0x28, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6f, 0x62, 0x6a, 0x73, 0x22, + 0x29, 0x3b, 0xd, 0xa, 0xd, 0xa, 0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c, + 0x6c, 0x73, 0x22, 0x29, 0x3b, 0xd, 0xa, 0xd, 0xa, 0x9, 0x66, 0x6f, + 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x61, 0x6c, 0x20, + 0x69, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x29, 0xd, 0xa, 0x9, + 0x7b, 0xd, 0xa, 0xd, 0xa, 0x9, 0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c, + 0x6c, 0x22, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x66, 0x6e, 0x63, 0x22, 0x2c, + 0x76, 0x61, 0x6c, 0x2e, 0x66, 0x75, 0x6e, 0x63, 0x29, 0x3b, 0xd, 0xa, + 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, + 0x22, 0x73, 0x72, 0x63, 0x22, 0x2c, 0x76, 0x61, 0x6c, 0x2e, 0x73, 0x72, + 0x63, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x2c, + 0x76, 0x61, 0x6c, 0x2e, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x74, 0x6f, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 0xd, 0xa, 0x9, + 0x9, 0x66, 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, + 0x20, 0x69, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x2e, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x73, 0x29, 0xd, 0xa, 0x9, 0x9, 0x7b, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x28, 0x22, 0x6c, 0x22, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, + 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, + 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x67, 0x65, 0x74, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x28, 0x69, 0x29, 0x2e, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, + 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x22, 0x74, + 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x76, 0x61, 0x6c, 0x22, 0x2c, 0x76, + 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x6c, 0x22, 0x29, 0x3b, 0xd, + 0xa, 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x69, 0x66, 0x28, 0x22, + 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0x20, 0x69, 0x6e, 0x20, + 0x76, 0x61, 0x6c, 0x29, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x66, + 0x6f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x2c, 0x76, 0x20, 0x69, + 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x2e, 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x73, 0x29, 0xd, 0xa, 0x9, 0x9, 0x9, 0x7b, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x9, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x28, 0x22, 0x77, 0x22, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x28, 0x22, 0x69, 0x64, 0x22, 0x2c, 0x69, 0x2e, 0x74, 0x6f, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x9, 0x9, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x28, 0x22, 0x65, 0x78, 0x70, 0x22, 0x2c, 0x76, 0x2e, 0x65, 0x78, 0x70, + 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x2c, 0x76, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x69, 0x66, 0x28, + 0x76, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x21, 0x3d, 0x22, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x22, 0x29, 0x20, 0x7b, 0xd, 0xa, 0x9, 0x9, + 0x9, 0x9, 0x9, 0x9, 0x65, 0x6d, 0x69, 0x74, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x28, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x22, 0x76, 0x61, + 0x6c, 0x22, 0x2c, 0x76, 0x2e, 0x76, 0x61, 0x6c, 0x29, 0x3b, 0xd, 0xa, + 0x9, 0x9, 0x9, 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x9, 0x9, + 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, + 0x77, 0x22, 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x9, 0x7d, 0xd, 0xa, + 0x9, 0x9, 0x7d, 0xd, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x61, 0x6c, 0x6c, 0x22, + 0x29, 0x3b, 0xd, 0xa, 0x9, 0x9, 0x20, 0xd, 0xa, 0x9, 0x7d, 0xd, + 0xa, 0x9, 0x65, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x28, 0x22, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x22, 0x29, 0x3b, 0xd, 0xa, + 0xd, 0xa, 0xd, 0xa, 0x9, 0x6f, 0x62, 0x6a, 0x73, 0x5f, 0x72, 0x65, + 0x67, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b, 0xd, 0xa, 0x9, + 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, + 0x3b, 0xd, 0xa, 0x9, 0xd, 0xa, 0x9, 0x69, 0x66, 0x28, 0x22, 0x63, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, 0x62, 0x61, 0x67, + 0x65, 0x22, 0x20, 0x69, 0x6e, 0x20, 0x3a, 0x3a, 0x67, 0x65, 0x74, 0x72, + 0x6f, 0x6f, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0x29, 0x20, + 0x3a, 0x3a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x67, 0x61, 0x72, + 0x62, 0x61, 0x67, 0x65, 0x28, 0x29, 0x3b, 0xd, 0xa, 0x7d, 0x63, 0x61, + 0x74, 0x63, 0x68, 0x28, 0x65, 0x29, 0xd, 0xa, 0x7b, 0xd, 0xa, 0x9, + 0x3a, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x22, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x22, 0x2b, 0x65, 0x2b, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x3b, + 0xd, 0xa, 0x7d, 0xd, 0xa, 0xd, 0xa }; diff --git a/src/sdk/scripting/squirrel/serialize_state.nut b/src/sdk/scripting/squirrel/serialize_state.nut new file mode 100644 index 0000000000..d490a023ae --- /dev/null +++ b/src/sdk/scripting/squirrel/serialize_state.nut @@ -0,0 +1,262 @@ +try { + +local objs_reg={maxid=0,refs={}} + +complex_types <- { + ["table"] = null, + ["array"] = null, + ["class"] = null, + ["instance"] = null, + ["weakref"] = null, +} + +function build_refs(t) +{ + if(t == ::getroottable()) + return; + local otype = ::type(t); + if(otype in complex_types) + { + if(!(t in objs_reg.refs)) { + objs_reg.refs[t] <- objs_reg.maxid++; + + iterateobject(t,function(o,i,val) + { + build_refs(val); + build_refs(i); + }) + } + + } +} + +function getvalue(v) +{ + switch(::type(v)) + { + case "table": + case "array": + case "class": + case "instance": + return objs_reg.refs[v].tostring(); + case "integer": + case "float": + return v; + case "bool": + return v.tostring(); + case "string": + return v; + case "null": + return "null"; + default: + + return pack_type(::type(v)); + } +} + +local packed_types={ + ["null"]="n", + ["string"]="s", + ["integer"]="i", + ["float"]="f", + ["userdata"]="u", + ["function"]="fn", + ["table"]="t", + ["array"]="a", + ["generator"]="g", + ["thread"]="h", + ["instance"]="x", + ["class"]="y", + ["bool"]="b", + ["weakref"]="w" +} + +function pack_type(type) +{ + if(type in packed_types)return packed_types[type] + return type +} + +function iterateobject(obj,func) +{ + local ty = ::type(obj); + if(ty == "instance") { + try { //TRY TO USE _nexti + foreach(idx,val in obj) + { + func(obj,idx,val); + } + } + catch(e) { + foreach(idx,val in obj.getclass()) + { + func(obj,idx,obj[idx]); + } + } + } + else if(ty == "weakref") { + func(obj,"@ref",obj.ref()); + } + else { + foreach(idx,val in obj) + { + func(obj,idx,val); + } + } + +} + +function build_tree() +{ + foreach(i,o in objs_reg.refs) + { + beginelement("o"); + attribute("type",(i==::getroottable()?"r":pack_type(::type(i)))); + local _typeof = typeof i; + if(_typeof != ::type(i)) { + attribute("typeof",_typeof); + } + attribute("ref",o.tostring()); + if(i != ::getroottable()){ + iterateobject(i,function (obj,idx,val) { + if(::type(val) == "function") + return; + + beginelement("e"); + emitvalue("kt","kv",idx); + emitvalue("vt","v",obj[idx]); + endelement("e"); + + }) + } + endelement("o"); + } +} + +function evaluate_watch(locals,id,expression) +{ + local func_src="return function (" + local params=[]; + + params.append(locals["this"]) + local first=1; + foreach(i,v in locals){ + if(i!="this" && i[0] != '@'){ //foreach iterators start with @ + if(!first){ + func_src=func_src+"," + + } + first=null + params.append(v) + func_src=func_src+i + } + } + func_src=func_src+"){\n" + func_src=func_src+"return ("+expression+")\n}" + + try { + local func=::compilestring(func_src); + return {status="ok" , val=func().acall(params)}; + } + catch(e) + { + + return {status="error"} + } +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +function emitvalue(type_attrib,value_attrib,val) +{ + attribute(type_attrib,pack_type(::type(val))); + attribute(value_attrib,getvalue(val).tostring()); +} + +local stack=[] +local level=3; +local si; + +//try { + //ENUMERATE THE STACK WATCHES + while(si=::getstackinfos(level)) + { + stack.append(si); + level++; + } + + //EVALUATE ALL WATCHES + objs_reg.refs[::getroottable()] <- objs_reg.maxid++; + foreach(i,val in stack) + { + if(val.src!="NATIVE") { + if("watches" in this) { + val.watches <- {} + foreach(i,watch in watches) + { + if(val.src!="NATIVE"){ + val.watches[i] <- evaluate_watch(val.locals,i,watch); + if(val.watches[i].status!="error") + build_refs(val.watches[i].val); + } + else{ + val.watches[i] <- {status="error"} + } + val.watches[i].exp <- watch; + } + + } + } + foreach(i,l in val.locals) + build_refs(l); + } + + + beginelement("objs"); + build_tree(); + endelement("objs"); + + beginelement("calls"); + + foreach(i,val in stack) + { + + beginelement("call"); + attribute("fnc",val.func); + attribute("src",val.src); + attribute("line",val.line.tostring()); + foreach(i,v in val.locals) + { + beginelement("l"); + attribute("name",getvalue(i).tostring()); + emitvalue("type","val",v); + endelement("l"); + } + if("watches" in val) { + foreach(i,v in val.watches) + { + beginelement("w"); + attribute("id",i.tostring()); + attribute("exp",v.exp); + attribute("status",v.status); + if(v.status!="error") { + emitvalue("type","val",v.val); + } + endelement("w"); + } + } + endelement("call"); + + } + endelement("calls"); + + + objs_reg = null; + stack = null; + + if("collectgarbage" in ::getroottable()) ::collectgarbage(); +}catch(e) +{ + ::print("ERROR"+e+"\n"); +} + diff --git a/src/sdk/scripting/squirrel/sqapi.cpp b/src/sdk/scripting/squirrel/sqapi.cpp index e4e0dadbcd..7b55bdf88b 100644 --- a/src/sdk/scripting/squirrel/sqapi.cpp +++ b/src/sdk/scripting/squirrel/sqapi.cpp @@ -29,13 +29,8 @@ bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPt #define sq_aux_paramscheck(v,count) \ { \ if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\ -} +} -SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e) -{ - v->_lasterror = e; - return SQ_ERROR; -} SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type) { @@ -66,10 +61,10 @@ HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize) SQSharedState *ss; SQVM *v; ss=_ss(friendvm); - + v= (SQVM *)SQ_MALLOC(sizeof(SQVM)); new (v) SQVM(ss); - + if(v->Init(friendvm, initialstacksize)) { friendvm->Push(v); return v; @@ -83,7 +78,7 @@ SQInteger sq_getvmstate(HSQUIRRELVM v) { if(v->_suspended) return SQ_VMSTATE_SUSPENDED; - else { + else { if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING; else return SQ_VMSTATE_IDLE; } @@ -98,11 +93,20 @@ void sq_seterrorhandler(HSQUIRRELVM v) } } +void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook) +{ + v->_debughook_native = hook; + v->_debughook_closure.Null(); + v->_debughook = hook?true:false; +} + void sq_setdebughook(HSQUIRRELVM v) { SQObject o = stack_get(v,-1); if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { - v->_debughook = o; + v->_debughook_closure = o; + v->_debughook_native = NULL; + v->_debughook = !sq_isnull(o); v->Pop(); } } @@ -114,14 +118,23 @@ void sq_close(HSQUIRRELVM v) sq_delete(ss, SQSharedState); } +SQInteger sq_getversion() +{ + return SQUIRREL_VERSION_NUMBER; +} + SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror) { SQObjectPtr o; +#ifndef NO_COMPILER if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { v->Push(SQClosure::Create(_ss(v), _funcproto(o))); return SQ_OK; } return SQ_ERROR; +#else + return sq_throwerror(v,_SC("this is a no compiler build")); +#endif } void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable) @@ -144,18 +157,29 @@ void sq_addref(HSQUIRRELVM v,HSQOBJECT *po) #endif } +SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po) +{ + if(!ISREFCOUNTED(type(*po))) return 0; +#ifdef NO_GARBAGE_COLLECTOR + return po->_unVal.pRefCounted->_uiRef; +#else + return _ss(v)->_refs_table.GetRefCount(*po); +#endif +} + SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po) { if(!ISREFCOUNTED(type(*po))) return SQTrue; #ifdef NO_GARBAGE_COLLECTOR + bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse; __Release(po->_type,po->_unVal); - return SQFalse; //the ret val doesn't work(and cannot be fixed) + return ret; //the ret val doesn't work(and cannot be fixed) #else return _ss(v)->_refs_table.Release(*po); #endif } -const SQChar *sq_objtostring(HSQOBJECT *o) +const SQChar *sq_objtostring(const HSQOBJECT *o) { if(sq_type(*o) == OT_STRING) { return _stringval(*o); @@ -163,7 +187,7 @@ const SQChar *sq_objtostring(HSQOBJECT *o) return NULL; } -SQInteger sq_objtointeger(HSQOBJECT *o) +SQInteger sq_objtointeger(const HSQOBJECT *o) { if(sq_isnumeric(*o)) { return tointeger(*o); @@ -171,7 +195,7 @@ SQInteger sq_objtointeger(HSQOBJECT *o) return 0; } -SQFloat sq_objtofloat(HSQOBJECT *o) +SQFloat sq_objtofloat(const HSQOBJECT *o) { if(sq_isnumeric(*o)) { return tofloat(*o); @@ -179,7 +203,7 @@ SQFloat sq_objtofloat(HSQOBJECT *o) return 0; } -SQBool sq_objtobool(HSQOBJECT *o) +SQBool sq_objtobool(const HSQOBJECT *o) { if(sq_isbool(*o)) { return _integer(*o); @@ -187,16 +211,24 @@ SQBool sq_objtobool(HSQOBJECT *o) return SQFalse; } +SQUserPointer sq_objtouserpointer(const HSQOBJECT *o) +{ + if(sq_isuserpointer(*o)) { + return _userpointer(*o); + } + return 0; +} + void sq_pushnull(HSQUIRRELVM v) { - v->Push(_null_); + v->PushNull(); } void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len) { if(s) v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len))); - else v->Push(_null_); + else v->PushNull(); } void sq_pushinteger(HSQUIRRELVM v,SQInteger n) @@ -223,17 +255,22 @@ SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size) { SQUserData *ud = SQUserData::Create(_ss(v), size); v->Push(ud); - return ud->_val; + return (SQUserPointer)sq_aligning(ud + 1); } void sq_newtable(HSQUIRRELVM v) { - v->Push(SQTable::Create(_ss(v), 0)); + v->Push(SQTable::Create(_ss(v), 0)); +} + +void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity) +{ + v->Push(SQTable::Create(_ss(v), initialcapacity)); } void sq_newarray(HSQUIRRELVM v,SQInteger size) { - v->Push(SQArray::Create(_ss(v), size)); + v->Push(SQArray::Create(_ss(v), size)); } SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase) @@ -247,7 +284,7 @@ SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase) } SQClass *newclass = SQClass::Create(_ss(v), baseclass); if(baseclass) v->Pop(); - v->Push(newclass); + v->Push(newclass); return SQ_OK; } @@ -266,7 +303,7 @@ SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx) SQObjectPtr *arr; _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); _array(*arr)->Append(v->GetUp(-1)); - v->Pop(1); + v->Pop(); return SQ_OK; } @@ -318,15 +355,15 @@ SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx) SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx) { - sq_aux_paramscheck(v, 1); + sq_aux_paramscheck(v, 1); SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); } SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos) { - sq_aux_paramscheck(v, 1); + sq_aux_paramscheck(v, 1); SQObjectPtr *arr; _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); @@ -334,26 +371,32 @@ SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos) return ret; } - void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars) { - SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func); + SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars); nc->_nparamscheck = 0; for(SQUnsignedInteger i = 0; i < nfreevars; i++) { - nc->_outervalues.push_back(v->Top()); + nc->_outervalues[i] = v->Top(); v->Pop(); } - v->Push(SQObjectPtr(nc)); + v->Push(SQObjectPtr(nc)); } SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars) { SQObject o = stack_get(v, idx); - if(sq_isclosure(o)) { + if(type(o) == OT_CLOSURE) { SQClosure *c = _closure(o); - SQFunctionProto *proto = _funcproto(c->_function); + SQFunctionProto *proto = c->_function; *nparams = (SQUnsignedInteger)proto->_nparameters; - *nfreevars = (SQUnsignedInteger)c->_outervalues.size(); + *nfreevars = (SQUnsignedInteger)proto->_noutervalues; + return SQ_OK; + } + else if(type(o) == OT_NATIVECLOSURE) + { + SQNativeClosure *c = _nativeclosure(o); + *nparams = (SQUnsignedInteger)c->_nparamscheck; + *nfreevars = c->_noutervalues; return SQ_OK; } return sq_throwerror(v,_SC("the object is not a closure")); @@ -403,16 +446,24 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx) !sq_isclass(env) && !sq_isinstance(env)) return sq_throwerror(v,_SC("invalid environment")); - SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env)); + SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env)); SQObjectPtr ret; if(sq_isclosure(o)) { SQClosure *c = _closure(o)->Clone(); + __ObjRelease(c->_env); c->_env = w; + __ObjAddRef(c->_env); + if(_closure(o)->_base) { + c->_base = _closure(o)->_base; + __ObjAddRef(c->_base); + } ret = c; } else { //then must be a native closure SQNativeClosure *c = _nativeclosure(o)->Clone(); + __ObjRelease(c->_env); c->_env = w; + __ObjAddRef(c->_env); ret = c; } v->Pop(); @@ -420,6 +471,22 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx) return SQ_OK; } +SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + if(!sq_isnativeclosure(o) && + !sq_isclosure(o)) + return sq_throwerror(v,_SC("the target is not a closure")); + if(sq_isnativeclosure(o)) + { + v->Push(_nativeclosure(o)->_name); + } + else { //closure + v->Push(_closure(o)->_function->_name); + } + return SQ_OK; +} + SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx) { SQObject &o=stack_get(v,idx); @@ -491,19 +558,32 @@ SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx) return type(stack_get(v, idx)); } +SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + SQObjectPtr res; + if(!v->TypeOf(o,res)) { + return SQ_ERROR; + } + v->Push(res); + return SQ_OK; +} -void sq_tostring(HSQUIRRELVM v,SQInteger idx) +SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &o = stack_get(v, idx); SQObjectPtr res; - v->ToString(o,res); + if(!v->ToString(o,res)) { + return SQ_ERROR; + } v->Push(res); + return SQ_OK; } void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b) { SQObjectPtr &o = stack_get(v, idx); - *b = v->IsFalse(o)?SQFalse:SQTrue; + *b = SQVM::IsFalse(o)?SQFalse:SQTrue; } SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i) @@ -555,10 +635,10 @@ SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread) SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &o = stack_get(v,idx); - v->Push(_null_); + v->PushNull(); if(!v->Clone(o, stack_get(v, -1))){ v->Pop(); - return sq_aux_invalidtype(v, type(o)); + return SQ_ERROR; } return SQ_OK; } @@ -579,6 +659,12 @@ SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx) } } +SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + return HashObj(o); +} + SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag) { SQObjectPtr *o = NULL; @@ -599,7 +685,7 @@ SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag) return SQ_OK; } -SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag) +SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag) { switch(type(*o)) { case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break; @@ -722,27 +808,31 @@ SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); SQObjectPtr res; if(!v->DeleteSlot(*self, key, res)){ + v->Pop(); return SQ_ERROR; } if(pushval) v->GetUp(-1) = res; - else v->Pop(1); + else v->Pop(); return SQ_OK; } SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self = stack_get(v, idx); - if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { + if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) { v->Pop(2); return SQ_OK; } - v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; + return SQ_ERROR; } SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self = stack_get(v, idx); - if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(type(v->GetUp(-2)) == OT_NULL) { + v->Pop(2); + return sq_throwerror(v, _SC("null key")); + } switch(type(self)) { case OT_TABLE: _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1)); @@ -773,6 +863,26 @@ SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx) v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; } +SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic) +{ + SQObjectPtr &self = stack_get(v, idx); + if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); + if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false)) + return SQ_ERROR; + return SQ_OK; +} + +SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic) +{ + SQObjectPtr &self = stack_get(v, idx); + if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes")); + if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true)) + return SQ_ERROR; + return SQ_OK; +} + SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self = stack_get(v, idx); @@ -810,12 +920,10 @@ SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) if(_table(*self)->Get(key,t)) { _table(*self)->Remove(key); } - // C::B patch: Put brackets around inner if(...) - if(pushval != 0) { - if(pushval) v->GetUp(-1) = t; - } + if(pushval != 0) + v->GetUp(-1) = t; else - v->Pop(1); + v->Pop(); return SQ_OK; } @@ -826,7 +934,7 @@ SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx) case OT_TABLE: case OT_USERDATA: if(!_delegable(self)->_delegate){ - v->Push(_null_); + v->PushNull(); break; } v->Push(SQObjectPtr(_delegable(self)->_delegate)); @@ -834,16 +942,16 @@ SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx) default: return sq_throwerror(v,_SC("wrong type")); break; } return SQ_OK; - + } SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr &self=stack_get(v,idx); - if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) + if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,DONT_FALL_BACK)) return SQ_OK; - v->Pop(1); - return sq_throwerror(v,_SC("the index doesn't exist")); + v->Pop(); + return SQ_ERROR; } SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx) @@ -862,15 +970,24 @@ SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx) if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1))) return SQ_OK; break; - case OT_ARRAY: - if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) - return SQ_OK; + case OT_ARRAY:{ + SQObjectPtr& key = v->GetUp(-1); + if(sq_isnumeric(key)){ + if(_array(self)->Get(tointeger(key),v->GetUp(-1))) { + return SQ_OK; + } + } + else { + v->Pop(); + return sq_throwerror(v,_SC("invalid index type for an array")); + } + } break; default: - v->Pop(1); + v->Pop(); return sq_throwerror(v,_SC("rawget works only on array/table/instance and class")); - } - v->Pop(1); + } + v->Pop(); return sq_throwerror(v,_SC("the index doesn't exist")); } @@ -894,9 +1011,9 @@ const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedIntege if(type(ci._closure)!=OT_CLOSURE) return NULL; SQClosure *c=_closure(ci._closure); - SQFunctionProto *func=_funcproto(c->_function); + SQFunctionProto *func=c->_function; if(func->_noutervalues > (SQInteger)idx) { - v->Push(c->_outervalues[idx]); + v->Push(*_outer(c->_outervalues[idx])->_valptr); return _stringval(func->_outervalues[idx]._name); } idx -= func->_noutervalues; @@ -918,12 +1035,20 @@ void sq_resetobject(HSQOBJECT *po) SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err) { v->_lasterror=SQString::Create(_ss(v),err); - return -1; + return SQ_ERROR; +} + +SQRESULT sq_throwobject(HSQUIRRELVM v) +{ + v->_lasterror = v->GetUp(-1); + v->Pop(); + return SQ_ERROR; } + void sq_reseterror(HSQUIRRELVM v) { - v->_lasterror = _null_; + v->_lasterror.Null(); } void sq_getlasterror(HSQUIRRELVM v) @@ -931,18 +1056,22 @@ void sq_getlasterror(HSQUIRRELVM v) v->Push(v->_lasterror); } -void sq_reservestack(HSQUIRRELVM v,SQInteger nsize) +SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize) { if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) { + if(v->_nmetamethodscall) { + return sq_throwerror(v,_SC("cannot resize stack while in a metamethod")); + } v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size())); } + return SQ_OK; } SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror) { if(type(v->GetUp(-1))==OT_GENERATOR){ - v->Push(_null_); //retval - if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR)) + v->PushNull(); //retval + if(!v->Execute(v->GetUp(-2),0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR)) {v->Raise_Error(v->_lasterror); return SQ_ERROR;} if(!retval) v->Pop(); @@ -955,6 +1084,7 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror) { SQObjectPtr res; if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){ + if(!v->_suspended) { v->Pop(params);//pop closure and args } @@ -982,14 +1112,16 @@ SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseer SQObjectPtr ret; if(!v->_suspended) return sq_throwerror(v,_SC("cannot resume a vm that is not running any code")); + SQInteger target = v->_suspended_target; if(wakeupret) { - v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval + if(target != -1) { + v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval + } v->Pop(); - } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_; - if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) + } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); } + SQObjectPtr dummy; + if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) { return SQ_ERROR; - if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) { - while (v->_top > 1) v->_stack[--v->_top] = _null_; } if(retval) v->Push(ret); @@ -1019,6 +1151,8 @@ SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up) SQObjectPtr *o = NULL; _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); unsigned short tag = SQ_BYTECODE_STREAM_TAG; + if(_closure(*o)->_function->_noutervalues) + return sq_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized")); if(w(up,&tag,2) != 2) return sq_throwerror(v,_SC("io error")); if(!_closure(*o)->Save(v,up,w)) @@ -1029,7 +1163,7 @@ SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up) SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up) { SQObjectPtr closure; - + unsigned short tag; if(r(up,&tag,2) != 2) return sq_throwerror(v,_SC("io error")); @@ -1046,6 +1180,16 @@ SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize) return _ss(v)->GetScratchPad(minsize); } +SQRESULT sq_resurrectunreachable(HSQUIRRELVM v) +{ +#ifndef NO_GARBAGE_COLLECTOR + _ss(v)->ResurrectUnreachable(v); + return SQ_OK; +#else + return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build")); +#endif +} + SQInteger sq_collectgarbage(HSQUIRRELVM v) { #ifndef NO_GARBAGE_COLLECTOR @@ -1055,17 +1199,41 @@ SQInteger sq_collectgarbage(HSQUIRRELVM v) #endif } +SQRESULT sq_getcallee(HSQUIRRELVM v) +{ + if(v->_callsstacksize > 1) + { + v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); + return SQ_OK; + } + return sq_throwerror(v,_SC("no closure in the calls stack")); +} + const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) { - SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr &self=stack_get(v,idx); const SQChar *name = NULL; - if(type(self) == OT_CLOSURE) { - if(_closure(self)->_outervalues.size()>nval) { - v->Push(_closure(self)->_outervalues[nval]); - SQFunctionProto *fp = _funcproto(_closure(self)->_function); + switch(type(self)) + { + case OT_CLOSURE:{ + SQClosure *clo = _closure(self); + SQFunctionProto *fp = clo->_function; + if(((SQUnsignedInteger)fp->_noutervalues) > nval) { + v->Push(*(_outer(clo->_outervalues[nval])->_valptr)); SQOuterVar &ov = fp->_outervalues[nval]; name = _stringval(ov._name); } + } + break; + case OT_NATIVECLOSURE:{ + SQNativeClosure *clo = _nativeclosure(self); + if(clo->_noutervalues > nval) { + v->Push(clo->_outervalues[nval]); + name = _SC("@NATIVE"); + } + } + break; + default: break; //shutup compiler } return name; } @@ -1075,22 +1243,24 @@ SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) SQObjectPtr &self=stack_get(v,idx); switch(type(self)) { - case OT_CLOSURE: - if(_closure(self)->_outervalues.size()>nval){ - _closure(self)->_outervalues[nval]=stack_get(v,-1); + case OT_CLOSURE:{ + SQFunctionProto *fp = _closure(self)->_function; + if(((SQUnsignedInteger)fp->_noutervalues) > nval){ + *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1); } else return sq_throwerror(v,_SC("invalid free var index")); + } break; case OT_NATIVECLOSURE: - if(_nativeclosure(self)->_outervalues.size()>nval){ - _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1); + if(_nativeclosure(self)->_noutervalues > nval){ + _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1); } else return sq_throwerror(v,_SC("invalid free var index")); break; default: return sq_aux_invalidtype(v,type(self)); } - v->Pop(1); + v->Pop(); return SQ_OK; } @@ -1125,7 +1295,7 @@ SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) if(type(key) == OT_NULL) { attrs = _class(*o)->_attributes; v->Pop(); - v->Push(attrs); + v->Push(attrs); return SQ_OK; } else if(_class(*o)->GetAttributes(key,attrs)) { @@ -1136,6 +1306,77 @@ SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) return sq_throwerror(v,_SC("wrong index")); } +SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-1); + SQTable *m = _class(*o)->_members; + SQObjectPtr val; + if(m->Get(key,val)) { + handle->_static = _isfield(val) ? SQFalse : SQTrue; + handle->_index = _member_idx(val); + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); +} + +SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val) +{ + switch(type(self)) { + case OT_INSTANCE: { + SQInstance *i = _instance(self); + if(handle->_static) { + SQClass *c = i->_class; + val = &c->_methods[handle->_index].val; + } + else { + val = &i->_values[handle->_index]; + + } + } + break; + case OT_CLASS: { + SQClass *c = _class(self); + if(handle->_static) { + val = &c->_methods[handle->_index].val; + } + else { + val = &c->_defaultvalues[handle->_index].val; + } + } + break; + default: + return sq_throwerror(v,_SC("wrong type(expected class or instance)")); + } + return SQ_OK; +} + +SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle) +{ + SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr *val = NULL; + if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { + return SQ_ERROR; + } + v->Push(_realval(*val)); + return SQ_OK; +} + +SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle) +{ + SQObjectPtr &self = stack_get(v,idx); + SQObjectPtr &newval = stack_get(v,-1); + SQObjectPtr *val = NULL; + if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) { + return SQ_ERROR; + } + *val = newval; + v->Pop(); + return SQ_OK; +} + SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) { SQObjectPtr *o = NULL; @@ -1143,7 +1384,7 @@ SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) if(_class(*o)->_base) v->Push(SQObjectPtr(_class(*o)->_base)); else - v->Push(_null_); + v->PushNull(); return SQ_OK; } @@ -1246,9 +1487,10 @@ void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx) dest->Push(stack_get(src,idx)); } -void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc) +void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc) { _ss(v)->_printfunc = printfunc; + _ss(v)->_errorfunc = errfunc; } SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v) @@ -1256,6 +1498,11 @@ SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v) return _ss(v)->_printfunc; } +SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v) +{ + return _ss(v)->_errorfunc; +} + void *sq_malloc(SQUnsignedInteger size) { return SQ_MALLOC(size); diff --git a/src/sdk/scripting/squirrel/sqbaselib.cpp b/src/sdk/scripting/squirrel/sqbaselib.cpp index 8b8fc28f76..4b87e93c71 100644 --- a/src/sdk/scripting/squirrel/sqbaselib.cpp +++ b/src/sdk/scripting/squirrel/sqbaselib.cpp @@ -16,22 +16,31 @@ bool str2num(const SQChar *s,SQObjectPtr &res) { SQChar *end; - if(scstrstr(s,_SC("."))){ + const SQChar *e = s; + SQBool isfloat = SQFalse; + SQChar c; + while((c = *e) != _SC('\0')) + { + if(c == _SC('.') || c == _SC('E')|| c == _SC('e')) { //e and E is for scientific notation + isfloat = SQTrue; + break; + } + e++; + } + if(isfloat){ SQFloat r = SQFloat(scstrtod(s,&end)); if(s == end) return false; res = r; - return true; } else{ SQInteger r = SQInteger(scstrtol(s,&end,10)); if(s == end) return false; res = r; - return true; } + return true; } -// C::B patch: Make the compiler happy by commenting unused variables -static SQInteger base_dummy(HSQUIRRELVM /*v*/) +static SQInteger base_dummy(HSQUIRRELVM v) { return 0; } @@ -42,6 +51,11 @@ static SQInteger base_collectgarbage(HSQUIRRELVM v) sq_pushinteger(v, sq_collectgarbage(v)); return 1; } +static SQInteger base_resurectureachable(HSQUIRRELVM v) +{ + sq_resurrectunreachable(v); + return 1; +} #endif static SQInteger base_getroottable(HSQUIRRELVM v) @@ -59,7 +73,7 @@ static SQInteger base_getconsttable(HSQUIRRELVM v) static SQInteger base_setroottable(HSQUIRRELVM v) { - SQObjectPtr &o=stack_get(v,2); + SQObjectPtr o = v->_roottable; if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR; v->Push(o); return 1; @@ -67,7 +81,7 @@ static SQInteger base_setroottable(HSQUIRRELVM v) static SQInteger base_setconsttable(HSQUIRRELVM v) { - SQObjectPtr &o=stack_get(v,2); + SQObjectPtr o = _ss(v)->_consts; if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR; v->Push(o); return 1; @@ -88,17 +102,17 @@ static SQInteger base_setdebughook(HSQUIRRELVM v) static SQInteger base_enabledebuginfo(HSQUIRRELVM v) { SQObjectPtr &o=stack_get(v,2); - sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0); + + sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue); return 0; } -static SQInteger base_getstackinfos(HSQUIRRELVM v) +static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level) { - SQInteger level; SQStackInfos si; SQInteger seq = 0; const SQChar *name = NULL; - sq_getinteger(v, -1, &level); + if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) { const SQChar *fn = _SC("unknown"); @@ -108,33 +122,39 @@ static SQInteger base_getstackinfos(HSQUIRRELVM v) sq_newtable(v); sq_pushstring(v, _SC("func"), -1); sq_pushstring(v, fn, -1); - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); sq_pushstring(v, _SC("src"), -1); sq_pushstring(v, src, -1); - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); sq_pushstring(v, _SC("line"), -1); sq_pushinteger(v, si.line); - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); sq_pushstring(v, _SC("locals"), -1); sq_newtable(v); seq=0; while ((name = sq_getlocal(v, level, seq))) { sq_pushstring(v, name, -1); sq_push(v, -2); - sq_createslot(v, -4); + sq_newslot(v, -4, SQFalse); sq_pop(v, 1); seq++; } - sq_createslot(v, -3); + sq_newslot(v, -3, SQFalse); return 1; } return 0; } +static SQInteger base_getstackinfos(HSQUIRRELVM v) +{ + SQInteger level; + sq_getinteger(v, -1, &level); + return __getcallstackinfos(v,level); +} static SQInteger base_assert(HSQUIRRELVM v) { - if(v->IsFalse(stack_get(v,2))){ + if(SQVM::IsFalse(stack_get(v,2))){ return sq_throwerror(v,_SC("assertion failed")); } return 0; @@ -171,6 +191,15 @@ static SQInteger base_print(HSQUIRRELVM v) return 0; } +static SQInteger base_error(HSQUIRRELVM v) +{ + const SQChar *str; + sq_tostring(v,2); + sq_getstring(v,-1,&str); + if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str); + return 0; +} + static SQInteger base_compilestring(HSQUIRRELVM v) { SQInteger nargs=sq_gettop(v); @@ -190,7 +219,7 @@ static SQInteger base_compilestring(HSQUIRRELVM v) static SQInteger base_newthread(HSQUIRRELVM v) { SQObjectPtr &func = stack_get(v,2); - SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2; + SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2; HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize); sq_move(newv,v,-2); return 1; @@ -223,6 +252,16 @@ static SQInteger base_type(HSQUIRRELVM v) return 1; } +static SQInteger base_callee(HSQUIRRELVM v) +{ + if(v->_callsstacksize > 1) + { + v->Push(v->_callsstack[v->_callsstacksize - 2]._closure); + return 1; + } + return sq_throwerror(v,_SC("no closure in the calls stack")); +} + static SQRegFunction base_funcs[]={ //generic {_SC("seterrorhandler"),base_seterrorhandler,2, NULL}, @@ -235,14 +274,17 @@ static SQRegFunction base_funcs[]={ {_SC("setconsttable"),base_setconsttable,2, NULL}, {_SC("assert"),base_assert,2, NULL}, {_SC("print"),base_print,2, NULL}, + {_SC("error"),base_error,2, NULL}, {_SC("compilestring"),base_compilestring,-2, _SC(".ss")}, {_SC("newthread"),base_newthread,2, _SC(".c")}, {_SC("suspend"),base_suspend,-1, NULL}, {_SC("array"),base_array,-2, _SC(".n")}, {_SC("type"),base_type,2, NULL}, + {_SC("callee"),base_callee,0,NULL}, {_SC("dummy"),base_dummy,0,NULL}, #ifndef NO_GARBAGE_COLLECTOR - {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")}, + {_SC("collectgarbage"),base_collectgarbage,0, NULL}, + {_SC("resurrectunreachable"),base_resurectureachable,0, NULL}, #endif {0,0} }; @@ -256,21 +298,25 @@ void sq_base_register(HSQUIRRELVM v) sq_newclosure(v,base_funcs[i].f,0); sq_setnativeclosurename(v,-1,base_funcs[i].name); sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); i++; } + + sq_pushstring(v,_SC("_versionnumber_"),-1); + sq_pushinteger(v,SQUIRREL_VERSION_NUMBER); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_version_"),-1); sq_pushstring(v,SQUIRREL_VERSION,-1); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_charsize_"),-1); sq_pushinteger(v,sizeof(SQChar)); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_intsize_"),-1); sq_pushinteger(v,sizeof(SQInteger)); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pushstring(v,_SC("_floatsize_"),-1); sq_pushinteger(v,sizeof(SQFloat)); - sq_createslot(v,-3); + sq_newslot(v,-3, SQFalse); sq_pop(v,1); } @@ -299,7 +345,7 @@ static SQInteger default_delegate_tofloat(HSQUIRRELVM v) v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0))); break; default: - v->Push(_null_); + v->PushNull(); break; } return 1; @@ -324,7 +370,7 @@ static SQInteger default_delegate_tointeger(HSQUIRRELVM v) v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0)); break; default: - v->Push(_null_); + v->PushNull(); break; } return 1; @@ -357,6 +403,7 @@ static SQInteger number_delegate_tochar(HSQUIRRELVM v) } + ///////////////////////////////////////////////////////////////// //TABLE DEFAULT DELEGATE @@ -378,27 +425,41 @@ static SQInteger container_rawexists(HSQUIRRELVM v) return 1; } -static SQInteger table_rawset(HSQUIRRELVM v) +static SQInteger container_rawset(HSQUIRRELVM v) { return sq_rawset(v,-3); } -static SQInteger table_rawget(HSQUIRRELVM v) +static SQInteger container_rawget(HSQUIRRELVM v) { return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR; } +static SQInteger table_setdelegate(HSQUIRRELVM v) +{ + if(SQ_FAILED(sq_setdelegate(v,-2))) + return SQ_ERROR; + sq_push(v,-1); // -1 because sq_setdelegate pops 1 + return 1; +} + +static SQInteger table_getdelegate(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR; +} SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ {_SC("len"),default_delegate_len,1, _SC("t")}, - {_SC("rawget"),table_rawget,2, _SC("t")}, - {_SC("rawset"),table_rawset,3, _SC("t")}, + {_SC("rawget"),container_rawget,2, _SC("t")}, + {_SC("rawset"),container_rawset,3, _SC("t")}, {_SC("rawdelete"),table_rawdelete,2, _SC("t")}, {_SC("rawin"),container_rawexists,2, _SC("t")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {_SC("clear"),obj_clear,1, _SC(".")}, + {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")}, + {_SC("getdelegate"),table_getdelegate,1, _SC(".")}, {0,0} }; @@ -473,6 +534,111 @@ static SQInteger array_resize(HSQUIRRELVM v) return sq_throwerror(v, _SC("size must be a number")); } +static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) { + SQObjectPtr temp; + SQInteger size = src->Size(); + for(SQInteger n = 0; n < size; n++) { + src->Get(n,temp); + v->Push(src); + v->Push(temp); + if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) { + return SQ_ERROR; + } + dest->Set(n,v->GetUp(-1)); + v->Pop(); + } + return 0; +} + +static SQInteger array_map(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQInteger size = _array(o)->Size(); + SQObjectPtr ret = SQArray::Create(_ss(v),size); + if(SQ_FAILED(__map_array(_array(ret),_array(o),v))) + return SQ_ERROR; + v->Push(ret); + return 1; +} + +static SQInteger array_apply(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + if(SQ_FAILED(__map_array(_array(o),_array(o),v))) + return SQ_ERROR; + return 0; +} + +static SQInteger array_reduce(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQArray *a = _array(o); + SQInteger size = a->Size(); + if(size == 0) { + return 0; + } + SQObjectPtr res; + a->Get(0,res); + if(size > 1) { + SQObjectPtr other; + for(SQInteger n = 1; n < size; n++) { + a->Get(n,other); + v->Push(o); + v->Push(res); + v->Push(other); + if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { + return SQ_ERROR; + } + res = v->GetUp(-1); + v->Pop(); + } + } + v->Push(res); + return 1; +} + +static SQInteger array_filter(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQArray *a = _array(o); + SQObjectPtr ret = SQArray::Create(_ss(v),0); + SQInteger size = a->Size(); + SQObjectPtr val; + for(SQInteger n = 0; n < size; n++) { + a->Get(n,val); + v->Push(o); + v->Push(n); + v->Push(val); + if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) { + return SQ_ERROR; + } + if(!SQVM::IsFalse(v->GetUp(-1))) { + _array(ret)->Append(val); + } + v->Pop(); + } + v->Push(ret); + return 1; +} + +static SQInteger array_find(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v,1); + SQObjectPtr &val = stack_get(v,2); + SQArray *a = _array(o); + SQInteger size = a->Size(); + SQObjectPtr temp; + for(SQInteger n = 0; n < size; n++) { + bool res = false; + a->Get(n,temp); + if(SQVM::IsEqual(temp,val,res) && res) { + v->Push(n); + return 1; + } + } + return 0; +} + bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret) { @@ -486,7 +652,7 @@ bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQ v->Push(a); v->Push(b); if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { - if(!sq_isstring( v->_lasterror)) + if(!sq_isstring( v->_lasterror)) v->Raise_Error(_SC("compare func failed")); return false; } @@ -500,7 +666,7 @@ bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQ return true; } -bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, int root, int bottom, SQInteger func) +bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func) { SQInteger maxChild; SQInteger done = 0; @@ -525,6 +691,11 @@ bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, int root, int bottom, SQIntege if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret)) return false; if (ret < 0) { + if (root == maxChild) { + v->Raise_Error(_SC("inconsistent compare function")); + return false; // We'd be swapping ourselve. The compare function is incorrect + } + _Swap(arr->_values[root],arr->_values[maxChild]); root = maxChild; } @@ -584,7 +755,7 @@ static SQInteger array_slice(HSQUIRRELVM v) } v->Push(arr); return 1; - + } SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ @@ -603,6 +774,11 @@ SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {_SC("clear"),obj_clear,1, _SC(".")}, + {_SC("map"),array_map,2, _SC("ac")}, + {_SC("apply"),array_apply,2, _SC("ac")}, + {_SC("reduce"),array_reduce,2, _SC("ac")}, + {_SC("filter"),array_filter,2, _SC("ac")}, + {_SC("find"),array_find,2, _SC("a.")}, {0,0} }; @@ -718,12 +894,16 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) { SQObject o = stack_get(v,1); SQTable *res = SQTable::Create(_ss(v),4); if(type(o) == OT_CLOSURE) { - SQFunctionProto *f = _funcproto(_closure(o)->_function); + SQFunctionProto *f = _closure(o)->_function; SQInteger nparams = f->_nparameters + (f->_varparams?1:0); SQObjectPtr params = SQArray::Create(_ss(v),nparams); + SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams); for(SQInteger n = 0; n_nparameters; n++) { _array(params)->Set((SQInteger)n,f->_parameters[n]); } + for(SQInteger j = 0; j_ndefaultparams; j++) { + _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]); + } if(f->_varparams) { _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1)); } @@ -732,8 +912,9 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) { res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename); res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params); res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams); + res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams); } - else { //OT_NATIVECLOSURE + else { //OT_NATIVECLOSURE SQNativeClosure *nc = _nativeclosure(o); res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true); res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name); @@ -753,6 +934,7 @@ static SQInteger closure_getinfos(HSQUIRRELVM v) { } + SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={ {_SC("call"),closure_call,-1, _SC("c")}, {_SC("pcall"),closure_pcall,-1, _SC("c")}, @@ -785,17 +967,15 @@ SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={ }; //THREAD DEFAULT DELEGATE - static SQInteger thread_call(HSQUIRRELVM v) { - SQObjectPtr o = stack_get(v,1); if(type(o) == OT_THREAD) { SQInteger nparams = sq_gettop(v); _thread(o)->Push(_thread(o)->_roottable); for(SQInteger i = 2; i<(nparams+1); i++) sq_move(_thread(o),v,i); - if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) { + if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) { sq_move(v,_thread(o),-1); sq_pop(_thread(o),1); return 1; @@ -822,7 +1002,7 @@ static SQInteger thread_wakeup(HSQUIRRELVM v) break; } } - + SQInteger wakeupret = sq_gettop(v)>1?1:0; if(wakeupret) { sq_move(thread,v,2); @@ -861,46 +1041,117 @@ static SQInteger thread_getstatus(HSQUIRRELVM v) return 1; } +static SQInteger thread_getstackinfos(HSQUIRRELVM v) +{ + SQObjectPtr o = stack_get(v,1); + if(type(o) == OT_THREAD) { + SQVM *thread = _thread(o); + SQInteger threadtop = sq_gettop(thread); + SQInteger level; + sq_getinteger(v,-1,&level); + SQRESULT res = __getcallstackinfos(thread,level); + if(SQ_FAILED(res)) + { + sq_settop(thread,threadtop); + if(type(thread->_lasterror) == OT_STRING) { + sq_throwerror(v,_stringval(thread->_lasterror)); + } + else { + sq_throwerror(v,_SC("unknown error")); + } + } + if(res > 0) { + //some result + sq_move(v,thread,-1); + sq_settop(thread,threadtop); + return 1; + } + //no result + sq_settop(thread,threadtop); + return 0; + + } + return sq_throwerror(v,_SC("wrong parameter")); +} + SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = { {_SC("call"), thread_call, -1, _SC("v")}, {_SC("wakeup"), thread_wakeup, -1, _SC("v")}, {_SC("getstatus"), thread_getstatus, 1, _SC("v")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")}, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {0,0}, }; static SQInteger class_getattributes(HSQUIRRELVM v) { - if(SQ_SUCCEEDED(sq_getattributes(v,-2))) - return 1; - return SQ_ERROR; + return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR; } static SQInteger class_setattributes(HSQUIRRELVM v) { - if(SQ_SUCCEEDED(sq_setattributes(v,-3))) - return 1; - return SQ_ERROR; + return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR; } static SQInteger class_instance(HSQUIRRELVM v) { - if(SQ_SUCCEEDED(sq_createinstance(v,-1))) - return 1; - return SQ_ERROR; + return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR; +} + +static SQInteger class_getbase(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR; +} + +static SQInteger class_newmember(HSQUIRRELVM v) +{ + SQInteger top = sq_gettop(v); + SQBool bstatic = SQFalse; + if(top == 5) + { + sq_tobool(v,-1,&bstatic); + sq_pop(v,1); + } + + if(top < 4) { + sq_pushnull(v); + } + return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR; +} + +static SQInteger class_rawnewmember(HSQUIRRELVM v) +{ + SQInteger top = sq_gettop(v); + SQBool bstatic = SQFalse; + if(top == 5) + { + sq_tobool(v,-1,&bstatic); + sq_pop(v,1); + } + + if(top < 4) { + sq_pushnull(v); + } + return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR; } SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { {_SC("getattributes"), class_getattributes, 2, _SC("y.")}, {_SC("setattributes"), class_setattributes, 3, _SC("y..")}, + {_SC("rawget"),container_rawget,2, _SC("y")}, + {_SC("rawset"),container_rawset,3, _SC("y")}, {_SC("rawin"),container_rawexists,2, _SC("y")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, {_SC("instance"),class_instance,1, _SC("y")}, + {_SC("getbase"),class_getbase,1, _SC("y")}, + {_SC("newmember"),class_newmember,-3, _SC("y")}, + {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")}, {0,0} }; + static SQInteger instance_getclass(HSQUIRRELVM v) { if(SQ_SUCCEEDED(sq_getclass(v,1))) @@ -910,6 +1161,8 @@ static SQInteger instance_getclass(HSQUIRRELVM v) SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { {_SC("getclass"), instance_getclass, 1, _SC("x")}, + {_SC("rawget"),container_rawget,2, _SC("x")}, + {_SC("rawset"),container_rawset,3, _SC("x")}, {_SC("rawin"),container_rawexists,2, _SC("x")}, {_SC("weakref"),obj_delegate_weakref,1, NULL }, {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, @@ -930,4 +1183,3 @@ SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = { {0,0} }; - diff --git a/src/sdk/scripting/squirrel/sqclass.cpp b/src/sdk/scripting/squirrel/sqclass.cpp index 700efd6217..dcee77d708 100644 --- a/src/sdk/scripting/squirrel/sqclass.cpp +++ b/src/sdk/scripting/squirrel/sqclass.cpp @@ -5,33 +5,39 @@ #include "sqvm.h" #include "sqtable.h" #include "sqclass.h" +#include "sqfuncproto.h" #include "sqclosure.h" + + SQClass::SQClass(SQSharedState *ss,SQClass *base) { _base = base; _typetag = 0; _hook = NULL; _udsize = 0; - _metamethods.resize(MT_LAST); //size it to max size + _locked = false; + _constructoridx = -1; if(_base) { + _constructoridx = _base->_constructoridx; + _udsize = _base->_udsize; _defaultvalues.copy(base->_defaultvalues); _methods.copy(base->_methods); - _metamethods.copy(base->_metamethods); + _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST); __ObjAddRef(_base); } _members = base?base->_members->Clone() : SQTable::Create(ss,0); __ObjAddRef(_members); - _locked = false; + INIT_CHAIN(); ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); } -void SQClass::Finalize() { - _attributes = _null_; +void SQClass::Finalize() { + _attributes.Null(); _defaultvalues.resize(0); _methods.resize(0); - _metamethods.resize(0); + _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST); __ObjRelease(_members); if(_base) { __ObjRelease(_base); @@ -47,28 +53,40 @@ SQClass::~SQClass() bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) { SQObjectPtr temp; - if(_locked) + bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic; + if(_locked && !belongs_to_static_table) return false; //the class already has an instance so cannot be modified if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value { _defaultvalues[_member_idx(temp)].val = val; return true; } - if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) { + if(belongs_to_static_table) { SQInteger mmidx; - if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && + if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) { _metamethods[mmidx] = val; - } + } else { + SQObjectPtr theval = val; + if(_base && type(val) == OT_CLOSURE) { + theval = _closure(val)->Clone(); + _closure(theval)->_base = _base; + __ObjAddRef(_base); //ref for the closure + } if(type(temp) == OT_NULL) { + bool isconstructor; + SQVM::IsEqual(ss->_constructoridx, key, isconstructor); + if(isconstructor) { + _constructoridx = (SQInteger)_methods.size(); + } SQClassMember m; - m.val = val; + m.val = theval; _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size()))); _methods.push_back(m); } else { - _methods[_member_idx(temp)].val = val; + _methods[_member_idx(temp)].val = theval; } } return true; @@ -158,13 +176,14 @@ SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize) Init(ss); } -void SQInstance::Finalize() +void SQInstance::Finalize() { SQUnsignedInteger nvalues = _class->_defaultvalues.size(); __ObjRelease(_class); - for(SQUnsignedInteger i = 0; i < nvalues; i++) { - _values[i] = _null_; - } + _NULL_SQOBJECT_VECTOR(_values,nvalues); + //for(SQUnsignedInteger i = 0; i < nvalues; i++) { +// _values[i].Null(); +// } } SQInstance::~SQInstance() @@ -173,8 +192,7 @@ SQInstance::~SQInstance() if(_class){ Finalize(); } //if _class is null it was already finalized by the GC } -// C::B patch: Make the compiler happy by commenting unused variables -bool SQInstance::GetMetaMethod(SQVM * /*v*/,SQMetaMethod mm,SQObjectPtr &res) +bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) { if(type(_class->_metamethods[mm]) != OT_NULL) { res = _class->_metamethods[mm]; diff --git a/src/sdk/scripting/squirrel/sqcompiler.cpp b/src/sdk/scripting/squirrel/sqcompiler.cpp index 7a1a6fb413..d210724148 100644 --- a/src/sdk/scripting/squirrel/sqcompiler.cpp +++ b/src/sdk/scripting/squirrel/sqcompiler.cpp @@ -2,6 +2,7 @@ see copyright notice in squirrel.h */ #include "sqpcheader.h" +#ifndef NO_COMPILER #include #include #include "sqopcodes.h" @@ -13,27 +14,48 @@ #include "sqvm.h" #include "sqtable.h" -#define DEREF_NO_DEREF -1 -#define DEREF_FIELD -2 +#define EXPR 1 +#define OBJECT 2 +#define BASE 3 +#define LOCAL 4 +#define OUTER 5 -struct ExpState -{ - ExpState() - { - _deref = DEREF_NO_DEREF; - _freevar = false; - _class_or_delete = false; - _funcarg = false; - } - bool _class_or_delete; - bool _funcarg; - bool _freevar; - SQInteger _deref; +struct SQExpState { + SQInteger etype; /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */ + SQInteger epos; /* expr. location on stack; -1 for OBJECT and BASE */ + bool donot_get; /* signal not to deref the next value */ +}; + +struct SQScope { + SQInteger outers; + SQInteger stacksize; }; -typedef sqvector ExpStateVec; +#define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \ + _scope.outers = _fs->_outers; \ + _scope.stacksize = _fs->GetStackSize(); + +#define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \ + if(_fs->CountOuters(_scope.stacksize)) { \ + _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ + } \ + } + +#define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \ + _fs->SetStackSize(_scope.stacksize); \ + } \ + _scope = __oldscope__; \ + } -#define _exst (_expstates.top()) +#define END_SCOPE() { SQInteger oldouters = _fs->_outers;\ + if(_fs->GetStackSize() != _scope.stacksize) { \ + _fs->SetStackSize(_scope.stacksize); \ + if(oldouters != _fs->_outers) { \ + _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \ + } \ + } \ + _scope = __oldscope__; \ + } #define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \ SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \ @@ -54,6 +76,8 @@ class SQCompiler _lex.Init(_ss(v), rg, up,ThrowError,this); _sourcename = SQString::Create(_ss(v), sourcename); _lineinfo = lineinfo;_raiseerror = raiseerror; + _scope.outers = 0; + _scope.stacksize = 0; compilererror = NULL; } static void ThrowError(void *ud, const SQChar *s) { @@ -71,27 +95,11 @@ class SQCompiler longjmp(_errorjmp,1); } void Lex(){ _token = _lex.Lex();} - void PushExpState(){ _expstates.push_back(ExpState()); } - bool IsDerefToken(SQInteger tok) - { - switch(tok){ - case _SC('='): case _SC('('): case TK_NEWSLOT: - case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true; - } - return false; - } - ExpState PopExpState() - { - ExpState ret = _expstates.top(); - _expstates.pop_back(); - return ret; - } SQObject Expect(SQInteger tok) { - + if(_token != tok) { if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) { - //ret = SQString::Create(_ss(_vm),_SC("constructor")); //do nothing } else { @@ -162,15 +170,17 @@ class SQCompiler funcstate._name = SQString::Create(_ss(_vm), _SC("main")); _fs = &funcstate; _fs->AddParameter(_fs->CreateString(_SC("this"))); + _fs->AddParameter(_fs->CreateString(_SC("vargv"))); + _fs->_varparams = true; _fs->_sourcename = _sourcename; SQInteger stacksize = _fs->GetStackSize(); if(setjmp(_errorjmp) == 0) { Lex(); while(_token > 0){ Statement(); - if(_lex._prevtoken != _SC('}')) OptionalSemicolon(); + if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); } - CleanStack(stacksize); + _fs->SetStackSize(stacksize); _fs->AddLineInfos(_lex._currentline, _lineinfo, true); _fs->AddInstruction(_OP_RETURN, 0xFF); _fs->SetStackSize(0); @@ -196,7 +206,7 @@ class SQCompiler if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); } } - void Statement() + void Statement(bool closeframe = true) { _fs->AddLineInfos(_lex._currentline, _lineinfo); switch(_token){ @@ -213,7 +223,6 @@ class SQCompiler SQOpcode op; if(_token == TK_RETURN) { op = _OP_RETURN; - } else { op = _OP_YIELD; @@ -226,13 +235,13 @@ class SQCompiler if(op == _OP_RETURN && _fs->_traps > 0) _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0); _fs->_returnexp = retexp; - _fs->AddInstruction(op, 1, _fs->PopTarget()); + _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize()); } - else{ + else{ if(op == _OP_RETURN && _fs->_traps > 0) _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0); _fs->_returnexp = -1; - _fs->AddInstruction(op, 0xFF); + _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize()); } break;} case TK_BREAK: @@ -240,6 +249,7 @@ class SQCompiler if(_fs->_breaktargets.top() > 0){ _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0); } + RESOLVE_OUTERS(); _fs->AddInstruction(_OP_JMP, 0, -1234); _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos()); Lex(); @@ -249,6 +259,7 @@ class SQCompiler if(_fs->_continuetargets.top() > 0) { _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0); } + RESOLVE_OUTERS(); _fs->AddInstruction(_OP_JMP, 0, -1234); _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos()); Lex(); @@ -263,11 +274,16 @@ class SQCompiler EnumStatement(); break; case _SC('{'):{ - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Lex(); Statements(); Expect(_SC('}')); - _fs->SetStackSize(stacksize); + if(closeframe) { + END_SCOPE(); + } + else { + END_SCOPE_NO_CLOSE(); + } } break; case TK_TRY: @@ -286,14 +302,15 @@ class SQCompiler SQObject val = ExpectScalar(); OptionalSemicolon(); SQTable *enums = _table(_ss(_vm)->_consts); - SQObjectPtr strongid = id; + SQObjectPtr strongid = id; enums->NewSlot(strongid,SQObjectPtr(val)); strongid.Null(); } break; default: CommaExpr(); - _fs->PopTarget(); + _fs->DiscardTarget(); + //_fs->PopTarget(); break; } _fs->SnoozeOpt(); @@ -311,38 +328,49 @@ class SQCompiler SQInteger p1 = _fs->PopTarget(); //key in OP_GET _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3); } - void EmitCompoundArith(SQInteger tok,bool deref) + void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos) { - SQInteger oper; - switch(tok){ - case TK_MINUSEQ: oper = '-'; break; - case TK_PLUSEQ: oper = '+'; break; - case TK_MULEQ: oper = '*'; break; - case TK_DIVEQ: oper = '/'; break; - case TK_MODEQ: oper = '%'; break; - default: oper = 0; //shut up compiler - assert(0); break; - }; - if(deref) { - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger src = _fs->PopTarget(); - //mixes dest obj and source val in the arg1(hack?) - _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper); - } - else { - Emit2ArgsOP(_OP_COMPARITHL, oper); + /* Generate code depending on the expression type */ + switch(etype) { + case LOCAL:{ + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->PopTarget(); //key in OP_GET + _fs->PushTarget(p1); + //EmitCompArithLocal(tok, p1, p1, p2); + _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0); + } + break; + case OBJECT: + case BASE: + { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + /* _OP_COMPARITH mixes dest obj and source val in the arg1 */ + _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok)); + } + break; + case OUTER: + { + SQInteger val = _fs->TopTarget(); + SQInteger tmp = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp, pos); + _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0); + _fs->AddInstruction(_OP_SETOUTER, tmp, pos, tmp); + } + break; } } void CommaExpr() { for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr()); } - ExpState Expression(bool funcarg = false) + void Expression() { - PushExpState(); - _exst._class_or_delete = false; - _exst._funcarg = funcarg; + SQExpState es = _es; + _es.etype = EXPR; + _es.epos = -1; + _es.donot_get = false; LogicalOrExp(); switch(_token) { case _SC('='): @@ -351,40 +379,49 @@ class SQCompiler case TK_PLUSEQ: case TK_MULEQ: case TK_DIVEQ: - case TK_MODEQ: - { - SQInteger op = _token; - SQInteger ds = _exst._deref; - bool freevar = _exst._freevar; - if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression")); - Lex(); Expression(); + case TK_MODEQ:{ + SQInteger op = _token; + SQInteger ds = _es.etype; + SQInteger pos = _es.epos; + if(ds == EXPR) Error(_SC("can't assign expression")); + Lex(); Expression(); - switch(op){ - case TK_NEWSLOT: - if(freevar) Error(_SC("free variables cannot be modified")); - if(ds == DEREF_FIELD) - EmitDerefOp(_OP_NEWSLOT); - else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - Error(_SC("can't 'create' a local slot")); - break; - case _SC('='): //ASSIGN - if(freevar) Error(_SC("free variables cannot be modified")); - if(ds == DEREF_FIELD) - EmitDerefOp(_OP_SET); - else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - SQInteger p2 = _fs->PopTarget(); //src in OP_GET - SQInteger p1 = _fs->TopTarget(); //key in OP_GET - _fs->AddInstruction(_OP_MOVE, p1, p2); + switch(op){ + case TK_NEWSLOT: + if(ds == OBJECT || ds == BASE) + EmitDerefOp(_OP_NEWSLOT); + else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + Error(_SC("can't 'create' a local slot")); + break; + case _SC('='): //ASSIGN + switch(ds) { + case LOCAL: + { + SQInteger src = _fs->PopTarget(); + SQInteger dst = _fs->TopTarget(); + _fs->AddInstruction(_OP_MOVE, dst, src); } break; - case TK_MINUSEQ: - case TK_PLUSEQ: - case TK_MULEQ: - case TK_DIVEQ: - case TK_MODEQ: - EmitCompoundArith(op,ds == DEREF_FIELD); + case OBJECT: + case BASE: + EmitDerefOp(_OP_SET); break; + case OUTER: + { + SQInteger src = _fs->PopTarget(); + SQInteger dst = _fs->PushTarget(); + _fs->AddInstruction(_OP_SETOUTER, dst, pos, src); + } } + break; + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ: + EmitCompoundArith(op, ds, pos); + break; + } } break; case _SC('?'): { @@ -408,9 +445,9 @@ class SQCompiler } break; } - return PopExpState(); + _es = es; } - void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0) + template void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0) { Lex(); (this->*f)(); SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget(); @@ -474,22 +511,30 @@ class SQCompiler } void BitwiseAndExp() { - CompExp(); + EqExp(); for(;;) if(_token == _SC('&')) - {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND); + {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND); }else return; } + void EqExp() + { + CompExp(); + for(;;) switch(_token) { + case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break; + case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break; + case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break; + default: return; + } + } void CompExp() { ShiftExp(); for(;;) switch(_token) { - case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break; case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break; case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break; case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break; case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break; - case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break; - default: return; + default: return; } } void ShiftExp() @@ -499,25 +544,51 @@ class SQCompiler case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break; case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break; case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break; - default: return; + default: return; } } + SQOpcode ChooseArithOpByToken(SQInteger tok) + { + switch(tok) { + case TK_PLUSEQ: case '+': return _OP_ADD; + case TK_MINUSEQ: case '-': return _OP_SUB; + case TK_MULEQ: case '*': return _OP_MUL; + case TK_DIVEQ: case '/': return _OP_DIV; + case TK_MODEQ: case '%': return _OP_MOD; + default: assert(0); + } + return _OP_ADD; + } + SQInteger ChooseCompArithCharByToken(SQInteger tok) + { + SQInteger oper; + switch(tok){ + case TK_MINUSEQ: oper = '-'; break; + case TK_PLUSEQ: oper = '+'; break; + case TK_MULEQ: oper = '*'; break; + case TK_DIVEQ: oper = '/'; break; + case TK_MODEQ: oper = '%'; break; + default: oper = 0; //shut up compiler + assert(0); break; + }; + return oper; + } void PlusExp() { MultExp(); for(;;) switch(_token) { case _SC('+'): case _SC('-'): - BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break; + BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break; default: return; } } - + void MultExp() { PrefixedExpr(); for(;;) switch(_token) { case _SC('*'): case _SC('/'): case _SC('%'): - BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break; + BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break; default: return; } } @@ -527,66 +598,95 @@ class SQCompiler SQInteger pos = Factor(); for(;;) { switch(_token) { - case _SC('.'): { + case _SC('.'): pos = -1; - Lex(); - if(_token == TK_PARENT) { - Lex(); - if(!NeedGet()) - Error(_SC("parent cannot be set")); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src); + Lex(); + + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + if(_es.etype==BASE) { + Emit2ArgsOP(_OP_GET); + pos = _fs->TopTarget(); + _es.etype = EXPR; + _es.epos = pos; } else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - if(NeedGet()) Emit2ArgsOP(_OP_GET); - } - _exst._deref = DEREF_FIELD; - _exst._freevar = false; + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; } break; case _SC('['): if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration")); - Lex(); Expression(); Expect(_SC(']')); + Lex(); Expression(); Expect(_SC(']')); pos = -1; - if(NeedGet()) Emit2ArgsOP(_OP_GET); - _exst._deref = DEREF_FIELD; - _exst._freevar = false; + if(_es.etype==BASE) { + Emit2ArgsOP(_OP_GET); + pos = _fs->TopTarget(); + _es.etype = EXPR; + _es.epos = pos; + } + else { + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; + } break; case TK_MINUSMINUS: case TK_PLUSPLUS: - if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { - SQInteger tok = _token; Lex(); - if(pos < 0) - Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1); - else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1); - } - - } - return; - break; - case _SC('('): { - if(_exst._deref != DEREF_NO_DEREF) { - if(pos<0) { - SQInteger key = _fs->PopTarget(); //key - SQInteger table = _fs->PopTarget(); //table etc... - SQInteger closure = _fs->PushTarget(); - SQInteger ttarget = _fs->PushTarget(); - _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); + if(IsEndOfStatement()) return; + SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1; + Lex(); + switch(_es.etype) + { + case EXPR: Error(_SC("can't '++' or '--' an expression")); break; + case OBJECT: + case BASE: + Emit2ArgsOP(_OP_PINC, diff); + break; + case LOCAL: { + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff); + } + break; + case OUTER: { + SQInteger tmp1 = _fs->PushTarget(); + SQInteger tmp2 = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos); + _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff); + _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2); + _fs->PopTarget(); + } } - else{ + } + return; + break; + case _SC('('): + switch(_es.etype) { + case OBJECT: { + SQInteger key = _fs->PopTarget(); /* location of the key */ + SQInteger table = _fs->PopTarget(); /* location of the object */ + SQInteger closure = _fs->PushTarget(); /* location for the closure */ + SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */ + _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); + } + break; + case BASE: + //Emit2ArgsOP(_OP_GET); + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + break; + case OUTER: + _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos); + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + break; + default: _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - } } - else - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - _exst._deref = DEREF_NO_DEREF; + _es.etype = EXPR; Lex(); FunctionCallArgs(); - } break; default: return; } @@ -594,185 +694,211 @@ class SQCompiler } SQInteger Factor() { - _exst._deref = DEREF_NO_DEREF; + _es.etype = EXPR; switch(_token) { - case TK_STRING_LITERAL: { - //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1)); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); - Lex(); - } + case TK_STRING_LITERAL: + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); + Lex(); break; - case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break; - case TK_VARGV: { Lex(); - Expect(_SC('[')); - Expression(); - Expect(_SC(']')); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src); - } + case TK_BASE: + Lex(); + _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget()); + _es.etype = BASE; + _es.epos = _fs->TopTarget(); + return (_es.epos); break; case TK_IDENTIFIER: case TK_CONSTRUCTOR: case TK_THIS:{ - _exst._freevar = false; - SQObject id; - SQObject constant; + SQObject id; + SQObject constant; + switch(_token) { - case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; - case TK_THIS: id = _fs->CreateString(_SC("this")); break; + case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; + case TK_THIS: id = _fs->CreateString(_SC("this")); break; case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break; } + SQInteger pos = -1; Lex(); - if((pos = _fs->GetLocalVariable(id)) == -1) { - //checks if is a free variable - if((pos = _fs->GetOuterVariable(id)) != -1) { - _exst._deref = _fs->PushTarget(); - _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos); - _exst._freevar = true; - } - else if(_fs->IsConstant(id,constant)) { //line 634 - SQObjectPtr constval; - SQObject constid; - if(type(constant) == OT_TABLE) { - Expect('.'); constid = Expect(TK_IDENTIFIER); - if(!_table(constant)->Get(constid,constval)) { - constval.Null(); - Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid)); - } - } - else { - constval = constant; - } - _exst._deref = _fs->PushTarget(); - SQObjectType ctype = type(constval); - if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) { - _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval)); - } - else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) { - SQFloat f = _float(constval); - _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f)); - } - else { - _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval)); - } + if((pos = _fs->GetLocalVariable(id)) != -1) { + /* Handle a local variable (includes 'this') */ + _fs->PushTarget(pos); + _es.etype = LOCAL; + _es.epos = pos; + } - _exst._freevar = true; + else if((pos = _fs->GetOuterVariable(id)) != -1) { + /* Handle a free var */ + if(NeedGet()) { + _es.epos = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos); + /* _es.etype = EXPR; already default value */ } else { - _fs->PushTarget(0); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(NeedGet()) Emit2ArgsOP(_OP_GET); - _exst._deref = DEREF_FIELD; + _es.etype = OUTER; + _es.epos = pos; } } - else{ - _fs->PushTarget(pos); - _exst._deref = pos; + else if(_fs->IsConstant(id, constant)) { + /* Handle named constant */ + SQObjectPtr constval; + SQObject constid; + if(type(constant) == OT_TABLE) { + Expect('.'); + constid = Expect(TK_IDENTIFIER); + if(!_table(constant)->Get(constid, constval)) { + constval.Null(); + Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid)); + } + } + else { + constval = constant; + } + _es.epos = _fs->PushTarget(); + + /* generate direct or literal function depending on size */ + SQObjectType ctype = type(constval); + switch(ctype) { + case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break; + case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break; + default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break; + } + _es.etype = EXPR; + } + else { + /* Handle a non-local variable, aka a field. Push the 'this' pointer on + * the virtual stack (always found in offset 0, so no instruction needs to + * be generated), and push the key next. Generate an _OP_LOAD instruction + * for the latter. If we are not using the variable as a dref expr, generate + * the _OP_GET instruction. + */ + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(NeedGet()) { + Emit2ArgsOP(_OP_GET); + } + _es.etype = OBJECT; } - return _exst._deref; + return _es.epos; } break; - case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break; case TK_DOUBLE_COLON: // "::" - _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget()); - _exst._deref = DEREF_FIELD; - _token = _SC('.'); //hack - return -1; + _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget()); + _es.etype = OBJECT; + _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/ + _es.epos = -1; + return _es.epos; break; - case TK_NULL: + case TK_NULL: _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); Lex(); break; - case TK_INTEGER: { - if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits? - _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue); - } - else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue)); - } - Lex(); - } - break; - case TK_FLOAT: - if(sizeof(SQFloat) == sizeof(SQInt32)) { - _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue)); - } - else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue)); - } - Lex(); - break; + case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break; + case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break; case TK_TRUE: case TK_FALSE: _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0); Lex(); break; case _SC('['): { - _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget()); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY); SQInteger apos = _fs->GetCurrentPos(),key = 0; Lex(); while(_token != _SC(']')) { - Expression(); + Expression(); if(_token == _SC(',')) Lex(); SQInteger val = _fs->PopTarget(); SQInteger array = _fs->TopTarget(); - _fs->AddInstruction(_OP_APPENDARRAY, array, val); + _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK); key++; } _fs->SetIntructionParam(apos, 1, key); Lex(); } break; - case _SC('{'):{ - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); - Lex();ParseTableOrClass(_SC(',')); - } + case _SC('{'): + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); + Lex();ParseTableOrClass(_SC(','),_SC('}')); break; case TK_FUNCTION: FunctionExp(_token);break; + case _SC('@'): FunctionExp(_token,true);break; case TK_CLASS: Lex(); ClassExp();break; - case _SC('-'): UnaryOP(_OP_NEG); break; - case _SC('!'): UnaryOP(_OP_NOT); break; - case _SC('~'): UnaryOP(_OP_BWNOT); break; - case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break; - case TK_RESUME : UnaryOP(_OP_RESUME); break; - case TK_CLONE : UnaryOP(_OP_CLONE); break; - case TK_MINUSMINUS : + case _SC('-'): + Lex(); + switch(_token) { + case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break; + case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break; + default: UnaryOP(_OP_NEG); + } + break; + case _SC('!'): Lex(); UnaryOP(_OP_NOT); break; + case _SC('~'): + Lex(); + if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; } + UnaryOP(_OP_BWNOT); + break; + case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break; + case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break; + case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break; + case TK_MINUSMINUS : case TK_PLUSPLUS :PrefixIncDec(_token); break; case TK_DELETE : DeleteExpr(); break; - case TK_DELEGATE : DelegateExpr(); break; case _SC('('): Lex(); CommaExpr(); Expect(_SC(')')); break; default: Error(_SC("expression expected")); } return -1; } + void EmitLoadConstInt(SQInteger value,SQInteger target) + { + if(target < 0) { + target = _fs->PushTarget(); + } + if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits? + _fs->AddInstruction(_OP_LOADINT, target,value); + } + else { + _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); + } + } + void EmitLoadConstFloat(SQFloat value,SQInteger target) + { + if(target < 0) { + target = _fs->PushTarget(); + } + if(sizeof(SQFloat) == sizeof(SQInt32)) { + _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value)); + } + else { + _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value)); + } + } void UnaryOP(SQOpcode op) { - Lex(); PrefixedExpr(); + PrefixedExpr(); SQInteger src = _fs->PopTarget(); _fs->AddInstruction(op, _fs->PushTarget(), src); } bool NeedGet() { switch(_token) { - case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS: - case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ: + case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ: + case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return false; } - return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('['))); + return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('[')))); } - void FunctionCallArgs() { SQInteger nargs = 1;//this while(_token != _SC(')')) { - Expression(true); + Expression(); MoveIfCurrentTargetIsLocal(); - nargs++; - if(_token == _SC(',')){ - Lex(); + nargs++; + if(_token == _SC(',')){ + Lex(); if(_token == ')') Error(_SC("expression expected, found ')'")); } } @@ -782,17 +908,16 @@ class SQCompiler SQInteger closure = _fs->PopTarget(); _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs); } - void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}') + void ParseTableOrClass(SQInteger separator,SQInteger terminator) { SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0; - while(_token != terminator) { bool hasattrs = false; bool isstatic = false; //check if is an attribute if(separator == ';') { if(_token == TK_ATTR_OPEN) { - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex(); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex(); ParseTableOrClass(',',TK_ATTR_CLOSE); hasattrs = true; } @@ -802,38 +927,45 @@ class SQCompiler } } switch(_token) { - case TK_FUNCTION: - case TK_CONSTRUCTOR:{ - SQInteger tk = _token; - Lex(); - SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); - Expect(_SC('(')); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - CreateFunction(id); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); - } - break; - case _SC('['): - Lex(); CommaExpr(); Expect(_SC(']')); - Expect(_SC('=')); Expression(); + case TK_FUNCTION: + case TK_CONSTRUCTOR:{ + SQInteger tk = _token; + Lex(); + SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); + Expect(_SC('(')); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + } + break; + case _SC('['): + Lex(); CommaExpr(); Expect(_SC(']')); + Expect(_SC('=')); Expression(); + break; + case TK_STRING_LITERAL: //JSON + if(separator == ',') { //only works for tables + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL))); + Expect(_SC(':')); Expression(); break; - default : - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - Expect(_SC('=')); Expression(); + } + default : + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + Expect(_SC('=')); Expression(); } - if(_token == separator) Lex();//optional comma/semicolon nkeys++; SQInteger val = _fs->PopTarget(); SQInteger key = _fs->PopTarget(); SQInteger attrs = hasattrs ? _fs->PopTarget():-1; - // C::B patch: Eliminate compiler warnings assert((hasattrs && (attrs == key-1)) || !hasattrs); - // C::B patch: Eliminate compiler warnings - int flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); + unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); SQInteger table = _fs->TopTarget(); //<AddInstruction(_OP_NEWSLOTA, flags, table, key, val); - //_fs->PopTarget(); + if(separator == _SC(',')) { //hack recognizes a table from the separator + _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val); + } + else { + _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember + } } if(separator == _SC(',')) //hack recognizes a table from the separator _fs->SetIntructionParam(tpos, 1, nkeys); @@ -842,8 +974,20 @@ class SQCompiler void LocalDeclStatement() { SQObject varname; + Lex(); + if( _token == TK_FUNCTION) { + Lex(); + varname = Expect(TK_IDENTIFIER); + Expect(_SC('(')); + CreateFunction(varname,false); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + _fs->PopTarget(); + _fs->PushLocalVariable(varname); + return; + } + do { - Lex(); varname = Expect(TK_IDENTIFIER); + varname = Expect(TK_IDENTIFIER); if(_token == _SC('=')) { Lex(); Expression(); SQInteger src = _fs->PopTarget(); @@ -855,8 +999,8 @@ class SQCompiler } _fs->PopTarget(); _fs->PushLocalVariable(varname); - - } while(_token == _SC(',')); + if(_token == _SC(',')) Lex(); else break; + } while(1); } void IfStatement() { @@ -865,22 +1009,22 @@ class SQCompiler Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); SQInteger jnepos = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); - + BEGIN_SCOPE(); + Statement(); // if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon(); - - CleanStack(stacksize); + + END_SCOPE(); SQInteger endifblock = _fs->GetCurrentPos(); if(_token == TK_ELSE){ haselse = true; - stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); _fs->AddInstruction(_OP_JMP); jmppos = _fs->GetCurrentPos(); Lex(); Statement(); OptionalSemicolon(); - CleanStack(stacksize); + END_SCOPE(); _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); } _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0)); @@ -888,41 +1032,41 @@ class SQCompiler void WhileStatement() { SQInteger jzpos, jmppos; - SQInteger stacksize = _fs->GetStackSize(); jmppos = _fs->GetCurrentPos(); Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - + BEGIN_BREAKBLE_BLOCK(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); - stacksize = _fs->GetStackSize(); - + BEGIN_SCOPE(); + Statement(); - - CleanStack(stacksize); + + END_SCOPE(); _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - + END_BREAKBLE_BLOCK(jmppos); } void DoWhileStatement() { Lex(); - SQInteger jzpos = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); + SQInteger jmptrg = _fs->GetCurrentPos(); BEGIN_BREAKBLE_BLOCK() + BEGIN_SCOPE(); Statement(); - CleanStack(stacksize); + END_SCOPE(); Expect(TK_WHILE); SQInteger continuetrg = _fs->GetCurrentPos(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1); + _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1); END_BREAKBLE_BLOCK(continuetrg); } void ForStatement() { Lex(); - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Expect(_SC('(')); if(_token == TK_LOCAL) LocalDeclStatement(); else if(_token != _SC(';')){ @@ -960,8 +1104,8 @@ class SQCompiler } _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0); if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - CleanStack(stacksize); - + END_SCOPE(); + END_BREAKBLE_BLOCK(continuetrg); } void ForEachStatement() @@ -976,9 +1120,9 @@ class SQCompiler idxname = _fs->CreateString(_SC("@INDEX@")); } Expect(TK_IN); - + //save the stack size - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); //put the table in the stack(evaluate the table expression) Expression(); Expect(_SC(')')); SQInteger container = _fs->TopTarget(); @@ -1001,9 +1145,10 @@ class SQCompiler _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos); _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos); - //restore the local variable stack(remove index,val and ref idx) - CleanStack(stacksize); END_BREAKBLE_BLOCK(foreachpos - 1); + //restore the local variable stack(remove index,val and ref idx) + _fs->PopTarget(); + END_SCOPE(); } void SwitchStatement() { @@ -1016,7 +1161,6 @@ class SQCompiler SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size(); _fs->_breaktargets.push_back(0); while(_token == TK_CASE) { - //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one if(!bfirst) { _fs->AddInstruction(_OP_JMP, 0, 0); skipcondjmp = _fs->GetCurrentPos(); @@ -1032,26 +1176,24 @@ class SQCompiler _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp)); } tonextcondjmp = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Statements(); - _fs->SetStackSize(stacksize); + END_SCOPE(); bfirst = false; } if(tonextcondjmp != -1) _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); if(_token == TK_DEFAULT) { - // _fs->AddLineInfos(_lex._currentline, _lineinfo); Lex(); Expect(_SC(':')); - SQInteger stacksize = _fs->GetStackSize(); + BEGIN_SCOPE(); Statements(); - _fs->SetStackSize(stacksize); + END_SCOPE(); } Expect(_SC('}')); _fs->PopTarget(); __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__; if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__); _fs->_breaktargets.pop_back(); - } void FunctionStatement() { @@ -1060,7 +1202,7 @@ class SQCompiler _fs->PushTarget(0); _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); - + while(_token == TK_DOUBLE_COLON) { Lex(); id = Expect(TK_IDENTIFIER); @@ -1075,23 +1217,28 @@ class SQCompiler } void ClassStatement() { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; + SQExpState es; + Lex(); + es = _es; + _es.donot_get = true; PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name")); - if(es._deref == DEREF_FIELD) { + if(_es.etype == EXPR) { + Error(_SC("invalid class name")); + } + else if(_es.etype == OBJECT || _es.etype == BASE) { ClassExp(); EmitDerefOp(_OP_NEWSLOT); _fs->PopTarget(); } - else Error(_SC("cannot create a class in a local with the syntax(class )")); + else { + Error(_SC("cannot create a class in a local with the syntax(class )")); + } + _es = es; } SQObject ExpectScalar() { SQObject val; + val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x switch(_token) { case TK_INTEGER: val._type = OT_INTEGER; @@ -1121,18 +1268,17 @@ class SQCompiler } break; default: - Error(_SC("scalar expected : integer,float or string")); + Error(_SC("scalar expected : integer,float or string")); } Lex(); return val; } void EnumStatement() { - - Lex(); + Lex(); SQObject id = Expect(TK_IDENTIFIER); Expect(_SC('{')); - + SQObject table = _fs->CreateTable(); SQInteger nval = 0; while(_token != _SC('}')) { @@ -1150,16 +1296,10 @@ class SQCompiler if(_token == ',') Lex(); } SQTable *enums = _table(_ss(_vm)->_consts); - SQObjectPtr strongid = id; - /*SQObjectPtr dummy; - if(enums->Get(strongid,dummy)) { - dummy.Null(); strongid.Null(); - Error(_SC("enumeration already exists")); - }*/ + SQObjectPtr strongid = id; enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table)); strongid.Null(); Lex(); - } void TryCatchStatement() { @@ -1170,7 +1310,11 @@ class SQCompiler if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++; if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++; SQInteger trappos = _fs->GetCurrentPos(); - Statement(); + { + BEGIN_SCOPE(); + Statement(); + END_SCOPE(); + } _fs->_traps--; _fs->AddInstruction(_OP_POPTRAP, 1, 0); if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--; @@ -1179,17 +1323,20 @@ class SQCompiler SQInteger jmppos = _fs->GetCurrentPos(); _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos)); Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')')); - SQInteger stacksize = _fs->GetStackSize(); - SQInteger ex_target = _fs->PushLocalVariable(exid); - _fs->SetIntructionParam(trappos, 0, ex_target); - Statement(); - _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); - CleanStack(stacksize); + { + BEGIN_SCOPE(); + SQInteger ex_target = _fs->PushLocalVariable(exid); + _fs->SetIntructionParam(trappos, 0, ex_target); + Statement(); + _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); + END_SCOPE(); + } } - void FunctionExp(SQInteger ftype) + void FunctionExp(SQInteger ftype,bool lambda = false) { Lex(); Expect(_SC('(')); - CreateFunction(_null_); + SQObjectPtr dummy; + CreateFunction(dummy,lambda); _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1); } void ClassExp() @@ -1202,53 +1349,61 @@ class SQCompiler } if(_token == TK_ATTR_OPEN) { Lex(); - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); ParseTableOrClass(_SC(','),TK_ATTR_CLOSE); attrs = _fs->TopTarget(); } Expect(_SC('{')); if(attrs != -1) _fs->PopTarget(); if(base != -1) _fs->PopTarget(); - _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs); - ParseTableOrClass(_SC(';')); - } - void DelegateExpr() - { - Lex(); CommaExpr(); - Expect(_SC(':')); - CommaExpr(); - SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget(); - _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate); + _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS); + ParseTableOrClass(_SC(';'),_SC('}')); } void DeleteExpr() { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; + SQExpState es; + Lex(); + es = _es; + _es.donot_get = true; PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression")); - if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE); - else Error(_SC("cannot delete a local")); + if(_es.etype==EXPR) Error(_SC("can't delete an expression")); + if(_es.etype==OBJECT || _es.etype==BASE) { + Emit2ArgsOP(_OP_DELETE); + } + else { + Error(_SC("cannot delete an (outer) local")); + } + _es = es; } void PrefixIncDec(SQInteger token) { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; + SQExpState es; + SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1; + Lex(); + es = _es; + _es.donot_get = true; PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1); - else { - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1); + if(_es.etype==EXPR) { + Error(_SC("can't '++' or '--' an expression")); } + else if(_es.etype==OBJECT || _es.etype==BASE) { + Emit2ArgsOP(_OP_INC, diff); + } + else if(_es.etype==LOCAL) { + SQInteger src = _fs->TopTarget(); + _fs->AddInstruction(_OP_INCL, src, src, 0, diff); + + } + else if(_es.etype==OUTER) { + SQInteger tmp = _fs->PushTarget(); + _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos); + _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff); + _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp); + } + _es = es; } - void CreateFunction(SQObject &name) + void CreateFunction(SQObject &name,bool lambda = false) { - SQFuncState *funcstate = _fs->PushChildState(_ss(_vm)); funcstate->_name = name; SQObject paramname; @@ -1258,6 +1413,7 @@ class SQCompiler while(_token!=_SC(')')) { if(_token == TK_VARPARAMS) { if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters")); + funcstate->AddParameter(_fs->CreateString(_SC("vargv"))); funcstate->_varparams = true; Lex(); if(_token != _SC(')')) Error(_SC("expected ')'")); @@ -1266,7 +1422,7 @@ class SQCompiler else { paramname = Expect(TK_IDENTIFIER); funcstate->AddParameter(paramname); - if(_token == _SC('=')) { + if(_token == _SC('=')) { Lex(); Expression(); funcstate->AddDefaultParam(_fs->TopTarget()); @@ -1283,26 +1439,19 @@ class SQCompiler for(SQInteger n = 0; n < defparams; n++) { _fs->PopTarget(); } - //outer values - if(_token == _SC(':')) { - Lex(); Expect(_SC('(')); - while(_token != _SC(')')) { - paramname = Expect(TK_IDENTIFIER); - //outers are treated as implicit local variables - funcstate->AddOuterValue(paramname); - if(_token == _SC(',')) Lex(); - else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); - } - Lex(); - } - + SQFuncState *currchunk = _fs; _fs = funcstate; - Statement(); + if(lambda) { + Expression(); + _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());} + else { + Statement(false); + } funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true); funcstate->AddInstruction(_OP_RETURN, -1); funcstate->SetStackSize(0); - //_fs->->_stacksize = _fs->_stacksize; + SQFunctionProto *func = funcstate->BuildProto(); #ifdef _DEBUG_DUMP funcstate->Dump(func); @@ -1311,11 +1460,6 @@ class SQCompiler _fs->_functions.push_back(func); _fs->PopChildState(); } - void CleanStack(SQInteger stacksize) - { - if(_fs->GetStackSize() != stacksize) - _fs->SetStackSize(stacksize); - } void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve) { while(ntoresolve > 0) { @@ -1345,7 +1489,8 @@ class SQCompiler bool _raiseerror; SQInteger _debugline; SQInteger _debugop; - ExpStateVec _expstates; + SQExpState _es; + SQScope _scope; SQChar *compilererror; jmp_buf _errorjmp; SQVM *_vm; @@ -1356,3 +1501,5 @@ bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcena SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo); return p.Compile(out); } + +#endif diff --git a/src/sdk/scripting/squirrel/sqdbgserver.cpp b/src/sdk/scripting/squirrel/sqdbgserver.cpp new file mode 100644 index 0000000000..1f662fb8b7 --- /dev/null +++ b/src/sdk/scripting/squirrel/sqdbgserver.cpp @@ -0,0 +1,687 @@ +#include +#include +#include + +#include "sqrdbg.h" +#include "sqdbgserver.h" + +#include +#include +#include + +#ifndef _UNICODE +#define scstrcpy strcpy +#else +#define scstrcpy wcscpy +#endif +struct XMLEscape{ + const SQChar c; + const SQChar *esc; +}; + +#define SQDBG_DEBUG_HOOK _SC("_sqdbg_debug_hook_") +#define SQDBG_ERROR_HANDLER _SC("_sqdbg_error_handler_") + +XMLEscape g_escapes[]={ + {_SC('<'),_SC("<")},{'>',_SC(">")},{_SC('&'),_SC("&")},{_SC('\''),_SC("'")},{_SC('\"'),_SC(""")},{_SC('\n'),_SC(""n")},{_SC('\r'),_SC(""r")},{NULL,NULL} +}; + +const SQChar *IntToString(SQInteger n) +{ + static SQChar temp[256]; + scsprintf(temp,_SC("%d"),n); + return temp; +} + +const SQChar *PtrToString(void *p) +{ + static SQChar temp[256]; + scsprintf(temp,_SC("%p"),p); + return temp; +} + +SQInteger debug_hook(HSQUIRRELVM v); +SQInteger error_handler(HSQUIRRELVM v); + +SQInteger beginelement(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *name; + sq_getuserpointer(v,-1,&up); + SQDbgServer *self = (SQDbgServer*)up; + sq_getuserpointer(v,-1,&up); + sq_getstring(v,2,&name); + self->BeginElement(name); + return 0; +} + +SQInteger endelement(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *name; + sq_getuserpointer(v,-1,&up); + SQDbgServer *self = (SQDbgServer*)up; + sq_getuserpointer(v,-1,&up); + sq_getstring(v,2,&name); + self->EndElement(name); + return 0; +} + +SQInteger attribute(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *name,*value; + sq_getuserpointer(v,-1,&up); + SQDbgServer *self = (SQDbgServer*)up; + sq_getuserpointer(v,-1,&up); + sq_getstring(v,2,&name); + sq_getstring(v,3,&value); + self->Attribute(name,value); + return 0; +} + +SQDbgServer::SQDbgServer(HSQUIRRELVM v) +{ + _ready = false; + //_nestedcalls = 0; + _autoupdate = false; + _v = v; + _state = eDBG_Running; + _accept = INVALID_SOCKET; + _endpoint = INVALID_SOCKET; + //_maxrecursion = 10; + sq_resetobject(&_debugroot); +} + +SQDbgServer::~SQDbgServer() +{ + VMStateMap::iterator itr = _vmstate.begin(); + while(itr != _vmstate.end()) { + VMState *vs = itr->second; + delete vs; + ++itr; + } + _vmstate.clear(); + sq_pushobject(_v,_debugroot); + sq_clear(_v,-1); + sq_release(_v,&_debugroot); + if(_accept != INVALID_SOCKET) + sqdbg_closesocket(_accept); + if(_endpoint != INVALID_SOCKET) + sqdbg_closesocket(_endpoint); +} + +bool SQDbgServer::Init() +{ + //creates an environment table for the debugger + + sq_newtable(_v); + sq_getstackobj(_v,-1,&_debugroot); + sq_addref(_v,&_debugroot); + + //creates a emptyslot to store the watches + sq_pushstring(_v,_SC("watches"),-1); + sq_pushnull(_v); + sq_newslot(_v,-3, SQFalse); + + sq_pushstring(_v,_SC("beginelement"),-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,beginelement,1); + sq_setparamscheck(_v,2,_SC(".s")); + sq_newslot(_v,-3, SQFalse); + + sq_pushstring(_v,_SC("endelement"),-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,endelement,1); + sq_setparamscheck(_v,2,_SC(".s")); + sq_newslot(_v,-3, SQFalse); + + sq_pushstring(_v,_SC("attribute"),-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,attribute,1); + sq_setparamscheck(_v,3,_SC(".ss")); + sq_newslot(_v,-3, SQFalse); + + sq_pop(_v,1); + + //stores debug hook and error handler in the registry + sq_pushregistrytable(_v); + + sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,debug_hook,1); + sq_newslot(_v,-3, SQFalse); + + sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,error_handler,1); + sq_newslot(_v,-3, SQFalse); + + + sq_pop(_v,1); + + //sets the error handlers + SetErrorHandlers(_v); + return true; +} + +bool SQDbgServer::ReadMsg() +{ + return false; +} + +void SQDbgServer::BusyWait() +{ + while( !ReadMsg() ) + Sleep(0); +} + + + +void SQDbgServer::SendChunk(const SQChar *chunk) +{ + char *buf=NULL; + int buf_len=0; +#ifdef _UNICODE + buf_len=(int)scstrlen(chunk)+1; + buf=(char *)sq_getscratchpad(_v,(buf_len)*3); + //wcstombs((char *)buf,chunk,buf_len*3); + WideCharToMultiByte(CP_UTF8,0,chunk,-1,buf,buf_len*3,NULL,NULL); +#else + buf_len=(int)scstrlen(chunk); + buf=(char *)chunk; +#endif + send(_endpoint,(const char*)buf,(int)strlen((const char *)buf),0); +} + + +void SQDbgServer::Terminated() +{ + BeginElement(_SC("terminated")); + EndElement(_SC("terminated")); + ::Sleep(200); +} + +VMState *SQDbgServer::GetVMState(HSQUIRRELVM v) +{ + VMState *ret = NULL; + VMStateMap::iterator itr = _vmstate.find(v); + if(itr == _vmstate.end()) { + ret = new VMState(); + _vmstate.insert(VMStateMap::value_type(v,ret)); + } + else { + ret = itr->second; + } + return ret; +} + +void SQDbgServer::Hook(HSQUIRRELVM v,SQInteger type,SQInteger line,const SQChar *src,const SQChar *func) +{ + + VMState *vs = GetVMState(v); + switch(_state){ + case eDBG_Running: + if(type==_SC('l') && _breakpoints.size()) { + BreakPointSetItor itr = _breakpoints.find(BreakPoint(line,src)); + if(itr != _breakpoints.end()) { + Break(v,line,src,_SC("breakpoint")); + BreakExecution(); + } + } + break; + case eDBG_Suspended: + vs->_nestedcalls=0; + case eDBG_StepOver: + switch(type){ + case _SC('l'): + if(vs->_nestedcalls==0) { + Break(v,line,src,_SC("step")); + BreakExecution(); + } + break; + case _SC('c'): + vs->_nestedcalls++; + break; + case _SC('r'): + if(vs->_nestedcalls==0){ + vs->_nestedcalls=0; + + }else{ + vs->_nestedcalls--; + } + break; + } + break; + case eDBG_StepInto: + switch(type){ + case _SC('l'): + vs->_nestedcalls=0; + Break(v,line,src,_SC("step")); + BreakExecution(); + break; + + } + break; + case eDBG_StepReturn: + switch(type){ + case _SC('l'): + break; + case _SC('c'): + vs->_nestedcalls++; + break; + case _SC('r'): + if(vs->_nestedcalls==0){ + vs->_nestedcalls=0; + _state=eDBG_StepOver; + }else{ + vs->_nestedcalls--; + } + + break; + } + break; + case eDBG_Disabled: + break; + } +} + + +#define MSG_ID(x,y) ((y<<8)|x) +//ab Add Breakpoint +//rb Remove Breakpoint +//sp Suspend +void SQDbgServer::ParseMsg(const char *msg) +{ + + if(strlen(msg) == 0) + return; + + switch(*((unsigned short *)msg)){ + case MSG_ID('a','b'): { + BreakPoint bp; + if(ParseBreakpoint(msg+3,bp)){ + AddBreakpoint(bp); + scprintf(_SC("added bp %d %s\n"),bp._line,bp._src.c_str()); + } + else + scprintf(_SC("error parsing add breakpoint")); + } + break; + case MSG_ID('r','b'): { + BreakPoint bp; + if(ParseBreakpoint(msg+3,bp)){ + RemoveBreakpoint(bp); + scprintf(_SC("removed bp %d %s\n"),bp._line,bp._src.c_str()); + }else + scprintf(_SC("error parsing remove breakpoint")); + } + break; + case MSG_ID('g','o'): + if(_state!=eDBG_Running){ + _state=eDBG_Running; + BeginDocument(); + BeginElement(_SC("resumed")); + EndElement(_SC("resumed")); + EndDocument(); +// Send(_SC("\r\n")); + scprintf(_SC("go (execution resumed)\n")); + } + break; + case MSG_ID('s','p'): + if(_state!=eDBG_Suspended){ + _state=eDBG_Suspended; + scprintf(_SC("suspend\n")); + } + break; + case MSG_ID('s','o'): + if(_state==eDBG_Suspended){ + _state=eDBG_StepOver; + } + break; + case MSG_ID('s','i'): + if(_state==eDBG_Suspended){ + _state=eDBG_StepInto; + scprintf(_SC("step into\n")); + } + break; + case MSG_ID('s','r'): + if(_state==eDBG_Suspended){ + _state=eDBG_StepReturn; + scprintf(_SC("step return\n")); + } + break; + case MSG_ID('d','i'): + if(_state!=eDBG_Disabled){ + _state=eDBG_Disabled; + scprintf(_SC("disabled\n")); + } + break; + case MSG_ID('a','w'): { + Watch w; + if(ParseWatch(msg+3,w)) + { + AddWatch(w); + scprintf(_SC("added watch %d %s\n"),w._id,w._exp.c_str()); + /*if(_state == eDBG_Suspended) { + Break(_line,_src.c_str(),_break_type.c_str()); + }*/ + } + else + scprintf(_SC("error parsing add watch")); + } + break; + case MSG_ID('r','w'): { + SQInteger id; + if(ParseRemoveWatch(msg+3,id)) + { + RemoveWatch(id); + scprintf(_SC("added watch %d\n"),id); + } + else + scprintf(_SC("error parsing remove watch")); + } + break; + case MSG_ID('t','r'): + scprintf(_SC("terminate from user\n")); + exit(0); + break; + case MSG_ID('r','d'): + scprintf(_SC("ready\n")); + _ready=true; + break; + default: + scprintf(_SC("unknown packet")); + + } +} + +bool SQDbgServer::ParseBreakpoint(const char *msg,BreakPoint &out) +{ + static char stemp[MAX_BP_PATH]; + static SQChar desttemp[MAX_BP_PATH]; + char *ep=NULL; + out._line=strtoul(msg,&ep,16); + if(ep==msg || (*ep)!=':')return false; + + char *dest=stemp; + ep++; + while((*ep)!='\n' && (*ep)!='\0') + { + //*dest=tolower(*ep); + *dest=*ep; + *dest++;*ep++; + } + *dest='\0'; + *dest++; + *dest='\0'; +#ifdef _UNICODE + int len=(int)strlen(stemp); + SQChar *p = desttemp; + size_t destlen = mbstowcs(p,stemp,len); + p[destlen]=_SC('\0'); + out._src=p; +#else + out._src=stemp; +#endif + return true; +} + +bool SQDbgServer::ParseWatch(const char *msg,Watch &out) +{ + char *ep=NULL; + out._id=strtoul(msg,&ep,16); + if(ep==msg || (*ep)!=':')return false; + + //char *dest=out._src; + ep++; + while((*ep)!='\n' && (*ep)!='\0') + { + out._exp.append(1,*ep); + *ep++; + } + return true; +} + +bool SQDbgServer::ParseRemoveWatch(const char *msg,SQInteger &id) +{ + char *ep=NULL; + id=strtoul(msg,&ep,16); + if(ep==msg)return false; + return true; +} + + +void SQDbgServer::BreakExecution() +{ + _state=eDBG_Suspended; + while(_state==eDBG_Suspended){ + if(SQ_FAILED(sq_rdbg_update(this))) + exit(0); + Sleep(10); + } +} + +//COMMANDS +void SQDbgServer::AddBreakpoint(BreakPoint &bp) +{ + _breakpoints.insert(bp); + BeginDocument(); + BeginElement(_SC("addbreakpoint")); + Attribute(_SC("line"),IntToString(bp._line)); + Attribute(_SC("src"),bp._src.c_str()); + EndElement(_SC("addbreakpoint")); + EndDocument(); +} + +void SQDbgServer::AddWatch(Watch &w) +{ + _watches.insert(w); +} + +void SQDbgServer::RemoveWatch(SQInteger id) +{ + WatchSetItor itor=_watches.find(Watch(id,_SC(""))); + if(itor==_watches.end()){ + BeginDocument(); + BeginElement(_SC("error")); + Attribute(_SC("desc"),_SC("the watch does not exists")); + EndElement(_SC("error")); + EndDocument(); + } + else{ + _watches.erase(itor); + scprintf(_SC("removed watch %d\n"),id); + } +} + +void SQDbgServer::RemoveBreakpoint(BreakPoint &bp) +{ + BreakPointSetItor itor=_breakpoints.find(bp); + if(itor==_breakpoints.end()){ + BeginDocument(); + BeginElement(_SC("error")); + Attribute(_SC("desc"),_SC("the breakpoint doesn't exists")); + EndElement(_SC("error")); + EndDocument(); + } + else{ + BeginDocument(); + BeginElement(_SC("removebreakpoint")); + Attribute(_SC("line"),IntToString(bp._line)); + Attribute(_SC("src"),bp._src.c_str()); + EndElement(_SC("removebreakpoint")); + EndDocument(); + _breakpoints.erase(itor); + } +} + +void SQDbgServer::Break(HSQUIRRELVM v,SQInteger line,const SQChar *src,const SQChar *type,const SQChar *error) +{ + _line = line; + _src = src; + _break_type = src; + if(!error){ + BeginDocument(); + BeginElement(_SC("break")); + Attribute(_SC("thread"),PtrToString(v)); + Attribute(_SC("line"),IntToString(line)); + Attribute(_SC("src"),src); + Attribute(_SC("type"),type); + SerializeState(v); + EndElement(_SC("break")); + EndDocument(); + }else{ + BeginDocument(); + BeginElement(_SC("break")); + Attribute(_SC("thread"),PtrToString(v)); + Attribute(_SC("line"),IntToString(line)); + Attribute(_SC("src"),src); + Attribute(_SC("type"),type); + Attribute(_SC("error"),error); + SerializeState(v); + EndElement(_SC("break")); + EndDocument(); + } +} + +void SQDbgServer::InformNewFileLoaded(HSQUIRRELVM v,const SQChar *src) +{ + SQInteger vm_state = sq_getvmstate(v); + if(vm_state != SQ_VMSTATE_SUSPENDED) + sq_suspendvm(v); + + BeginDocument(); + BeginElement(_SC("file_loaded")); + Attribute(_SC("src"),src); + EndElement(_SC("file_loaded")); + EndDocument(); + + if(vm_state != SQ_VMSTATE_SUSPENDED) + sq_wakeupvm(v,false,false,false,false); +} + +void SQDbgServer::SerializeState(HSQUIRRELVM v) +{ + sq_pushnull(v); + sq_setdebughook(v); + sq_pushnull(v); + sq_seterrorhandler(v); + sq_pushobject(v,_serializefunc); + sq_pushobject(v,_debugroot); + sq_pushstring(v,_SC("watches"),-1); + sq_newtable(v); + for(WatchSetItor i=_watches.begin(); i!=_watches.end(); ++i) + { + sq_pushinteger(v,i->_id); + sq_pushstring(v,i->_exp.c_str(),(SQInteger)i->_exp.length()); + sq_createslot(v,-3); + } + sq_rawset(v,-3); + if(SQ_SUCCEEDED(sq_call(v,1,SQTrue,SQFalse))){ + //if(SQ_SUCCEEDED(sqstd_getblob(v,-1,(SQUserPointer*)&sz))) + //SendChunk(sz); + } + sq_pop(v,2); + + SetErrorHandlers(v); +} + + +void SQDbgServer::SetErrorHandlers(HSQUIRRELVM v) +{ + sq_pushregistrytable(v); + sq_pushstring(v,SQDBG_DEBUG_HOOK,-1); + sq_rawget(v,-2); + sq_setdebughook(v); + sq_pushstring(v,SQDBG_ERROR_HANDLER,-1); + sq_rawget(v,-2); + sq_seterrorhandler(v); + sq_pop(v,1); +} + +void SQDbgServer::BeginDocument() +{ + _xmlcurrentement = -1; + SendChunk(_SC("")); +} + +void SQDbgServer::BeginElement(const SQChar *name) +{ + _xmlcurrentement++; + XMLElementState *self = &xmlstate[_xmlcurrentement]; + scstrcpy(self->name,name); + self->haschildren = false; + if(_xmlcurrentement > 0) { + XMLElementState *parent = &xmlstate[_xmlcurrentement-1]; + if(!parent->haschildren) { + SendChunk(_SC(">")); // closes the parent tag + parent->haschildren = true; + } + } + _scratchstring.resize(2+scstrlen(name)); + scsprintf(&_scratchstring[0],_SC("<%s"),name); + SendChunk(&_scratchstring[0]); +} + +void SQDbgServer::Attribute(const SQChar *name,const SQChar *value) +{ + XMLElementState *self = &xmlstate[_xmlcurrentement]; + assert(!self->haschildren); //cannot have attributes if already has children + const SQChar *escval = escape_xml(value); + _scratchstring.resize(10+scstrlen(name)+scstrlen(escval)); + scsprintf(&_scratchstring[0],_SC(" %s=\"%s\""),name,escval); + SendChunk(&_scratchstring[0]); +} + +void SQDbgServer::EndElement(const SQChar *name) +{ + XMLElementState *self = &xmlstate[_xmlcurrentement]; + assert(scstrcmp(self->name,name) == 0); + if(self->haschildren) { + _scratchstring.resize(10+scstrlen(name)); + scsprintf(&_scratchstring[0],_SC(""),name); + SendChunk(&_scratchstring[0]); + + } + else { + SendChunk(_SC("/>")); + } + _xmlcurrentement--; +} + +void SQDbgServer::EndDocument() +{ + SendChunk(_SC("\r\n")); +} + +//this can be done much better/faster(do we need that?) +const SQChar *SQDbgServer::escape_xml(const SQChar *s) +{ + SQChar *temp= sq_getscratchpad(_v,((SQInteger)scstrlen(s)*6) + sizeof(SQChar)); + SQChar *dest= temp; + while(*s!=_SC('\0')){ + + const SQChar *escape = NULL; + switch(*s) { + case _SC('<'): escape = _SC("<"); break; + case _SC('>'): escape = _SC(">"); break; + case _SC('&'): escape = _SC("&"); break; + case _SC('\''): escape = _SC("'"); break; + case _SC('\"'): escape = _SC("""); break; + case _SC('\n'): escape = _SC("\\n"); break; + case _SC('\r'): escape = _SC("\\r"); break; + } + if(escape) { + scstrcpy(dest,escape); + dest += scstrlen(escape); + } + else { + *dest=*s;*dest++; + } + *s++; + } + *dest=_SC('\0'); + return temp; + +} diff --git a/src/sdk/scripting/squirrel/sqdebug.cpp b/src/sdk/scripting/squirrel/sqdebug.cpp index 7f96c4f90f..72555c7130 100644 --- a/src/sdk/scripting/squirrel/sqdebug.cpp +++ b/src/sdk/scripting/squirrel/sqdebug.cpp @@ -15,7 +15,7 @@ SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi) SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; if(sq_isclosure(ci._closure)) { SQClosure *c = _closure(ci._closure); - SQFunctionProto *proto = _funcproto(c->_function); + SQFunctionProto *proto = c->_function; fi->funcid = proto; fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown"); fi->source = type(proto->_name) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown"); @@ -33,7 +33,7 @@ SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si) SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; switch (type(ci._closure)) { case OT_CLOSURE:{ - SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function); + SQFunctionProto *func = _closure(ci._closure)->_function; if (type(func->_name) == OT_STRING) si->funcname = _stringval(func->_name); if (type(func->_sourcename) == OT_STRING) @@ -64,25 +64,17 @@ void SQVM::Raise_Error(const SQChar *s, ...) _lasterror = SQString::Create(_ss(this),_spval,-1); } -void SQVM::Raise_Error(SQObjectPtr &desc) +void SQVM::Raise_Error(const SQObjectPtr &desc) { _lasterror = desc; } -SQString *SQVM::PrintObjVal(const SQObject &o) +SQString *SQVM::PrintObjVal(const SQObjectPtr &o) { switch(type(o)) { case OT_STRING: return _string(o); case OT_INTEGER: - // C::B patch: Support for Windows 64 bit - #if defined(_WIN64) - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%I64d"), _integer(o)); - // C::B patch: Support for Linux 64 bit - #elif defined(_SQ64) - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%ld"), _integer(o)); - #else - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o)); - #endif + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _PRINT_INT_FMT, _integer(o)); return SQString::Create(_ss(this), _spval); break; case OT_FLOAT: @@ -94,7 +86,7 @@ SQString *SQVM::PrintObjVal(const SQObject &o) } } -void SQVM::Raise_IdxError(SQObject &o) +void SQVM::Raise_IdxError(const SQObjectPtr &o) { SQObjectPtr oval = PrintObjVal(o); Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval)); @@ -103,14 +95,14 @@ void SQVM::Raise_IdxError(SQObject &o) void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2) { SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2); - Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); + Raise_Error(_SC("comparison between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); } void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type) { SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1); - SQInteger found = 0; + SQInteger found = 0; for(SQInteger i=0; i<16; i++) { SQInteger mask = 0x00000001 << i; diff --git a/src/sdk/scripting/squirrel/sqfuncstate.cpp b/src/sdk/scripting/squirrel/sqfuncstate.cpp index f98c757c57..ea9ee06907 100644 --- a/src/sdk/scripting/squirrel/sqfuncstate.cpp +++ b/src/sdk/scripting/squirrel/sqfuncstate.cpp @@ -2,9 +2,10 @@ see copyright notice in squirrel.h */ #include "sqpcheader.h" +#ifndef NO_COMPILER #include "sqcompiler.h" -#include "sqfuncproto.h" #include "sqstring.h" +#include "sqfuncproto.h" #include "sqtable.h" #include "sqopcodes.h" #include "sqfuncstate.h" @@ -28,25 +29,25 @@ SQInstructionDesc g_InstrDesc[]={ {_SC("_OP_GET")}, {_SC("_OP_EQ")}, {_SC("_OP_NE")}, - {_SC("_OP_ARITH")}, + {_SC("_OP_ADD")}, + {_SC("_OP_SUB")}, + {_SC("_OP_MUL")}, + {_SC("_OP_DIV")}, + {_SC("_OP_MOD")}, {_SC("_OP_BITW")}, {_SC("_OP_RETURN")}, {_SC("_OP_LOADNULLS")}, - {_SC("_OP_LOADROOTTABLE")}, + {_SC("_OP_LOADROOT")}, {_SC("_OP_LOADBOOL")}, {_SC("_OP_DMOVE")}, {_SC("_OP_JMP")}, - {_SC("_OP_JNZ")}, + {_SC("_OP_JCMP")}, {_SC("_OP_JZ")}, - {_SC("_OP_LOADFREEVAR")}, - {_SC("_OP_VARGC")}, - {_SC("_OP_GETVARGV")}, - {_SC("_OP_NEWTABLE")}, - {_SC("_OP_NEWARRAY")}, + {_SC("_OP_SETOUTER")}, + {_SC("_OP_GETOUTER")}, + {_SC("_OP_NEWOBJ")}, {_SC("_OP_APPENDARRAY")}, - {_SC("_OP_GETPARENT")}, {_SC("_OP_COMPARITH")}, - {_SC("_OP_COMPARITHL")}, {_SC("_OP_INC")}, {_SC("_OP_INCL")}, {_SC("_OP_PINC")}, @@ -64,14 +65,15 @@ SQInstructionDesc g_InstrDesc[]={ {_SC("_OP_RESUME")}, {_SC("_OP_FOREACH")}, {_SC("_OP_POSTFOREACH")}, - {_SC("_OP_DELEGATE")}, {_SC("_OP_CLONE")}, {_SC("_OP_TYPEOF")}, {_SC("_OP_PUSHTRAP")}, {_SC("_OP_POPTRAP")}, {_SC("_OP_THROW")}, - {_SC("_OP_CLASS")}, - {_SC("_OP_NEWSLOTA")} + {_SC("_OP_NEWSLOTA")}, + {_SC("_OP_GETBASE")}, + {_SC("_OP_CLOSE")}, + {_SC("_OP_JCMP")} }; #endif void DumpLiteral(SQObjectPtr &o) @@ -79,19 +81,8 @@ void DumpLiteral(SQObjectPtr &o) switch(type(o)){ case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break; case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break; - case OT_INTEGER: - // C::B patch: Support for Windows 64 bit - #if defined(_WIN64) - scprintf(_SC("{%I64d}"),_integer(o)); - // C::B patch: Support for Linux 64 bit - #elif defined(_SQ64) - scprintf(_SC("{%ld}"),_integer(o)); - #else - scprintf(_SC("{%d}"),_integer(o)); - #endif - break; + case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break; case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break; - // C::B patch: Eliminate compiler warnings default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler } } @@ -112,6 +103,8 @@ SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc _errfunc = efunc; _errtarget = ed; _bgenerator = false; + _outers = 0; + _ss = ss; } @@ -171,7 +164,7 @@ void SQFuncState::Dump(SQFunctionProto *func) for(i=0;i<_instructions.size();i++){ SQInstruction &inst=_instructions[i]; if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){ - + SQInteger lidx = inst._arg1; scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0); if(lidx >= 0xFFFFFFFF) @@ -180,7 +173,7 @@ void SQFuncState::Dump(SQFunctionProto *func) SQInteger refidx; SQObjectPtr val,key,refo; while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { - refo = refidx; + refo = refidx; } DumpLiteral(key); } @@ -196,7 +189,7 @@ void SQFuncState::Dump(SQFunctionProto *func) SQInteger refidx; SQObjectPtr val,key,refo; while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { - refo = refidx; + refo = refidx; } DumpLiteral(key); scprintf(_SC("\n")); @@ -206,11 +199,12 @@ void SQFuncState::Dump(SQFunctionProto *func) else if(inst.op==_OP_LOADFLOAT) { scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3); } - else if(inst.op==_OP_ARITH){ + /* else if(inst.op==_OP_ARITH){ scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); - } - else + }*/ + else { scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + } n++; } scprintf(_SC("-----\n")); @@ -294,8 +288,9 @@ SQInteger SQFuncState::TopTarget(){ } SQInteger SQFuncState::PopTarget() { - SQInteger npos=_targetstack.back(); - SQLocalVarInfo t=_vlocals[_targetstack.back()]; + SQUnsignedInteger npos=_targetstack.back(); + assert(npos < _vlocals.size()); + SQLocalVarInfo &t = _vlocals[npos]; if(type(t._name)==OT_NULL){ _vlocals.pop_back(); } @@ -308,14 +303,31 @@ SQInteger SQFuncState::GetStackSize() return _vlocals.size(); } +SQInteger SQFuncState::CountOuters(SQInteger stacksize) +{ + SQInteger outers = 0; + SQInteger k = _vlocals.size() - 1; + while(k >= stacksize) { + SQLocalVarInfo &lvi = _vlocals[k]; + k--; + if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer + outers++; + } + } + return outers; +} + void SQFuncState::SetStackSize(SQInteger n) { SQInteger size=_vlocals.size(); while(size>n){ size--; - SQLocalVarInfo lvi=_vlocals.back(); + SQLocalVarInfo lvi = _vlocals.back(); if(type(lvi._name)!=OT_NULL){ - lvi._end_op=GetCurrentPos(); + if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer + _outers--; + } + lvi._end_op = GetCurrentPos(); _localvarinfos.push_back(lvi); } _vlocals.pop_back(); @@ -348,15 +360,17 @@ SQInteger SQFuncState::PushLocalVariable(const SQObject &name) lvi._pos=_vlocals.size(); _vlocals.push_back(lvi); if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size(); - return pos; } + + SQInteger SQFuncState::GetLocalVariable(const SQObject &name) { SQInteger locals=_vlocals.size(); while(locals>=1){ - if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){ + SQLocalVarInfo &lvi = _vlocals[locals-1]; + if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){ return locals-1; } locals--; @@ -364,6 +378,13 @@ SQInteger SQFuncState::GetLocalVariable(const SQObject &name) return -1; } +void SQFuncState::MarkLocalAsOuter(SQInteger pos) +{ + SQLocalVarInfo &lvi = _vlocals[pos]; + lvi._end_op = UINT_MINUS_ONE; + _outers++; +} + SQInteger SQFuncState::GetOuterVariable(const SQObject &name) { SQInteger outers = _outervalues.size(); @@ -371,27 +392,25 @@ SQInteger SQFuncState::GetOuterVariable(const SQObject &name) if(_string(_outervalues[i]._name) == _string(name)) return i; } - return -1; -} - -void SQFuncState::AddOuterValue(const SQObject &name) -{ SQInteger pos=-1; - if(_parent) { + if(_parent) { pos = _parent->GetLocalVariable(name); if(pos == -1) { pos = _parent->GetOuterVariable(name); if(pos != -1) { _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local - return; + return _outervalues.size() - 1; } } else { + _parent->MarkLocalAsOuter(pos); _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local - return; + return _outervalues.size() - 1; + + } } - _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global + return -1; } void SQFuncState::AddParameter(const SQObject &name) @@ -406,20 +425,58 @@ void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force) SQLineInfo li; li._line=line;li._op=(GetCurrentPos()+1); if(lineop)AddInstruction(_OP_LINE,0,line); - _lineinfos.push_back(li); + if(_lastline!=line) { + _lineinfos.push_back(li); + } _lastline=line; } } +void SQFuncState::DiscardTarget() +{ + SQInteger discardedtarget = PopTarget(); + SQInteger size = _instructions.size(); + if(size > 0 && _optimization){ + SQInstruction &pi = _instructions[size-1];//previous instruction + switch(pi.op) { + case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL: + if(pi._arg0 == discardedtarget) { + pi._arg0 = 0xFF; + } + } + } +} + void SQFuncState::AddInstruction(SQInstruction &i) { SQInteger size = _instructions.size(); if(size > 0 && _optimization){ //simple optimizer SQInstruction &pi = _instructions[size-1];//previous instruction switch(i.op) { + case _OP_JZ: + if( pi.op == _OP_CMP && pi._arg1 < 0xFF) { + pi.op = _OP_JCMP; + pi._arg0 = (unsigned char)pi._arg1; + pi._arg1 = i._arg1; + return; + } + case _OP_SET: + case _OP_NEWSLOT: + if(i._arg0 == i._arg3) { + i._arg0 = 0xFF; + } + break; + case _OP_SETOUTER: + if(i._arg0 == i._arg2) { + i._arg0 = 0xFF; + } + break; case _OP_RETURN: if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) { pi.op = _OP_TAILCALL; + } else if(pi.op == _OP_CLOSE){ + pi = i; + return; } break; case _OP_GET: @@ -428,7 +485,7 @@ void SQFuncState::AddInstruction(SQInstruction &i) pi._arg2 = (unsigned char)i._arg1; pi.op = _OP_GETK; pi._arg0 = i._arg0; - + return; } break; @@ -442,22 +499,37 @@ void SQFuncState::AddInstruction(SQInstruction &i) return; } break; - case _OP_APPENDARRAY: - if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + case _OP_APPENDARRAY: { + SQInteger aat = -1; + switch(pi.op) { + case _OP_LOAD: aat = AAT_LITERAL; break; + case _OP_LOADINT: aat = AAT_INT; break; + case _OP_LOADBOOL: aat = AAT_BOOL; break; + case _OP_LOADFLOAT: aat = AAT_FLOAT; break; + default: break; + } + if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ pi.op = _OP_APPENDARRAY; pi._arg0 = i._arg0; pi._arg1 = pi._arg1; - pi._arg2 = MAX_FUNC_STACKSIZE; + pi._arg2 = (unsigned char)aat; pi._arg3 = MAX_FUNC_STACKSIZE; return; } + } break; case _OP_MOVE: - if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1)) - { - pi._arg0 = i._arg0; - _optimization = false; - return; + switch(pi.op) { + case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW: + case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD: + + if(pi._arg0 == i._arg1) + { + pi._arg0 = i._arg0; + _optimization = false; + //_result_elimination = false; + return; + } } if(pi.op == _OP_MOVE) @@ -489,7 +561,7 @@ void SQFuncState::AddInstruction(SQInstruction &i) break; case _OP_LOADNULLS: if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) { - + pi._arg1 = pi._arg1 + 1; pi.op = _OP_LOADNULLS; return; @@ -523,7 +595,8 @@ SQObject SQFuncState::CreateTable() SQFunctionProto *SQFuncState::BuildProto() { - SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(), + + SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(), _nliterals,_parameters.size(),_functions.size(),_outervalues.size(), _lineinfos.size(),_localvarinfos.size(),_defaultparams.size()); @@ -543,9 +616,9 @@ SQFunctionProto *SQFuncState::BuildProto() for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf]; for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np]; for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no]; - for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no]; - for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no]; - for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no]; + for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl]; + for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni]; + for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd]; memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction)); @@ -576,3 +649,5 @@ SQFuncState::~SQFuncState() PopChildState(); } } + +#endif diff --git a/src/sdk/scripting/squirrel/sqlexer.cpp b/src/sdk/scripting/squirrel/sqlexer.cpp index 0c48fc6b4f..c09b511a8b 100644 --- a/src/sdk/scripting/squirrel/sqlexer.cpp +++ b/src/sdk/scripting/squirrel/sqlexer.cpp @@ -44,7 +44,7 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile ADD_KEYWORD(foreach, TK_FOREACH); ADD_KEYWORD(in, TK_IN); ADD_KEYWORD(typeof, TK_TYPEOF); - ADD_KEYWORD(delegate, TK_DELEGATE); + ADD_KEYWORD(base, TK_BASE); ADD_KEYWORD(delete, TK_DELETE); ADD_KEYWORD(try, TK_TRY); ADD_KEYWORD(catch, TK_CATCH); @@ -56,13 +56,10 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile ADD_KEYWORD(case, TK_CASE); ADD_KEYWORD(default, TK_DEFAULT); ADD_KEYWORD(this, TK_THIS); - ADD_KEYWORD(parent,TK_PARENT); ADD_KEYWORD(class,TK_CLASS); ADD_KEYWORD(extends,TK_EXTENDS); ADD_KEYWORD(constructor,TK_CONSTRUCTOR); ADD_KEYWORD(instanceof,TK_INSTANCEOF); - ADD_KEYWORD(vargc,TK_VARGC); - ADD_KEYWORD(vargv,TK_VARGV); ADD_KEYWORD(true,TK_TRUE); ADD_KEYWORD(false,TK_FALSE); ADD_KEYWORD(static,TK_STATIC); @@ -74,6 +71,7 @@ void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,Compile _lasttokenline = _currentline = 1; _currentcolumn = 0; _prevtoken = -1; + _reached_eof = SQFalse; Next(); } @@ -91,6 +89,7 @@ void SQLexer::Next() return; } _currdata = SQUIRREL_EOB; + _reached_eof = SQTrue; } const SQChar *SQLexer::Tok2Str(SQInteger tok) @@ -117,6 +116,10 @@ void SQLexer::LexBlockComment() } } } +void SQLexer::LexLineComment() +{ + do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); +} SQInteger SQLexer::Lex() { @@ -131,15 +134,16 @@ SQInteger SQLexer::Lex() NEXT(); _currentcolumn=1; continue; + case _SC('#'): LexLineComment(); continue; case _SC('/'): NEXT(); switch(CUR_CHAR){ case _SC('*'): NEXT(); LexBlockComment(); - continue; + continue; case _SC('/'): - do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); + LexLineComment(); continue; case _SC('='): NEXT(); @@ -158,17 +162,25 @@ SQInteger SQLexer::Lex() else { NEXT(); RETURN_TOKEN(TK_EQ); } case _SC('<'): NEXT(); - if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) } - else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); } - else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); } - else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); } - //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); } - else { RETURN_TOKEN('<') } + switch(CUR_CHAR) { + case _SC('='): + NEXT(); + if(CUR_CHAR == _SC('>')) { + NEXT(); + RETURN_TOKEN(TK_3WAYSCMP); + } + RETURN_TOKEN(TK_LE) + break; + case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break; + case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break; + case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break; + } + RETURN_TOKEN('<'); case _SC('>'): NEXT(); if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} - else if(CUR_CHAR == _SC('>')){ - NEXT(); + else if(CUR_CHAR == _SC('>')){ + NEXT(); if(CUR_CHAR == _SC('>')){ NEXT(); RETURN_TOKEN(TK_USHIFTR); @@ -183,8 +195,9 @@ SQInteger SQLexer::Lex() case _SC('@'): { SQInteger stype; NEXT(); - if(CUR_CHAR != _SC('"')) - Error(_SC("string expected")); + if(CUR_CHAR != _SC('"')) { + RETURN_TOKEN('@'); + } if((stype=ReadString('"',true))!=-1) { RETURN_TOKEN(stype); } @@ -254,15 +267,15 @@ SQInteger SQLexer::Lex() SQInteger c = CUR_CHAR; if (sciscntrl((int)c)) Error(_SC("unexpected character(control)")); NEXT(); - RETURN_TOKEN(c); + RETURN_TOKEN(c); } RETURN_TOKEN(0); } } } - return 0; + return 0; } - + SQInteger SQLexer::GetIDType(SQChar *s) { SQObjectPtr t; @@ -284,20 +297,20 @@ SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim) case SQUIRREL_EOB: Error(_SC("unfinished string")); return -1; - case _SC('\n'): - if(!verbatim) Error(_SC("newline in a constant")); - APPEND_CHAR(CUR_CHAR); NEXT(); + case _SC('\n'): + if(!verbatim) Error(_SC("newline in a constant")); + APPEND_CHAR(CUR_CHAR); NEXT(); _currentline++; break; case _SC('\\'): if(verbatim) { - APPEND_CHAR('\\'); NEXT(); + APPEND_CHAR('\\'); NEXT(); } else { NEXT(); switch(CUR_CHAR) { case _SC('x'): NEXT(); { - if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); + if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); const SQInteger maxdigits = 4; SQChar temp[maxdigits+1]; SQInteger n = 0; @@ -421,8 +434,7 @@ SQInteger SQLexer::ReadNumber() } } else { - // C::B patch: Eliminate compiler warnings - APPEND_CHAR((char)firstchar); + APPEND_CHAR((int)firstchar); while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) { if(CUR_CHAR == _SC('.') || isexponent(CUR_CHAR)) type = TFLOAT; if(isexponent(CUR_CHAR)) { @@ -436,7 +448,7 @@ SQInteger SQLexer::ReadNumber() } if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected")); } - + APPEND_CHAR(CUR_CHAR); NEXT(); } diff --git a/src/sdk/scripting/squirrel/sqmem.cpp b/src/sdk/scripting/squirrel/sqmem.cpp index 8a809eaf76..6faf8165ae 100644 --- a/src/sdk/scripting/squirrel/sqmem.cpp +++ b/src/sdk/scripting/squirrel/sqmem.cpp @@ -4,8 +4,6 @@ #include "sqpcheader.h" void *sq_vm_malloc(SQUnsignedInteger size){ return malloc(size); } -// C::B patch: Make the compiler happy by commenting unused variables -void *sq_vm_realloc(void *p, SQUnsignedInteger /*oldsize*/, SQUnsignedInteger size){ return realloc(p, size); } +void *sq_vm_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger size){ return realloc(p, size); } -// C::B patch: Make the compiler happy by commenting unused variables -void sq_vm_free(void *p, SQUnsignedInteger /*size*/){ free(p); } +void sq_vm_free(void *p, SQUnsignedInteger size){ free(p); } diff --git a/src/sdk/scripting/squirrel/sqobject.cpp b/src/sdk/scripting/squirrel/sqobject.cpp index a788bd32f6..2e4abb3531 100644 --- a/src/sdk/scripting/squirrel/sqobject.cpp +++ b/src/sdk/scripting/squirrel/sqobject.cpp @@ -35,6 +35,7 @@ const SQChar *IdType2Name(SQObjectType type) case _RT_CLASS: return _SC("class"); case _RT_INSTANCE: return _SC("instance"); case _RT_WEAKREF: return _SC("weakref"); + case _RT_OUTER: return _SC("outer"); default: return NULL; } @@ -42,13 +43,12 @@ const SQChar *IdType2Name(SQObjectType type) const SQChar *GetTypeName(const SQObjectPtr &obj1) { - return IdType2Name(type(obj1)); + return IdType2Name(type(obj1)); } SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len) { SQString *str=ADD_STRING(ss,s,len); - str->_sharedstate=ss; return str; } @@ -62,7 +62,7 @@ SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjec SQInteger idx = (SQInteger)TranslateIndex(refpos); while(idx < _len){ outkey = (SQInteger)idx; - outval = SQInteger(_val[idx]); + outval = (SQInteger)((SQUnsignedInteger)_val[idx]); //return idx for the next iteration return ++idx; } @@ -100,10 +100,10 @@ SQRefCounted::~SQRefCounted() } } -void SQWeakRef::Release() { - if(ISREFCOUNTED(_obj._type)) { +void SQWeakRef::Release() { + if(ISREFCOUNTED(_obj._type)) { _obj._unVal.pRefCounted->_weakref = NULL; - } + } sq_delete(this,SQWeakRef); } @@ -128,22 +128,24 @@ bool SQDelegable::SetDelegate(SQTable *mt) return true; } -bool SQGenerator::Yield(SQVM *v) +bool SQGenerator::Yield(SQVM *v,SQInteger target) { if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;} if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; } SQInteger size = v->_top-v->_stackbase; - _ci=*v->ci; + _stack.resize(size); - for(SQInteger n =0; n_stack[v->_stackbase]; + _stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this; + for(SQInteger n =1; n_stack[v->_stackbase+n]; - v->_stack[v->_stackbase+n] = _null_; } - SQInteger nvargs = v->ci->_vargs.size; - SQInteger vargsbase = v->ci->_vargs.base; - for(SQInteger j = nvargs - 1; j >= 0; j--) { - _vargsstack.push_back(v->_vargsstack[vargsbase+j]); + for(SQInteger j =0; j < size; j++) + { + v->_stack[v->_stackbase+j].Null(); } + + _ci = *v->ci; _ci._generator=NULL; for(SQInteger i=0;i<_ci._etraps;i++) { _etraps.push_back(v->_etraps.top()); @@ -153,37 +155,39 @@ bool SQGenerator::Yield(SQVM *v) return true; } -bool SQGenerator::Resume(SQVM *v,SQInteger target) +bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest) { - SQInteger size=_stack.size(); if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; } if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; } - SQInteger prevtop=v->_top-v->_stackbase; - PUSH_CALLINFO(v,_ci); - SQInteger oldstackbase=v->_stackbase; - v->_stackbase = v->_top; - v->ci->_target = (SQInt32)target; - v->ci->_generator = this; - v->ci->_vargs.size = (unsigned short)_vargsstack.size(); + SQInteger size = _stack.size(); + SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]); + assert(target>=0 && target<=255); + if(!v->EnterFrame(v->_top, v->_top + size, false)) + return false; + v->ci->_generator = this; + v->ci->_target = (SQInt32)target; + v->ci->_closure = _ci._closure; + v->ci->_ip = _ci._ip; + v->ci->_literals = _ci._literals; + v->ci->_ncalls = _ci._ncalls; + v->ci->_etraps = _ci._etraps; + v->ci->_root = _ci._root; + for(SQInteger i=0;i<_ci._etraps;i++) { v->_etraps.push_back(_etraps.top()); _etraps.pop_back(); } - for(SQInteger n =0; n_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this; + + for(SQInteger n = 1; n_stack[v->_stackbase+n] = _stack._vals[n]; - _stack._vals[0] = _null_; - } - while(_vargsstack.size()) { - v->_vargsstack.push_back(_vargsstack.back()); - _vargsstack.pop_back(); + _stack._vals[n].Null(); } - v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size); - v->_top=v->_stackbase+size; - v->ci->_prevtop = (SQInt32)prevtop; - v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase); + _state=eRunning; - if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure)) + if (v->_debughook) v->CallDebugHook(_SC('c')); return true; @@ -199,7 +203,7 @@ void SQArray::Extend(const SQArray *a){ const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop) { SQUnsignedInteger nvars=_nlocalvarinfos; - const SQChar *res=NULL; + const SQChar *res=NULL; if(nvars>=nseq){ for(SQUnsignedInteger i=0;i=nop) @@ -216,18 +220,45 @@ const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQU return res; } + SQInteger SQFunctionProto::GetLine(SQInstruction *curr) { SQInteger op = (SQInteger)(curr-_instructions); SQInteger line=_lineinfos[0]._line; - for(SQInteger i=1;i<_nlineinfos;i++){ - if(_lineinfos[i]._op>=op) - return line; - line=_lineinfos[i]._line; + SQInteger low = 0; + SQInteger high = _nlineinfos - 1; + SQInteger mid = 0; + while(low <= high) + { + mid = low + ((high - low) >> 1); + SQInteger curop = _lineinfos[mid]._op; + if(curop > op) + { + high = mid - 1; + } + else if(curop < op) { + if(mid < (_nlineinfos - 1) + && _lineinfos[mid + 1]._op >= op) { + break; + } + low = mid + 1; + } + else { //equal + break; + } } + + line = _lineinfos[mid]._line; return line; } +SQClosure::~SQClosure() +{ + __ObjRelease(_env); + __ObjRelease(_base); + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); +} + #define _CHECK_IO(exp) { if(!exp)return false; } bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size) { @@ -247,14 +278,14 @@ bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest return true; } -bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag) +bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag) { return SafeWrite(v,write,up,&tag,sizeof(tag)); } -bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag) +bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag) { - SQInteger t; + SQUnsignedInteger32 t; _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t))); if(t != tag){ v->Raise_Error(_SC("invalid or corrupted closure stream")); @@ -265,7 +296,8 @@ bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag) bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o) { - _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType))); + SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o); + _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type))); switch(type(o)){ case OT_STRING: _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger))); @@ -286,8 +318,9 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) { - SQObjectType t; - _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType))); + SQUnsignedInteger32 _type; + _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type))); + SQObjectType t = (SQObjectType)_type; switch(t){ case OT_STRING:{ SQInteger len; @@ -305,7 +338,7 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break; } case OT_NULL: - o=_null_; + o.Null(); break; default: v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t)); @@ -318,7 +351,9 @@ bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) { _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD)); _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar))); - _CHECK_IO(_funcproto(_function)->Save(v,up,write)); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger))); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat))); + _CHECK_IO(_function->Save(v,up,write)); _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL)); return true; } @@ -327,6 +362,8 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) { _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD)); _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar))); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger))); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat))); SQObjectPtr func; _CHECK_IO(SQFunctionProto::Load(v,up,read,func)); _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL)); @@ -334,6 +371,18 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) return true; } +SQFunctionProto::SQFunctionProto(SQSharedState *ss) +{ + _stacksize=0; + _bgenerator=false; + INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); +} + +SQFunctionProto::~SQFunctionProto() +{ + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); +} + bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) { SQInteger i,nliterals = _nliterals,nparameters = _nparameters; @@ -407,7 +456,7 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); _CHECK_IO(ReadObject(v, up, read, sourcename)); _CHECK_IO(ReadObject(v, up, read, name)); - + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals))); _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters))); @@ -417,9 +466,9 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams))); _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions))); _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions))); + - - SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters, + SQFunctionProto *f = SQFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters, nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams); SQObjectPtr proto = f; //gets a ref in case of failure f->_sourcename = sourcename; @@ -441,12 +490,11 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr for(i = 0; i < noutervalues; i++){ SQUnsignedInteger type; - // C::B patch: Avoid compiler warnings about shadowing params - SQObjectPtr name_; + SQObjectPtr name; _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger))); _CHECK_IO(ReadObject(v, up, read, o)); - _CHECK_IO(ReadObject(v, up, read, name_)); - f->_outervalues[i] = SQOuterVar(name_,o, (SQOuterType)type); + _CHECK_IO(ReadObject(v, up, read, name)); + f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type); } _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); @@ -475,7 +523,7 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize))); _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator))); _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams))); - + ret = f; return true; } @@ -493,11 +541,10 @@ void SQVM::Mark(SQCollectable **chain) START_MARK() SQSharedState::MarkObject(_lasterror,chain); SQSharedState::MarkObject(_errorhandler,chain); - SQSharedState::MarkObject(_debughook,chain); + SQSharedState::MarkObject(_debughook_closure,chain); SQSharedState::MarkObject(_roottable, chain); SQSharedState::MarkObject(temp_reg, chain); for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); - for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain); END_MARK() } @@ -535,7 +582,7 @@ void SQClass::Mark(SQCollectable **chain) SQSharedState::MarkObject(_methods[j].val, chain); SQSharedState::MarkObject(_methods[j].attrs, chain); } - for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) { + for(SQUnsignedInteger k =0; k< MT_LAST; k++) { SQSharedState::MarkObject(_metamethods[k], chain); } END_MARK() @@ -556,23 +603,43 @@ void SQGenerator::Mark(SQCollectable **chain) { START_MARK() for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); - for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); SQSharedState::MarkObject(_closure, chain); END_MARK() } +void SQFunctionProto::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain); + for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain); + END_MARK() +} + void SQClosure::Mark(SQCollectable **chain) { START_MARK() - for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); - for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain); + if(_base) _base->Mark(chain); + SQFunctionProto *fp = _function; + fp->Mark(chain); + for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain); + for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain); END_MARK() } void SQNativeClosure::Mark(SQCollectable **chain) { START_MARK() - for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); + for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain); + END_MARK() +} + +void SQOuter::Mark(SQCollectable **chain) +{ + START_MARK() + /* If the valptr points to a closed value, that value is alive */ + if(_valptr == &_value) { + SQSharedState::MarkObject(_value, chain); + } END_MARK() } diff --git a/src/sdk/scripting/squirrel/sqrdbg.cpp b/src/sdk/scripting/squirrel/sqrdbg.cpp new file mode 100644 index 0000000000..08da664e14 --- /dev/null +++ b/src/sdk/scripting/squirrel/sqrdbg.cpp @@ -0,0 +1,183 @@ + +#include +#include +#include + +#include +#include "sqrdbg.h" +#include "sqdbgserver.h" +SQInteger debug_hook(HSQUIRRELVM v); +SQInteger error_handler(HSQUIRRELVM v); + +#include "serialize_state.inl" + +HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate) +{ + + sockaddr_in bindaddr; +#ifdef _WIN32 + WSADATA wsadata; + if (WSAStartup (MAKEWORD(2,2), &wsadata) != 0){ + return NULL; + } +#endif + SQDbgServer *rdbg = new SQDbgServer(v); + rdbg->_autoupdate = autoupdate?true:false; + rdbg->_accept = socket(AF_INET,SOCK_STREAM,0); + bindaddr.sin_family = AF_INET; + bindaddr.sin_port = htons(port); + bindaddr.sin_addr.s_addr = htonl (INADDR_ANY); + if(bind(rdbg->_accept,(sockaddr*)&bindaddr,sizeof(bindaddr))==SOCKET_ERROR){ + delete rdbg; + sq_throwerror(v,_SC("failed to bind the socket")); + return NULL; + } + if(!rdbg->Init()) { + delete rdbg; + sq_throwerror(v,_SC("failed to initialize the debugger")); + return NULL; + } + + return rdbg; +} + +SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg) +{ + if(SQ_FAILED(sq_compilebuffer(rdbg->_v,serialize_state_nut,(SQInteger)scstrlen(serialize_state_nut),_SC("SERIALIZE_STATE"),SQFalse))) { + sq_throwerror(rdbg->_v,_SC("error compiling the serialization function")); + } + sq_getstackobj(rdbg->_v,-1,&rdbg->_serializefunc); + sq_addref(rdbg->_v,&rdbg->_serializefunc); + sq_pop(rdbg->_v,1); + + sockaddr_in cliaddr; + socklen_t addrlen=sizeof(cliaddr); + if(listen(rdbg->_accept,0)==SOCKET_ERROR) + return sq_throwerror(rdbg->_v,_SC("error on listen(socket)")); + rdbg->_endpoint = accept(rdbg->_accept,(sockaddr*)&cliaddr,&addrlen); + //do not accept any other connection + sqdbg_closesocket(rdbg->_accept); + rdbg->_accept = INVALID_SOCKET; + if(rdbg->_endpoint==INVALID_SOCKET){ + return sq_throwerror(rdbg->_v,_SC("error accept(socket)")); + } + while(!rdbg->_ready){ + sq_rdbg_update(rdbg); + } + return SQ_OK; +} + +SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg) +{ + timeval time; + time.tv_sec=0; + time.tv_usec=200; + fd_set read_flags; + FD_ZERO(&read_flags); + FD_SET(rdbg->_endpoint, &read_flags); + select(NULL/*ignored*/, &read_flags, NULL, NULL, &time); + if(FD_ISSET(rdbg->_endpoint,&read_flags)){ + char temp[1024]; + int size=0; + char c,prev=NULL; + memset(&temp,0,sizeof(temp)); + int res; + FD_CLR(rdbg->_endpoint, &read_flags); + int flags = 0; +#ifdef MSG_DONTWAIT + flags = MSG_DONTWAIT; +#endif // MSG_DONTWAIT + while((res = recv(rdbg->_endpoint,&c,1,flags))>0){ + + if(c=='\n')break; + if(c!='\r'){ + temp[size]=c; + prev=c; + size++; + } + if(size >= sizeof(temp)-2) break; + } + switch(res){ + + case 0: + return sq_throwerror(rdbg->_v,_SC("disconnected")); + case SOCKET_ERROR: + { + if(errno == EAGAIN || errno == EWOULDBLOCK) + { + // No bytes received in Linux + } + else + { + return sq_throwerror(rdbg->_v,_SC("socket error")); + } + } + + } + + temp[size]=NULL; + temp[size+1]=NULL; + rdbg->ParseMsg(temp); + } + return SQ_OK; +} + +SQInteger debug_hook(HSQUIRRELVM v) +{ + SQUserPointer up; + SQInteger event_type,line; + const SQChar *src,*func; + sq_getinteger(v,2,&event_type); + sq_getstring(v,3,&src); + sq_getinteger(v,4,&line); + sq_getstring(v,5,&func); + sq_getuserpointer(v,-1,&up); + HSQREMOTEDBG rdbg = (HSQREMOTEDBG)up; + rdbg->Hook(v,event_type,line,src,func); + if(rdbg->_autoupdate) { + if(SQ_FAILED(sq_rdbg_update(rdbg))) + return sq_throwerror(v,_SC("socket failed")); + } + return 0; +} + +SQInteger error_handler(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *sErr=NULL; + const SQChar *fn=_SC("unknown"); + const SQChar *src=_SC("unknown"); + SQInteger line=-1; + SQStackInfos si; + sq_getuserpointer(v,-1,&up); + HSQREMOTEDBG rdbg=(HSQREMOTEDBG)up; + if(SQ_SUCCEEDED(sq_stackinfos(v,1,&si))) + { + if(si.funcname)fn=si.funcname; + if(si.source)src=si.source; + line=si.line; + scprintf(_SC("*FUNCTION [%s] %s line [%d]\n"),fn,src,si.line); + } + if(sq_gettop(v)>=1){ + if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { + scprintf(_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr); + rdbg->Break(v,si.line,src,_SC("error"),sErr); + } + else{ + scprintf(_SC("\nAN ERROR HAS OCCURED [unknown]\n")); + rdbg->Break(v,si.line,src,_SC("error"),_SC("unknown")); + } + } + rdbg->BreakExecution(); + return 0; +} + + +SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg) +{ + delete rdbg; +#ifdef _WIN32 + WSACleanup(); +#endif + return SQ_OK; +} diff --git a/src/sdk/scripting/squirrel/sqstate.cpp b/src/sdk/scripting/squirrel/sqstate.cpp index 54b83866b2..7e353b7ba9 100644 --- a/src/sdk/scripting/squirrel/sqstate.cpp +++ b/src/sdk/scripting/squirrel/sqstate.cpp @@ -12,16 +12,17 @@ #include "squserdata.h" #include "sqclass.h" -SQObjectPtr _null_; -SQObjectPtr _true_(true); -SQObjectPtr _false_(false); -SQObjectPtr _one_((SQInteger)1); -SQObjectPtr _minusone_((SQInteger)-1); +//SQObjectPtr _null_; +//SQObjectPtr _true_(true); +//SQObjectPtr _false_(false); +//SQObjectPtr _one_((SQInteger)1); +//SQObjectPtr _minusone_((SQInteger)-1); SQSharedState::SQSharedState() { _compilererrorhandler = NULL; _printfunc = NULL; + _errorfunc = NULL; _debuginfo = false; _notifyallexceptions = false; } @@ -38,10 +39,10 @@ SQSharedState::SQSharedState() bool CompileTypemask(SQIntVec &res,const SQChar *typemask) { SQInteger i = 0; - + SQInteger mask = 0; while(typemask[i] != 0) { - + switch(typemask[i]){ case 'o': mask |= _RT_NULL; break; case 'i': mask |= _RT_INTEGER; break; @@ -65,15 +66,15 @@ bool CompileTypemask(SQIntVec &res,const SQChar *typemask) return false; } i++; - if(typemask[i] == '|') { - i++; + if(typemask[i] == '|') { + i++; if(typemask[i] == 0) return false; - continue; + continue; } res.push_back(mask); mask = 0; - + } return true; } @@ -83,7 +84,7 @@ SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) SQInteger i=0; SQTable *t=SQTable::Create(ss,0); while(funcz[i].name!=0){ - SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f); + SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0); nc->_nparamscheck = funcz[i].nparamscheck; nc->_name = SQString::Create(ss,funcz[i].name); if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) @@ -95,13 +96,14 @@ SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) } void SQSharedState::Init() -{ +{ _scratchpad=NULL; _scratchpadsize=0; #ifndef NO_GARBAGE_COLLECTOR _gc_chain=NULL; #endif - sq_new(_stringtable,SQStringTable); + _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable)); + new (_stringtable) SQStringTable(this); sq_new(_metamethods,SQObjectPtrVec); sq_new(_systemstrings,SQObjectPtrVec); sq_new(_types,SQObjectPtrVec); @@ -161,29 +163,29 @@ void SQSharedState::Init() SQSharedState::~SQSharedState() { - _constructoridx = _null_; + _constructoridx.Null(); _table(_registry)->Finalize(); _table(_consts)->Finalize(); _table(_metamethodsmap)->Finalize(); - _registry = _null_; - _consts = _null_; - _metamethodsmap = _null_; + _registry.Null(); + _consts.Null(); + _metamethodsmap.Null(); while(!_systemstrings->empty()) { - _systemstrings->back()=_null_; + _systemstrings->back().Null(); _systemstrings->pop_back(); } _thread(_root_vm)->Finalize(); - _root_vm = _null_; - _table_default_delegate = _null_; - _array_default_delegate = _null_; - _string_default_delegate = _null_; - _number_default_delegate = _null_; - _closure_default_delegate = _null_; - _generator_default_delegate = _null_; - _thread_default_delegate = _null_; - _class_default_delegate = _null_; - _instance_default_delegate = _null_; - _weakref_default_delegate = _null_; + _root_vm.Null(); + _table_default_delegate.Null(); + _array_default_delegate.Null(); + _string_default_delegate.Null(); + _number_default_delegate.Null(); + _closure_default_delegate.Null(); + _generator_default_delegate.Null(); + _thread_default_delegate.Null(); + _class_default_delegate.Null(); + _instance_default_delegate.Null(); + _weakref_default_delegate.Null(); _refs_table.Finalize(); #ifndef NO_GARBAGE_COLLECTOR SQCollectable *t = _gc_chain; @@ -239,34 +241,97 @@ void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain) case OT_THREAD:_thread(o)->Mark(chain);break; case OT_CLASS:_class(o)->Mark(chain);break; case OT_INSTANCE:_instance(o)->Mark(chain);break; + case OT_OUTER:_outer(o)->Mark(chain);break; + case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break; default: break; //shutup compiler } } -// C::B patch: Make the compiler happy by commenting unused variables -SQInteger SQSharedState::CollectGarbage(SQVM * /*vm*/) +void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain) +{ + SQVM *vms = _thread(_root_vm); + + vms->Mark(tchain); + + _refs_table.Mark(tchain); + MarkObject(_registry,tchain); + MarkObject(_consts,tchain); + MarkObject(_metamethodsmap,tchain); + MarkObject(_table_default_delegate,tchain); + MarkObject(_array_default_delegate,tchain); + MarkObject(_string_default_delegate,tchain); + MarkObject(_number_default_delegate,tchain); + MarkObject(_generator_default_delegate,tchain); + MarkObject(_thread_default_delegate,tchain); + MarkObject(_closure_default_delegate,tchain); + MarkObject(_class_default_delegate,tchain); + MarkObject(_instance_default_delegate,tchain); + MarkObject(_weakref_default_delegate,tchain); + +} + +SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm) { SQInteger n=0; SQCollectable *tchain=NULL; - SQVM *vms = _thread(_root_vm); - vms->Mark(&tchain); - SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed(); - _refs_table.Mark(&tchain); - MarkObject(_registry,&tchain); - MarkObject(_consts,&tchain); - MarkObject(_metamethodsmap,&tchain); - MarkObject(_table_default_delegate,&tchain); - MarkObject(_array_default_delegate,&tchain); - MarkObject(_string_default_delegate,&tchain); - MarkObject(_number_default_delegate,&tchain); - MarkObject(_generator_default_delegate,&tchain); - MarkObject(_thread_default_delegate,&tchain); - MarkObject(_closure_default_delegate,&tchain); - MarkObject(_class_default_delegate,&tchain); - MarkObject(_instance_default_delegate,&tchain); - MarkObject(_weakref_default_delegate,&tchain); + RunMark(vm,&tchain); + + SQCollectable *resurrected = _gc_chain; + SQCollectable *t = resurrected; + //SQCollectable *nx = NULL; + + _gc_chain = tchain; + + SQArray *ret = NULL; + if(resurrected) { + ret = SQArray::Create(this,0); + SQCollectable *rlast = NULL; + while(t) { + rlast = t; + SQObjectType type = t->GetType(); + if(type != OT_FUNCPROTO && type != OT_OUTER) { + SQObject sqo; + sqo._type = type; + sqo._unVal.pRefCounted = t; + ret->Append(sqo); + } + t = t->_next; + n++; + } + + assert(rlast->_next == NULL); + rlast->_next = _gc_chain; + if(_gc_chain) + { + _gc_chain->_prev = rlast; + } + _gc_chain = resurrected; + } + + t = _gc_chain; + while(t) { + t->UnMark(); + t = t->_next; + } + + if(ret) { + SQObjectPtr temp = ret; + vm->Push(temp); + } + else { + vm->PushNull(); + } + return n; +} + +SQInteger SQSharedState::CollectGarbage(SQVM *vm) +{ + SQInteger n = 0; + SQCollectable *tchain = NULL; + + RunMark(vm,&tchain); SQCollectable *t = _gc_chain; SQCollectable *nx = NULL; @@ -289,8 +354,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM * /*vm*/) t = t->_next; } _gc_chain = tchain; - SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed(); - assert(z == x); + return n; } #endif @@ -342,7 +406,7 @@ void RefTable::Finalize() { RefNode *nodes = _nodes; for(SQUnsignedInteger n = 0; n < _numofslots; n++) { - nodes->obj = _null_; + nodes->obj.Null(); nodes++; } } @@ -373,6 +437,15 @@ void RefTable::AddRef(SQObject &obj) ref->refs++; } +SQUnsignedInteger RefTable::GetRefCount(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,true); + return ref->refs; +} + + SQBool RefTable::Release(SQObject &obj) { SQHash mainpos; @@ -390,7 +463,7 @@ SQBool RefTable::Release(SQObject &obj) ref->next = _freelist; _freelist = ref; _slotused--; - ref->obj = _null_; + ref->obj.Null(); //<>test for shrink? return SQTrue; } @@ -414,8 +487,8 @@ void RefTable::Resize(SQUnsignedInteger size) //add back; assert(t->refs != 0); RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj); - nn->refs = t->refs; - t->obj = _null_; + nn->refs = t->refs; + t->obj.Null(); nfound++; } t++; @@ -492,8 +565,9 @@ void RefTable::AllocNodes(SQUnsignedInteger size) * http://www.lua.org/source/4.0.1/src_lstring.c.html */ -SQStringTable::SQStringTable() +SQStringTable::SQStringTable(SQSharedState *ss) { + _sharedstate = ss; AllocNodes(4); _slotused = 0; } @@ -515,19 +589,21 @@ SQString *SQStringTable::Add(const SQChar *news,SQInteger len) { if(len<0) len = (SQInteger)scstrlen(news); - SQHash h = ::_hashstr(news,len)&(_numofslots-1); + SQHash newhash = ::_hashstr(news,len); + SQHash h = newhash&(_numofslots-1); SQString *s; for (s = _strings[h]; s; s = s->_next){ if(s->_len == len && (!memcmp(news,s->_val,rsl(len)))) return s; //found } - SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); + SQString *t = (SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); new (t) SQString; + t->_sharedstate = _sharedstate; memcpy(t->_val,news,rsl(len)); t->_val[len] = _SC('\0'); t->_len = len; - t->_hash = ::_hashstr(news,len); + t->_hash = newhash; t->_next = _strings[h]; _strings[h] = t; _slotused++; @@ -559,7 +635,7 @@ void SQStringTable::Remove(SQString *bs) SQString *s; SQString *prev=NULL; SQHash h = bs->_hash&(_numofslots - 1); - + for (s = _strings[h]; s; ){ if(s == bs){ if(prev) diff --git a/src/sdk/scripting/squirrel/sqtable.cpp b/src/sdk/scripting/squirrel/sqtable.cpp index 1b3acd0b78..7f710bbb72 100644 --- a/src/sdk/scripting/squirrel/sqtable.cpp +++ b/src/sdk/scripting/squirrel/sqtable.cpp @@ -23,7 +23,8 @@ void SQTable::Remove(const SQObjectPtr &key) _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); if (n) { - n->val = n->key = _null_; + n->val.Null(); + n->key.Null(); _usednodes--; Rehash(false); } @@ -33,8 +34,9 @@ void SQTable::AllocNodes(SQInteger nSize) { _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize); for(SQInteger i=0;i_nodes; + _HashNode *src = _nodes; + _HashNode *dst = nt->_nodes; + SQInteger n = 0; + for(n = 0; n < _numofnodes; n++) { + dst->key = src->key; + dst->val = src->val; + if(src->next) { + assert(src->next > basesrc); + dst->next = basedst + (src->next - basesrc); + assert(dst != dst->next); + } + dst++; + src++; + } + assert(_firstfree > basesrc); + assert(_firstfree != NULL); + nt->_firstfree = basedst + (_firstfree - basesrc); + nt->_usednodes = _usednodes; +#else SQInteger ridx=0; SQObjectPtr key,val; while((ridx=Next(true,ridx,key,val))!=-1){ nt->NewSlot(key,val); } +#endif nt->SetDelegate(_delegate); return nt; } @@ -122,8 +147,8 @@ bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) n->key = mp->key; n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */ n->next = mp->next; - mp->key = _null_; - mp->val = _null_; + mp->key.Null(); + mp->val.Null(); mp->next = NULL; /* now `mp' is free */ } else{ @@ -179,7 +204,7 @@ bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val) void SQTable::_ClearNodes() { - for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; } + for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); } } void SQTable::Finalize() diff --git a/src/sdk/scripting/squirrel/sqvm.cpp b/src/sdk/scripting/squirrel/sqvm.cpp index b1e91b51cf..a84f0e52e0 100644 --- a/src/sdk/scripting/squirrel/sqvm.cpp +++ b/src/sdk/scripting/squirrel/sqvm.cpp @@ -5,8 +5,8 @@ #include #include #include "sqopcodes.h" -#include "sqfuncproto.h" #include "sqvm.h" +#include "sqfuncproto.h" #include "sqclosure.h" #include "sqstring.h" #include "sqtable.h" @@ -16,27 +16,12 @@ #define TOP() (_stack._vals[_top-1]) -#define CLEARSTACK(_last_top) { if((_last_top) >= _top) ClearStack(_last_top); } -void SQVM::ClearStack(SQInteger last_top) -{ - SQObjectType tOldType; - SQObjectValue unOldVal; - while (last_top >= _top) { - SQObjectPtr &o = _stack._vals[last_top--]; - tOldType = o._type; - unOldVal = o._unVal; - o._type = OT_NULL; - o._unVal.pUserPointer = NULL; - __Release(tOldType,unOldVal); - } -} - bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) { SQInteger res; - SQInteger i1 = _integer(o1), i2 = _integer(o2); - if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) + if((type(o1)|type(o2)) == OT_INTEGER) { + SQInteger i1 = _integer(o1), i2 = _integer(o2); switch(op) { case BW_AND: res = i1 & i2; break; case BW_OR: res = i1 | i2; break; @@ -46,86 +31,117 @@ bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,con case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } } - } + } else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} trg = res; return true; } +#define _ARITH_(op,trg,o1,o2) \ +{ \ + SQInteger tmask = type(o1)|type(o2); \ + switch(tmask) { \ + case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \ + case (OT_FLOAT|OT_INTEGER): \ + case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ + default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ + } \ +} + +#define _ARITH_NOZERO(op,trg,o1,o2,err) \ +{ \ + SQInteger tmask = type(o1)|type(o2); \ + switch(tmask) { \ + case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\ + case (OT_FLOAT|OT_INTEGER): \ + case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\ + default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\ + } \ +} + bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) { - if(sq_isnumeric(o1) && sq_isnumeric(o2)) { - if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) { - SQInteger res, i1 = _integer(o1), i2 = _integer(o2); - switch(op) { - case '+': res = i1 + i2; break; - case '-': res = i1 - i2; break; - case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; } - res = i1 / i2; + SQInteger tmask = type(o1)|type(o2); + switch(tmask) { + case OT_INTEGER:{ + SQInteger res, i1 = _integer(o1), i2 = _integer(o2); + switch(op) { + case '+': res = i1 + i2; break; + case '-': res = i1 - i2; break; + case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; } + res = i1 / i2; break; - case '*': res = i1 * i2; break; - case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } - res = i1 % i2; + case '*': res = i1 * i2; break; + case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; } + res = i1 % i2; break; - default: res = 0xDEADBEEF; - } - trg = res; - }else{ - SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); - switch(op) { - case '+': res = f1 + f2; break; - case '-': res = f1 - f2; break; - case '/': res = f1 / f2; break; - case '*': res = f1 * f2; break; - case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; - default: res = 0x0f; - } - trg = res; + default: res = 0xDEADBEEF; } - } else { - if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){ - if(!StringCat(o1, o2, trg)) return false; + trg = res; } + break; + case (OT_FLOAT|OT_INTEGER): + case (OT_FLOAT):{ + SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); + switch(op) { + case '+': res = f1 + f2; break; + case '-': res = f1 - f2; break; + case '/': res = f1 / f2; break; + case '*': res = f1 * f2; break; + case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; + default: res = 0x0f; } - else if(!ArithMetaMethod(op,o1,o2,trg)) { - Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; + trg = res; } + break; + default: + if(op == '+' && (tmask & _RT_STRING)){ + if(!StringCat(o1, o2, trg)) return false; } - } - return true; + else if(!ArithMetaMethod(op,o1,o2,trg)) { + return false; + } + } + return true; } SQVM::SQVM(SQSharedState *ss) { _sharedstate=ss; _suspended = SQFalse; - _suspended_target=-1; + _suspended_target = -1; _suspended_root = SQFalse; - _suspended_traps=-1; - _foreignptr=NULL; - _nnativecalls=0; - _lasterror = _null_; - _errorhandler = _null_; - _debughook = _null_; + _suspended_traps = -1; + _foreignptr = NULL; + _nnativecalls = 0; + _nmetamethodscall = 0; + _lasterror.Null(); + _errorhandler.Null(); + _debughook = false; + _debughook_native = NULL; + _debughook_closure.Null(); + _openouters = NULL; ci = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } void SQVM::Finalize() { - _roottable = _null_; - _lasterror = _null_; - _errorhandler = _null_; - _debughook = _null_; - temp_reg = _null_; + if(_openouters) CloseOuters(&_stack._vals[0]); + _roottable.Null(); + _lasterror.Null(); + _errorhandler.Null(); + _debughook = false; + _debughook_native = NULL; + _debughook_closure.Null(); + temp_reg.Null(); _callstackdata.resize(0); SQInteger size=_stack.size(); for(SQInteger i=0;i_gc_chain,this); } @@ -141,15 +157,20 @@ bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr default: mm = MT_ADD; assert(0); break; //shutup compiler } if(is_delegable(o1) && _delegable(o1)->_delegate) { - Push(o1);Push(o2); - return CallMetaMethod(_delegable(o1),mm,2,dest); + + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, mm, closure)) { + Push(o1);Push(o2); + return CallMetaMethod(closure,mm,2,dest); + } } + Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; } bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) { - + switch(type(o)) { case OT_INTEGER: trg = -_integer(o); @@ -161,10 +182,13 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) case OT_USERDATA: case OT_INSTANCE: if(_delegable(o)->_delegate) { - Push(o); - if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) { - trg = temp_reg; + SQObjectPtr closure; + if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) { + Push(o); + if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false; + _Swap(trg,temp_reg); return true; + } } default:break; //shutup compiler @@ -173,37 +197,49 @@ bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) return false; } -#define _RET_SUCCEED(exp) { result = (exp); return true; } +#define _RET_SUCCEED(exp) { result = (exp); return true; } bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) { - if(type(o1)==type(o2)){ - if(_rawval(o1)==_rawval(o2))_RET_SUCCEED(0); + SQObjectType t1 = type(o1), t2 = type(o2); + if(t1 == t2) { + if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0); SQObjectPtr res; - switch(type(o1)){ + switch(t1){ case OT_STRING: _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); case OT_INTEGER: - _RET_SUCCEED(_integer(o1)-_integer(o2)); + _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1); case OT_FLOAT: _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); case OT_TABLE: case OT_USERDATA: case OT_INSTANCE: if(_delegable(o1)->_delegate) { - Push(o1);Push(o2); - if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) break; + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) { + Push(o1);Push(o2); + if(CallMetaMethod(closure,MT_CMP,2,res)) { + if(type(res) != OT_INTEGER) { + Raise_Error(_SC("_cmp must return an integer")); + return false; + } + _RET_SUCCEED(_integer(res)) + } + return false; + } } //continues through (no break needed) - default: + default: _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 ); } - if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } - _RET_SUCCEED(_integer(res)); - + assert(0); + //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } + // _RET_SUCCEED(_integer(res)); + } else{ if(sq_isnumeric(o1) && sq_isnumeric(o2)){ - if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { + if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } _RET_SUCCEED(1); @@ -214,10 +250,10 @@ bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) _RET_SUCCEED(1); } } - else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);} - else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);} + else if(t1==OT_NULL) {_RET_SUCCEED(-1);} + else if(t2==OT_NULL) {_RET_SUCCEED(1);} else { Raise_CompareError(o1,o2); return false; } - + } assert(0); _RET_SUCCEED(0); //cannot happen @@ -228,36 +264,28 @@ bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObject SQInteger r; if(ObjCmp(o1,o2,r)) { switch(op) { - case CMP_G: res = (r > 0)?_true_:_false_; return true; - case CMP_GE: res = (r >= 0)?_true_:_false_; return true; - case CMP_L: res = (r < 0)?_true_:_false_; return true; - case CMP_LE: res = (r <= 0)?_true_:_false_; return true; - + case CMP_G: res = (r > 0); return true; + case CMP_GE: res = (r >= 0); return true; + case CMP_L: res = (r < 0); return true; + case CMP_LE: res = (r <= 0); return true; + case CMP_3W: res = r; return true; } assert(0); } return false; } -void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) +bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) { switch(type(o)) { case OT_STRING: res = o; - return; + return true; case OT_FLOAT: scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o)); break; case OT_INTEGER: - // C::B patch: Support for Windows 64 bit - #if defined(_WIN64) - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%I64d"),_integer(o)); - // C::B patch: Support for Linux 64 bit - #elif defined(_SQ64) - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%ld"),_integer(o)); - #else - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o)); - #endif + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_PRINT_INT_FMT,_integer(o)); break; case OT_BOOL: scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false")); @@ -266,41 +294,50 @@ void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) case OT_USERDATA: case OT_INSTANCE: if(_delegable(o)->_delegate) { - Push(o); - if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) { - if(type(res) == OT_STRING) - return; - //else keeps going to the default + SQObjectPtr closure; + if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) { + Push(o); + if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {; + if(type(res) == OT_STRING) + return true; + } + else { + return false; + } } } default: scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); } res = SQString::Create(_ss(this),_spval); + return true; } bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) { SQObjectPtr a, b; - ToString(str, a); - ToString(obj, b); + if(!ToString(str, a)) return false; + if(!ToString(obj, b)) return false; SQInteger l = _string(a)->_len , ol = _string(b)->_len; SQChar *s = _sp(rsl(l + ol + 1)); - memcpy(s, _stringval(a), rsl(l)); + memcpy(s, _stringval(a), rsl(l)); memcpy(s + l, _stringval(b), rsl(ol)); dest = SQString::Create(_ss(this), _spval, l + ol); return true; } -void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) +bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) { if(is_delegable(obj1) && _delegable(obj1)->_delegate) { - Push(obj1); - if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest)) - return; + SQObjectPtr closure; + if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) { + Push(obj1); + return CallMetaMethod(closure,MT_TYPEOF,1,dest); + } } dest = SQString::Create(_ss(this),GetTypeName(obj1)); + return true; } bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) @@ -312,28 +349,50 @@ bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) _callsstack = &_callstackdata[0]; _stackbase = 0; _top = 0; - if(!friendvm) + if(!friendvm) _roottable = SQTable::Create(_ss(this), 0); else { _roottable = friendvm->_roottable; _errorhandler = friendvm->_errorhandler; _debughook = friendvm->_debughook; + _debughook_native = friendvm->_debughook_native; + _debughook_closure = friendvm->_debughook_closure; } - + sq_base_register(this); return true; } -extern SQInstructionDesc g_InstrDesc[]; bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall) { - SQFunctionProto *func = _funcproto(closure->_function); + SQFunctionProto *func = closure->_function; - const SQInteger paramssize = func->_nparameters; + SQInteger paramssize = func->_nparameters; const SQInteger newtop = stackbase + func->_stacksize; SQInteger nargs = args; - if (paramssize != nargs) { + if(func->_varparams) + { + paramssize--; + if (nargs < paramssize) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + + //dumpstack(stackbase); + SQInteger nvargs = nargs - paramssize; + SQArray *arr = SQArray::Create(_ss(this),nvargs); + SQInteger pbase = stackbase+paramssize; + for(SQInteger n = 0; n < nvargs; n++) { + arr->_values[n] = _stack._vals[pbase]; + _stack._vals[pbase].Null(); + pbase++; + + } + _stack._vals[stackbase+paramssize] = arr; + //dumpstack(stackbase); + } + else if (paramssize != nargs) { SQInteger ndef = func->_ndefaultparams; SQInteger diff; if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) { @@ -341,99 +400,75 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; } } - else if(func->_varparams) - { - if (nargs < paramssize) { - Raise_Error(_SC("wrong number of parameters")); - return false; - } - for(SQInteger n = 0; n < nargs - paramssize; n++) { - _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]); - _stack._vals[stackbase+paramssize+n] = _null_; - } - } else { Raise_Error(_SC("wrong number of parameters")); return false; } } - if(type(closure->_env) == OT_WEAKREF) { - _stack._vals[stackbase] = _weakref(closure->_env)->_obj; + if(closure->_env) { + _stack._vals[stackbase] = closure->_env->_obj; } - if (!tailcall) { - CallInfo lc; - lc._generator = NULL; - lc._etraps = 0; - lc._prevstkbase = (SQInt32) ( stackbase - _stackbase ); - lc._target = (SQInt32) target; - lc._prevtop = (SQInt32) (_top - _stackbase); - lc._ncalls = 1; - lc._root = SQFalse; - PUSH_CALLINFO(this, lc); - } - else { - ci->_ncalls++; - } - ci->_vargs.size = (SQInt32)(nargs - paramssize); - ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size)); - ci->_closure = closure; + if(!EnterFrame(stackbase, newtop, tailcall)) return false; + + ci->_closure = closure; ci->_literals = func->_literals; - ci->_ip = func->_instructions; - //grows the stack if needed - if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) { - _stack.resize(_stack.size() + (func->_stacksize<<1)); - } + ci->_ip = func->_instructions; + ci->_target = (SQInt32)target; - _top = newtop; - _stackbase = stackbase; - if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + if (_debughook) { CallDebugHook(_SC('c')); + } + + if (closure->_function->_bgenerator) { + SQFunctionProto *f = closure->_function; + SQGenerator *gen = SQGenerator::Create(_ss(this), closure); + if(!gen->Yield(this,f->_stacksize)) + return false; + SQObjectPtr temp; + Return(1, target, temp); + STK(target) = gen; + } + + return true; } bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) { - if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) - for(SQInteger i=0;i_ncalls;i++) + SQBool _isroot = ci->_root; + SQInteger callerbase = _stackbase - ci->_prevstkbase; + + if (_debughook) { + for(SQInteger i=0; i_ncalls; i++) { CallDebugHook(_SC('r')); + } + } - SQBool broot = ci->_root; - SQInteger last_top = _top; - SQInteger target = ci->_target; - SQInteger oldstackbase = _stackbase; - _stackbase -= ci->_prevstkbase; - _top = _stackbase + ci->_prevtop; - if(ci->_vargs.size) PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - if (broot) { - if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1]; - else retval = _null_; + SQObjectPtr *dest; + if (_isroot) { + dest = &(retval); + } else if (ci->_target == -1) { + dest = NULL; + } else { + dest = &_stack._vals[callerbase + ci->_target]; } - else { - if(target != -1) { //-1 is when a class contructor ret value has to be ignored - if (_arg0 != MAX_FUNC_STACKSIZE) - STK(target) = _stack._vals[oldstackbase+_arg1]; - else - STK(target) = _null_; + if (dest) { + if(_arg0 != 0xFF) { + *dest = _stack._vals[_stackbase+_arg1]; } + else { + dest->Null(); + } + //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_; } - - CLEARSTACK(last_top); - assert(oldstackbase >= _stackbase); - return broot?true:false; + LeaveFrame(); + return _isroot ? true : false; } #define _RET_ON_FAIL(exp) { if(!exp) return false; } -bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) -{ - _RET_ON_FAIL(ARITH_OP( op , target, a, incr)); - a = target; - return true; -} - bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) { SQObjectPtr trg; @@ -443,17 +478,18 @@ bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObject return true; } -bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix) +bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx) { SQObjectPtr tmp, tself = self, tkey = key; - if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; } + if (!Get(tself, tkey, tmp, false, selfidx)) { return false; } _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) - Set(tself, tkey, target,true); + if (!Set(tself, tkey, target,selfidx)) { return false; } if (postfix) target = tmp; return true; } #define arg0 (_i_._arg0) +#define sarg0 ((SQInteger)*((signed char *)&_i_._arg0)) #define arg1 (_i_._arg1) #define sarg1 (*((SQInt32 *)&_i_._arg1)) #define arg2 (_i_._arg2) @@ -469,14 +505,9 @@ SQRESULT SQVM::Suspend() return SQ_SUSPEND_FLAG; } -void SQVM::PopVarArgs(VarArgs &vargs) -{ - for(SQInteger n = 0; n< vargs.size; n++) - _vargsstack.pop_back(); -} #define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; } -bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr +bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump) { SQInteger nrefidx; @@ -497,16 +528,22 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr case OT_INSTANCE: if(_delegable(o1)->_delegate) { SQObjectPtr itr; - Push(o1); - Push(o4); - if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){ - o4 = o2 = itr; - if(type(itr) == OT_NULL) _FINISH(exitpos); - if(!Get(o1, itr, o3, false,false)) { - Raise_Error(_SC("_nexti returned an invalid idx")); + SQObjectPtr closure; + if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) { + Push(o1); + Push(o4); + if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) { + o4 = o2 = itr; + if(type(itr) == OT_NULL) _FINISH(exitpos); + if(!Get(o1, itr, o3, false, DONT_FALL_BACK)) { + Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed + return false; + } + _FINISH(1); + } + else { return false; } - _FINISH(1); } Raise_Error(_SC("_nexti failed")); return false; @@ -521,71 +558,43 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr } o2 = idx; o4 = idx; - _generator(o1)->Resume(this, arg_2+1); + _generator(o1)->Resume(this, o3); _FINISH(0); } - default: + default: Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); } return false; //cannot be hit(just to avoid warnings) } -bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2) -{ - if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; } - switch(type(o2)) { - case OT_TABLE: - if(!_table(o1)->SetDelegate(_table(o2))){ - Raise_Error(_SC("delegate cycle detected")); - return false; - } - break; - case OT_NULL: - _table(o1)->SetDelegate(NULL); - break; - default: - Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2)); - return false; - break; - } - trg = o1; - return true; -} #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1)) -#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} } - #define SQ_THROW() { goto exception_trap; } +#define _GUARD(exp) { if(!exp) { SQ_THROW();} } + bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) { SQInteger nouters; SQClosure *closure = SQClosure::Create(_ss(this), func); if((nouters = func->_noutervalues)) { - closure->_outervalues.reserve(nouters); for(SQInteger i = 0; i_outervalues[i]; switch(v._type){ - case otSYMBOL: - closure->_outervalues.push_back(_null_); - if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true)) - {Raise_IdxError(v._src); return false; } - break; case otLOCAL: - closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]); + FindOuter(closure->_outervalues[i], &STK(_integer(v._src))); break; case otOUTER: - closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]); + closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)]; break; } } } SQInteger ndefparams; if((ndefparams = func->_ndefaultparams)) { - closure->_defaultparams.reserve(ndefparams); for(SQInteger i = 0; i < ndefparams; i++) { SQInteger spos = func->_defaultparams[i]; - closure->_defaultparams.push_back(_stack._vals[_stackbase + spos]); + closure->_defaultparams[i] = _stack._vals[_stackbase + spos]; } } target = closure; @@ -593,22 +602,6 @@ bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) } -// C::B patch: Fix shadowed variable warning -bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *callinfo) -{ - if(callinfo->_vargs.size == 0) { - Raise_Error(_SC("the function doesn't have var args")); - return false; - } - if(!sq_isnumeric(index)){ - Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index)); - return false; - } - SQInteger idx = tointeger(index); - if(idx < 0 || idx >= callinfo->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; } - target = _vargsstack[callinfo->_vargs.base+idx]; - return true; -} bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) { @@ -633,18 +626,14 @@ bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes return true; } - - -bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) +bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res) { if(type(o1) == type(o2)) { - res = ((_rawval(o1) == _rawval(o2)?true:false)); + res = (_rawval(o1) == _rawval(o2)); } else { if(sq_isnumeric(o1) && sq_isnumeric(o2)) { - SQInteger cmpres; - if(!ObjCmp(o1, o2,cmpres)) return false; - res = (cmpres == 0); + res = (tofloat(o1) == tofloat(o2)); } else { res = false; @@ -655,72 +644,52 @@ bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) bool SQVM::IsFalse(SQObjectPtr &o) { - // C::B patch: Eliminate compiler warnings - if(( (type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) ) - || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL + if(((type(o) & SQOBJECT_CANBEFALSE) + && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) )) +#if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64)) + || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL +#else + || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL +#endif + { return true; } return false; } -bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target) -{ - switch(type(o)) { - case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_; - break; - case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_; - break; - default: - Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o)); - return false; - } - return true; -} - -bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) +bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) { if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } _nnativecalls++; AutoDec ad(&_nnativecalls); SQInteger traps = 0; - //temp_reg vars for OP_CALL - SQInteger ct_target; - SQInteger ct_stackbase; - bool ct_tailcall; - + CallInfo *prevci = ci; + switch(et) { case ET_CALL: { - SQInteger last_top = _top; temp_reg = closure; - if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { + if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { //call the handler if there are no calls in the stack, if not relies on the previous node if(ci == NULL) CallErrorHandler(_lasterror); return false; } - if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) { - // C::B patch: Eliminate compiler warnings - //SQFunctionProto *f = _funcproto(_closure(temp_reg)->_function); - SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg)); - _GUARD(gen->Yield(this)); - Return(1, ci->_target, temp_reg); - outres = gen; - CLEARSTACK(last_top); + if(ci == prevci) { + outres = STK(_top-nargs); return true; } ci->_root = SQTrue; } break; - case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break; + case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break; case ET_RESUME_VM: case ET_RESUME_THROW_VM: traps = _suspended_traps; ci->_root = _suspended_root; - ci->_vargs = _suspend_varargs; _suspended = SQFalse; if(et == ET_RESUME_THROW_VM) { SQ_THROW(); } break; } - + exception_restore: // { @@ -731,86 +700,88 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); switch(_i_.op) { - case _OP_LINE: - if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) - CallDebugHook(_SC('l'),arg1); - continue; + case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue; case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; - case _OP_LOADINT: TARGET = (SQInteger)arg1; continue; + case _OP_LOADINT: +#ifndef _SQ64 + TARGET = (SQInteger)arg1; continue; +#else + TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue; +#endif case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue; case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; - case _OP_TAILCALL: - temp_reg = STK(arg1); - if (type(temp_reg) == OT_CLOSURE && !_funcproto(_closure(temp_reg)->_function)->_bgenerator){ - ct_tailcall = true; - if(ci->_vargs.size) PopVarArgs(ci->_vargs); + case _OP_TAILCALL:{ + SQObjectPtr &t = STK(arg1); + if (type(t) == OT_CLOSURE + && (!_closure(t)->_function->_bgenerator)){ + SQObjectPtr clo = t; + if(_openouters) CloseOuters(&(_stack._vals[_stackbase])); for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); - ct_target = ci->_target; - ct_stackbase = _stackbase; - goto common_call; + _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true)); + continue; } + } case _OP_CALL: { - ct_tailcall = false; - ct_target = arg0; - temp_reg = STK(arg1); - ct_stackbase = _stackbase+arg2; - -common_call: - SQObjectPtr clo = temp_reg; - SQInteger last_top = _top; + SQObjectPtr clo = STK(arg1); switch (type(clo)) { - case OT_CLOSURE:{ - _GUARD(StartCall(_closure(clo), ct_target, arg3, ct_stackbase, ct_tailcall)); - if (_funcproto(_closure(clo)->_function)->_bgenerator) { - SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(clo)); - _GUARD(gen->Yield(this)); - Return(1, ct_target, clo); - STK(ct_target) = gen; - CLEARSTACK(last_top); - continue; - } - } + case OT_CLOSURE: + _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false)); continue; case OT_NATIVECLOSURE: { bool suspend; - _GUARD(CallNative(_nativeclosure(clo), arg3, ct_stackbase, clo,suspend)); + _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend)); if(suspend){ _suspended = SQTrue; - _suspended_target = ct_target; + _suspended_target = sarg0; _suspended_root = ci->_root; _suspended_traps = traps; - _suspend_varargs = ci->_vargs; outres = clo; return true; } - if(ct_target != -1) { //skip return value for constructors - STK(ct_target) = clo; + if(sarg0 != -1) { + STK(arg0) = clo; } } continue; case OT_CLASS:{ SQObjectPtr inst; - _GUARD(CreateClassInstance(_class(clo),inst,temp_reg)); - STK(ct_target) = inst; - ct_target = -1; //fakes return value target so that is not overwritten by the constructor - if(type(temp_reg) != OT_NULL) { - _stack._vals[ct_stackbase] = inst; - goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the constructor) + _GUARD(CreateClassInstance(_class(clo),inst,clo)); + if(sarg0 != -1) { + STK(arg0) = inst; + } + SQInteger stkbase; + switch(type(clo)) { + case OT_CLOSURE: + stkbase = _stackbase+arg2; + _stack._vals[stkbase] = inst; + _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false)); + break; + case OT_NATIVECLOSURE: + bool suspend; + stkbase = _stackbase+arg2; + _stack._vals[stkbase] = inst; + _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend)); + break; + default: break; //shutup GCC 4.x } } break; case OT_TABLE: case OT_USERDATA: - case OT_INSTANCE: - { - Push(clo); - for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); - if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){ - STK(ct_target) = clo; + case OT_INSTANCE:{ + SQObjectPtr closure; + if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) { + Push(clo); + for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); + if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW(); + if(sarg0 != -1) { + STK(arg0) = clo; + } break; } - Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); - SQ_THROW(); + + //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); + //SQ_THROW(); } default: Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); @@ -819,95 +790,160 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn } continue; case _OP_PREPCALL: - case _OP_PREPCALLK: - { + case _OP_PREPCALLK: { SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1); SQObjectPtr &o = STK(arg2); - if (!Get(o, key, temp_reg,false,true)) { - if(type(o) == OT_CLASS) { //hack? - if(_class_ddel->Get(key,temp_reg)) { - STK(arg3) = o; - TARGET = temp_reg; - continue; - } - } - { Raise_IdxError(key); SQ_THROW();} + if (!Get(o, key, temp_reg,false,arg2)) { + SQ_THROW(); } - - STK(arg3) = type(o) == OT_CLASS?STK(0):o; - TARGET = temp_reg; + STK(arg3) = o; + _Swap(TARGET,temp_reg);//TARGET = temp_reg; } continue; case _OP_GETK: - if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,true)) { Raise_IdxError(ci->_literals[arg1]); SQ_THROW();} - TARGET = temp_reg; + if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();} + _Swap(TARGET,temp_reg);//TARGET = temp_reg; continue; case _OP_MOVE: TARGET = STK(arg1); continue; case _OP_NEWSLOT: _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); - if(arg0 != arg3) TARGET = STK(arg3); + if(arg0 != 0xFF) TARGET = STK(arg3); continue; case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; case _OP_SET: - if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } - if (arg0 != arg3) TARGET = STK(arg3); + if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); } + if (arg0 != 0xFF) TARGET = STK(arg3); continue; case _OP_GET: - if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } - TARGET = temp_reg; + if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); } + _Swap(TARGET,temp_reg);//TARGET = temp_reg; continue; case _OP_EQ:{ bool res; if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = res?_true_:_false_; + TARGET = res?true:false; }continue; - case _OP_NE:{ + case _OP_NE:{ bool res; if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = (!res)?_true_:_false_; + TARGET = (!res)?true:false; } continue; - case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue; + case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue; + case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue; + case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue; case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; case _OP_RETURN: - if(ci->_generator) { - ci->_generator->Kill(); + if((ci)->_generator) { + (ci)->_generator->Kill(); } if(Return(arg0, arg1, temp_reg)){ assert(traps==0); - outres = temp_reg; + //outres = temp_reg; + _Swap(outres,temp_reg); return true; } continue; - case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n) = _null_; }continue; - case _OP_LOADROOTTABLE: TARGET = _roottable; continue; - case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue; + case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue; + case _OP_LOADROOT: TARGET = _roottable; continue; + case _OP_LOADBOOL: TARGET = arg1?true:false; continue; case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; case _OP_JMP: ci->_ip += (sarg1); continue; - case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_JCMP: + _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg)); + if(IsFalse(temp_reg)) ci->_ip+=(sarg1); + continue; case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; - case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue; - case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue; - case _OP_GETVARGV: - if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } + case _OP_GETOUTER: { + SQClosure *cur_cls = _closure(ci->_closure); + SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); + TARGET = *(otr->_valptr); + } + continue; + case _OP_SETOUTER: { + SQClosure *cur_cls = _closure(ci->_closure); + SQOuter *otr = _outer(cur_cls->_outervalues[arg1]); + *(otr->_valptr) = STK(arg2); + if(arg0 != 0xFF) { + TARGET = STK(arg2); + } + } + continue; + case _OP_NEWOBJ: + switch(arg3) { + case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; + case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; + case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; + default: assert(0); continue; + } + case _OP_APPENDARRAY: + { + SQObject val; + val._unVal.raw = 0; + switch(arg2) { + case AAT_STACK: + val = STK(arg1); break; + case AAT_LITERAL: + val = ci->_literals[arg1]; break; + case AAT_INT: + val._type = OT_INTEGER; +#ifndef _SQ64 + val._unVal.nInteger = (SQInteger)arg1; +#else + val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1); +#endif + break; + case AAT_FLOAT: + val._type = OT_FLOAT; + val._unVal.fFloat = *((SQFloat *)&arg1); + break; + case AAT_BOOL: + val._type = OT_BOOL; + val._unVal.nInteger = arg1; + break; + default: assert(0); break; + + } + _array(STK(arg0))->Append(val); continue; + } + case _OP_COMPARITH: { + SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16); + _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); + } continue; - case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; - case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; - case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL); continue; - case _OP_GETPARENT: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue; - case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue; - case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue; - case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue; - case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue; - case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue; - case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue; + case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue; + case _OP_INCL: { + SQObjectPtr &a = STK(arg1); + if(type(a) == OT_INTEGER) { + a._unVal.nInteger = _integer(a) + sarg3; + } + else { + SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o)); + _ARITH_(+,a,a,o); + } + } continue; + case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue; + case _OP_PINCL: { + SQObjectPtr &a = STK(arg1); + if(type(a) == OT_INTEGER) { + TARGET = a; + a._unVal.nInteger = _integer(a) + sarg3; + } + else { + SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o)); + } + + } continue; case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; - case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue; - case _OP_INSTANCEOF: - if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE) + case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue; + case _OP_INSTANCEOF: + if(type(STK(arg1)) != OT_CLASS) {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} - TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_; + TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false; continue; - case _OP_AND: + case _OP_AND: if(IsFalse(STK(arg2))) { TARGET = STK(arg2); ci->_ip += (sarg1); @@ -920,7 +956,7 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn } continue; case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; - case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue; + case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue; case _OP_BWNOT: if(type(STK(arg1)) == OT_INTEGER) { SQInteger t = _integer(STK(arg1)); @@ -931,16 +967,16 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn SQ_THROW(); case _OP_CLOSURE: { SQClosure *c = ci->_closure._unVal.pClosure; - SQFunctionProto *fp = c->_function._unVal.pFunctionProto; + SQFunctionProto *fp = c->_function; if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } continue; } case _OP_YIELD:{ if(ci->_generator) { if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); - _GUARD(ci->_generator->Yield(this)); + _GUARD(ci->_generator->Yield(this,arg2)); traps -= ci->_etraps; - if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg; + if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg; } else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} if(Return(arg0, arg1, temp_reg)){ @@ -948,12 +984,12 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn outres = temp_reg; return true; } - + } continue; case _OP_RESUME: if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} - _GUARD(_generator(STK(arg1))->Resume(this, arg0)); + _GUARD(_generator(STK(arg1))->Resume(this, TARGET)); traps += ci->_etraps; continue; case _OP_FOREACH:{ int tojump; @@ -962,17 +998,13 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn continue; case _OP_POSTFOREACH: assert(type(STK(arg0)) == OT_GENERATOR); - if(_generator(STK(arg0))->_state == SQGenerator::eDead) + if(_generator(STK(arg0))->_state == SQGenerator::eDead) ci->_ip += (sarg1 - 1); continue; - case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue; - case _OP_CLONE: - if(!Clone(STK(arg1), TARGET)) - { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();} - continue; - case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue; + case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue; + case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue; case _OP_PUSHTRAP:{ - SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions; + SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions; _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++; ci->_etraps++; } @@ -985,92 +1017,70 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn } continue; case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; - case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; case _OP_NEWSLOTA: - bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false; - if(type(STK(arg1)) == OT_CLASS) { - if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) { - Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3)); - Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_); - Push(bstatic); - int nparams = 5; - if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) { - Pop(nparams); - continue; - } - } + _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false)); + continue; + case _OP_GETBASE:{ + SQClosure *clo = _closure(ci->_closure); + if(clo->_base) { + TARGET = clo->_base; } - _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic)); - if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) { - _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1)); + else { + TARGET.Null(); } continue; } - + case _OP_CLOSE: + if(_openouters) CloseOuters(&(STK(arg1))); + continue; + } + } } exception_trap: { SQObjectPtr currerror = _lasterror; // dumpstack(_stackbase); - SQInteger n = 0; +// SQInteger n = 0; SQInteger last_top = _top; - if(ci) { - if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror); - - if(traps) { - do { - if(ci->_etraps > 0) { - // C::B patch: Avoid compiler warnings about shadowing params - SQExceptionTrap &etrap = _etraps.top(); - ci->_ip = etrap._ip; - _top = etrap._stacksize; - _stackbase = etrap._stackbase; - _stack._vals[_stackbase+etrap._extarget] = currerror; - _etraps.pop_back(); traps--; ci->_etraps--; - CLEARSTACK(last_top); - goto exception_restore; - } - //if is a native closure - if(type(ci->_closure) != OT_CLOSURE && n) - break; - if(ci->_generator) ci->_generator->Kill(); - PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - n++; - } while(_callsstacksize); + + if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror); + + while( ci ) { + if(ci->_etraps > 0) { + SQExceptionTrap &et = _etraps.top(); + ci->_ip = et._ip; + _top = et._stacksize; + _stackbase = et._stackbase; + _stack._vals[_stackbase + et._extarget] = currerror; + _etraps.pop_back(); traps--; ci->_etraps--; + while(last_top >= _top) _stack._vals[last_top--].Null(); + goto exception_restore; } - else { - //call the hook - if(raiseerror && !_ss(this)->_notifyallexceptions) - CallErrorHandler(currerror); + else if (_debughook) { + //notify debugger of a "return" + //even if it really an exception unwinding the stack + for(SQInteger i = 0; i < ci->_ncalls; i++) { + CallDebugHook(_SC('r')); + } } - //remove call stack until a C function is found or the cstack is empty - if(ci) do { - SQBool exitafterthisone = ci->_root; - if(ci->_generator) ci->_generator->Kill(); - _stackbase -= ci->_prevstkbase; - _top = _stackbase + ci->_prevtop; - PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break; - } while(_callsstacksize); - - CLEARSTACK(last_top); + if(ci->_generator) ci->_generator->Kill(); + bool mustbreak = ci && ci->_root; + LeaveFrame(); + if(mustbreak) break; } + _lasterror = currerror; return false; } assert(0); - // C::B patch: Avoid compiler warnings - return false; } bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) { inst = theclass->CreateInstance(); - if(!theclass->Get(_ss(this)->_constructoridx,constructor)) { - constructor = _null_; + if(!theclass->GetConstructor(constructor)) { + constructor.Null(); } return true; } @@ -1085,246 +1095,324 @@ void SQVM::CallErrorHandler(SQObjectPtr &error) } } + void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) { - // C::B patch: Avoid compiler warnings about shadowing params - SQObjectPtr tmp_reg; - SQInteger nparams=5; - SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function); - Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); - Call(_debughook,nparams,_top-nparams,tmp_reg,SQFalse); - Pop(nparams); + _debughook = false; + SQFunctionProto *func=_closure(ci->_closure)->_function; + if(_debughook_native) { + const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL; + const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL; + SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip); + _debughook_native(this,type,src,line,fname); + } + else { + SQObjectPtr temp_reg; + SQInteger nparams=5; + Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); + Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse); + Pop(nparams); + } + _debughook = true; } -bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,bool &suspend) +bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend) { - if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } SQInteger nparamscheck = nclosure->_nparamscheck; - if(((nparamscheck > 0) && (nparamscheck != nargs)) - || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) { + SQInteger newtop = newbase + nargs + nclosure->_noutervalues; + + if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { + Raise_Error(_SC("Native stack overflow")); + return false; + } + + if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) || + ((nparamscheck < 0) && (nargs < (-nparamscheck))))) + { Raise_Error(_SC("wrong number of parameters")); return false; - } + } SQInteger tcs; - if((tcs = nclosure->_typecheck.size())) { - for(SQInteger i = 0; i < nargs && i < tcs; i++) - if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) { - Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i])); + SQIntVec &tc = nclosure->_typecheck; + if((tcs = tc.size())) { + for(SQInteger i = 0; i < nargs && i < tcs; i++) { + if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) { + Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i])); return false; } + } } - _nnativecalls++; - if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) { - _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1)); - } - SQInteger oldtop = _top; - SQInteger oldstackbase = _stackbase; - _top = stackbase + nargs; - CallInfo lci; - lci._closure = nclosure; - lci._generator = NULL; - lci._etraps = 0; - lci._prevstkbase = (SQInt32) (stackbase - _stackbase); - lci._ncalls = 1; - lci._prevtop = (SQInt32) (oldtop - oldstackbase); - PUSH_CALLINFO(this, lci); - _stackbase = stackbase; - //push free variables - SQInteger outers = nclosure->_outervalues.size(); + + if(!EnterFrame(newbase, newtop, false)) return false; + ci->_closure = nclosure; + + SQInteger outers = nclosure->_noutervalues; for (SQInteger i = 0; i < outers; i++) { - Push(nclosure->_outervalues[i]); + _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i]; } - - if(type(nclosure->_env) == OT_WEAKREF) { - _stack[stackbase] = _weakref(nclosure->_env)->_obj; + if(nclosure->_env) { + _stack._vals[newbase] = nclosure->_env->_obj; } - + _nnativecalls++; SQInteger ret = (nclosure->_function)(this); _nnativecalls--; + suspend = false; - if( ret == SQ_SUSPEND_FLAG) suspend = true; + if (ret == SQ_SUSPEND_FLAG) { + suspend = true; + } else if (ret < 0) { - _stackbase = oldstackbase; - _top = oldtop; - POP_CALLINFO(this); + LeaveFrame(); Raise_Error(_lasterror); return false; } - - if (ret != 0){ retval = TOP(); TOP().Null(); } - else { retval = _null_; } - _stackbase = oldstackbase; - _top = oldtop; - POP_CALLINFO(this); + if(ret) { + retval = _stack._vals[_top-1]; + } + else { + retval.Null(); + } + //retval = ret ? _stack._vals[_top-1] : _null_; + LeaveFrame(); return true; } -bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot) +#define FALLBACK_OK 0 +#define FALLBACK_NO_MATCH 1 +#define FALLBACK_ERROR 2 + +bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx) { switch(type(self)){ case OT_TABLE: if(_table(self)->Get(key,dest))return true; break; case OT_ARRAY: - if(sq_isnumeric(key)){ - return _array(self)->Get(tointeger(key),dest); - } + if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; } break; case OT_INSTANCE: if(_instance(self)->Get(key,dest)) return true; break; + case OT_CLASS: + if(_class(self)->Get(key,dest)) return true; + break; + case OT_STRING: + if(sq_isnumeric(key)){ + SQInteger n = tointeger(key); + if(abs((int)n) < _string(self)->_len) { + if(n < 0) n = _string(self)->_len - n; + dest = SQInteger(_stringval(self)[n]); + return true; + } + Raise_IdxError(key); + return false; + } + break; default:break; //shut up compiler } - if(FallBackGet(self,key,dest,raw)) return true; - - if(fetchroot) { - if(_rawval(STK(0)) == _rawval(self) && - type(STK(0)) == type(self)) { - return _table(_roottable)->Get(key,dest); + if(!raw) { + switch(FallBackGet(self,key,dest)) { + case FALLBACK_OK: return true; //okie + case FALLBACK_NO_MATCH: break; //keep falling back + case FALLBACK_ERROR: return false; // the metamethod failed } + if(InvokeDefaultDelegate(self,key,dest)) { + return true; + } + } +//#ifdef ROOT_FALLBACK + if(selfidx == 0) { + if(_table(_roottable)->Get(key,dest)) return true; } +//#endif + Raise_IdxError(key); return false; } -bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw) +bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) +{ + SQTable *ddel = NULL; + switch(type(self)) { + case OT_CLASS: ddel = _class_ddel; break; + case OT_TABLE: ddel = _table_ddel; break; + case OT_ARRAY: ddel = _array_ddel; break; + case OT_STRING: ddel = _string_ddel; break; + case OT_INSTANCE: ddel = _instance_ddel; break; + case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break; + case OT_GENERATOR: ddel = _generator_ddel; break; + case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break; + case OT_THREAD: ddel = _thread_ddel; break; + case OT_WEAKREF: ddel = _weakref_ddel; break; + default: return false; + } + return ddel->Get(key,dest); +} + + +SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest) { switch(type(self)){ - case OT_CLASS: - return _class(self)->Get(key,dest); - break; case OT_TABLE: case OT_USERDATA: //delegation if(_delegable(self)->_delegate) { - if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false)) - return true; - if(raw)return false; - Push(self);Push(key); - if(CallMetaMethod(_delegable(self),MT_GET,2,dest)) - return true; + if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK; } - if(type(self) == OT_TABLE) { - if(raw) return false; - return _table_ddel->Get(key,dest); + else { + return FALLBACK_NO_MATCH; } - return false; - break; - case OT_ARRAY: - if(raw)return false; - return _array_ddel->Get(key,dest); - case OT_STRING: - if(sq_isnumeric(key)){ - SQInteger n=tointeger(key); - if(abs((int)n)<_string(self)->_len){ - if(n<0)n=_string(self)->_len-n; - dest=SQInteger(_stringval(self)[n]); - return true; + //go through + case OT_INSTANCE: { + SQObjectPtr closure; + if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) { + Push(self);Push(key); + _nmetamethodscall++; + AutoDec ad(&_nmetamethodscall); + if(Call(closure, 2, _top - 2, dest, SQFalse)) { + Pop(2); + return FALLBACK_OK; + } + else { + Pop(2); + if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) + return FALLBACK_ERROR; + } } - return false; - } - else { - if(raw)return false; - return _string_ddel->Get(key,dest); } + } break; - case OT_INSTANCE: - if(raw)return false; - Push(self);Push(key); - if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) { - return _instance_ddel->Get(key,dest); - } - return true; - case OT_INTEGER:case OT_FLOAT:case OT_BOOL: - if(raw)return false; - return _number_ddel->Get(key,dest); - case OT_GENERATOR: - if(raw)return false; - return _generator_ddel->Get(key,dest); - case OT_CLOSURE: case OT_NATIVECLOSURE: - if(raw)return false; - return _closure_ddel->Get(key,dest); - case OT_THREAD: - if(raw)return false; - return _thread_ddel->Get(key,dest); - case OT_WEAKREF: - if(raw)return false; - return _weakref_ddel->Get(key,dest); - default:return false; + default: break;//shutup GCC 4.x } - return false; + // no metamethod or no fallback type + return FALLBACK_NO_MATCH; } -bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot) +bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx) { switch(type(self)){ case OT_TABLE: - if(_table(self)->Set(key,val)) - return true; - if(_table(self)->_delegate) { - if(Set(_table(self)->_delegate,key,val,false)) { - return true; - } - } - //keeps going - case OT_USERDATA: - if(_delegable(self)->_delegate) { - SQObjectPtr t; - Push(self);Push(key);Push(val); - if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; - } + if(_table(self)->Set(key,val)) return true; break; - case OT_INSTANCE:{ - if(_instance(self)->Set(key,val)) - return true; - SQObjectPtr t; - Push(self);Push(key);Push(val); - if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; - } + case OT_INSTANCE: + if(_instance(self)->Set(key,val)) return true; break; case OT_ARRAY: - if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } - return _array(self)->Set(tointeger(key),val); + if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } + if(!_array(self)->Set(tointeger(key),val)) { + Raise_IdxError(key); + return false; + } + return true; default: Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); return false; } - if(fetchroot) { - if(_rawval(STK(0)) == _rawval(self) && - type(STK(0)) == type(self)) { - return _table(_roottable)->Set(key,val); - } + + switch(FallBackSet(self,key,val)) { + case FALLBACK_OK: return true; //okie + case FALLBACK_NO_MATCH: break; //keep falling back + case FALLBACK_ERROR: return false; // the metamethod failed } + if(selfidx == 0) { + if(_table(_roottable)->Set(key,val)) + return true; + } + Raise_IdxError(key); return false; } +SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val) +{ + switch(type(self)) { + case OT_TABLE: + if(_table(self)->_delegate) { + if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK; + } + //keps on going + case OT_INSTANCE: + case OT_USERDATA:{ + SQObjectPtr closure; + SQObjectPtr t; + if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) { + Push(self);Push(key);Push(val); + _nmetamethodscall++; + AutoDec ad(&_nmetamethodscall); + if(Call(closure, 3, _top - 3, t, SQFalse)) { + Pop(3); + return FALLBACK_OK; + } + else { + if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found) + //error + Pop(3); + return FALLBACK_ERROR; + } + } + } + } + break; + default: break;//shutup GCC 4.x + } + // no metamethod or no fallback type + return FALLBACK_NO_MATCH; +} + bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) { - // C::B patch: Avoid compiler warnings about shadowing params - SQObjectPtr tmp_reg; + SQObjectPtr temp_reg; SQObjectPtr newobj; switch(type(self)){ case OT_TABLE: newobj = _table(self)->Clone(); goto cloned_mt; - case OT_INSTANCE: + case OT_INSTANCE: { newobj = _instance(self)->Clone(_ss(this)); cloned_mt: - if(_delegable(newobj)->_delegate){ + SQObjectPtr closure; + if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) { Push(newobj); Push(self); - CallMetaMethod(_delegable(newobj),MT_CLONED,2,tmp_reg); + if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg)) + return false; + } } target = newobj; return true; - case OT_ARRAY: + case OT_ARRAY: target = _array(self)->Clone(); return true; - default: return false; + default: + Raise_Error(_SC("cloning a %s"), GetTypeName(self)); + return false; } } +bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw) +{ + if(type(self) != OT_CLASS) { + Raise_Error(_SC("object must be a class")); + return false; + } + SQClass *c = _class(self); + if(!raw) { + SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER]; + if(type(mm) != OT_NULL ) { + Push(self); Push(key); Push(val); + Push(attrs); + Push(bstatic); + return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg); + } + } + if(!NewSlot(self, key, val,bstatic)) + return false; + if(type(attrs) != OT_NULL) { + c->SetAttributes(key,attrs); + } + return true; +} + bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) { if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } @@ -1334,22 +1422,36 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject if(_table(self)->_delegate) { SQObjectPtr res; if(!_table(self)->Get(key,res)) { - Push(self);Push(key);Push(val); - rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res); + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { + Push(self);Push(key);Push(val); + if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { + return false; + } + rawcall = false; + } + else { + rawcall = true; + } } } if(rawcall) _table(self)->NewSlot(key,val); //cannot fail - + break;} case OT_INSTANCE: { SQObjectPtr res; - Push(self);Push(key);Push(val); - if(!CallMetaMethod(_instance(self),MT_NEWSLOT,3,res)) { - Raise_Error(_SC("class instances do not support the new slot operator")); - return false; + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) { + Push(self);Push(key);Push(val); + if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) { + return false; + } + break; } + Raise_Error(_SC("class instances do not support the new slot operator")); + return false; break;} - case OT_CLASS: + case OT_CLASS: if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { if(_class(self)->_locked) { Raise_Error(_SC("trying to modify a class that has already been instantiated")); @@ -1370,6 +1472,8 @@ bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObject return true; } + + bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) { switch(type(self)) { @@ -1377,13 +1481,13 @@ bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr case OT_INSTANCE: case OT_USERDATA: { SQObjectPtr t; - bool handled = false; - if(_delegable(self)->_delegate) { + //bool handled = false; + SQObjectPtr closure; + if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) { Push(self);Push(key); - handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t); + return CallMetaMethod(closure,MT_DELSLOT,2,res); } - - if(!handled) { + else { if(type(self) == OT_TABLE) { if(_table(self)->Get(key,t)) { _table(self)->Remove(key); @@ -1415,12 +1519,12 @@ SQInteger prevstackbase = _stackbase; #endif switch(type(closure)) { case OT_CLOSURE: - return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror); + return Execute(closure, nparams, stackbase, outres, raiseerror); break; case OT_NATIVECLOSURE:{ bool suspend; return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend); - + } break; case OT_CLASS: { @@ -1445,38 +1549,130 @@ SQInteger prevstackbase = _stackbase; return true; } -bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) +bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) { - SQObjectPtr closure; - if(del->GetMetaMethod(this, mm, closure)) { - if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { - Pop(nparams); - return true; - } + //SQObjectPtr closure; + + _nmetamethodscall++; + if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { + _nmetamethodscall--; + Pop(nparams); + return true; } + _nmetamethodscall--; + //} Pop(nparams); return false; } +void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex) +{ + SQOuter **pp = &_openouters; + SQOuter *p; + SQOuter *otr; + + while ((p = *pp) != NULL && p->_valptr >= stackindex) { + if (p->_valptr == stackindex) { + target = SQObjectPtr(p); + return; + } + pp = &p->_next; + } + otr = SQOuter::Create(_ss(this), stackindex); + otr->_next = *pp; + otr->_idx = (stackindex - _stack._vals); + __ObjAddRef(otr); + *pp = otr; + target = SQObjectPtr(otr); +} + +bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall) +{ + if( !tailcall ) { + if( _callsstacksize == _alloccallsstacksize ) { + GrowCallStack(); + } + ci = &_callsstack[_callsstacksize++]; + ci->_prevstkbase = (SQInt32)(newbase - _stackbase); + ci->_prevtop = (SQInt32)(_top - _stackbase); + ci->_etraps = 0; + ci->_ncalls = 1; + ci->_generator = NULL; + ci->_root = SQFalse; + } + else { + ci->_ncalls++; + } + + _stackbase = newbase; + _top = newtop; + if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) { + if(_nmetamethodscall) { + Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod")); + return false; + } + _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2)); + RelocateOuters(); + } + return true; +} + +void SQVM::LeaveFrame() { + SQInteger last_top = _top; + SQInteger last_stackbase = _stackbase; + SQInteger css = --_callsstacksize; + + /* First clean out the call stack frame */ + ci->_closure.Null(); + _stackbase -= ci->_prevstkbase; + _top = _stackbase + ci->_prevtop; + ci = (css) ? &_callsstack[css-1] : NULL; + + if(_openouters) CloseOuters(&(_stack._vals[last_stackbase])); + while (last_top >= _top) { + _stack._vals[last_top--].Null(); + } +} + +void SQVM::RelocateOuters() +{ + SQOuter *p = _openouters; + while (p) { + p->_valptr = _stack._vals + p->_idx; + p = p->_next; + } +} + +void SQVM::CloseOuters(SQObjectPtr *stackindex) { + SQOuter *p; + while ((p = _openouters) != NULL && p->_valptr >= stackindex) { + p->_value = *(p->_valptr); + p->_valptr = &p->_value; + _openouters = p->_next; + __ObjRelease(p); + } +} + void SQVM::Remove(SQInteger n) { n = (n >= 0)?n + _stackbase - 1:_top + n; for(SQInteger i = n; i < _top; i++){ _stack[i] = _stack[i+1]; } - _stack[_top] = _null_; + _stack[_top].Null(); _top--; } void SQVM::Pop() { - _stack[--_top] = _null_; + _stack[--_top].Null(); } void SQVM::Pop(SQInteger n) { for(SQInteger i = 0; i < n; i++){ - _stack[--_top] = _null_; + _stack[--_top].Null(); } } +void SQVM::PushNull() { _stack[_top++].Null(); } void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; } SQObjectPtr &SQVM::Top() { return _stack[_top-1]; } SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; } @@ -1494,7 +1690,7 @@ void SQVM::dumpstack(SQInteger stackbase,bool dumpall) scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); scprintf(_SC("prev top: %d\n"),ci._prevtop); for(SQInteger i=0;i"));else scprintf(_SC(" ")); scprintf(_SC("[%d]:"),n); switch(type(obj)){ From b7e0af36428cc78dba282dfad43b822b1b351797 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Sun, 24 Apr 2016 18:47:58 +0200 Subject: [PATCH 02/16] [NOT COMPILE] Remove sqplus Remove the sqplus binding library does not update project files will not compile --- src/include/scripting/sqplus/Makefile.am | 10 - src/include/scripting/sqplus/SqPlusConst.h | 343 --- .../scripting/sqplus/SquirrelBindingsUtils.h | 151 -- .../sqplus/SquirrelBindingsUtilsWin32.h | 43 - src/include/scripting/sqplus/SquirrelObject.h | 224 -- src/include/scripting/sqplus/SquirrelVM.h | 124 - src/include/scripting/sqplus/sqplus.h | 1998 ----------------- src/include/scripting/sqplus/sqplusWin32.h | 7 - src/sdk/scripting/sqplus/Makefile.am | 14 - src/sdk/scripting/sqplus/SqPlus.cpp | 298 --- .../sqplus/SquirrelBindingsUtils.cpp | 123 - .../sqplus/SquirrelBindingsUtilsWin32.cpp | 32 - src/sdk/scripting/sqplus/SquirrelObject.cpp | 639 ------ src/sdk/scripting/sqplus/SquirrelVM.cpp | 347 --- src/sdk/scripting/sqplus/sqplus.cbp | 191 -- src/sdk/scripting/sqplus/sqplus.vcproj | 339 --- src/sdk/scripting/sqplus/sqplus71.vcproj | 229 -- 17 files changed, 5112 deletions(-) delete mode 100644 src/include/scripting/sqplus/Makefile.am delete mode 100644 src/include/scripting/sqplus/SqPlusConst.h delete mode 100644 src/include/scripting/sqplus/SquirrelBindingsUtils.h delete mode 100644 src/include/scripting/sqplus/SquirrelBindingsUtilsWin32.h delete mode 100644 src/include/scripting/sqplus/SquirrelObject.h delete mode 100644 src/include/scripting/sqplus/SquirrelVM.h delete mode 100644 src/include/scripting/sqplus/sqplus.h delete mode 100644 src/include/scripting/sqplus/sqplusWin32.h delete mode 100644 src/sdk/scripting/sqplus/Makefile.am delete mode 100644 src/sdk/scripting/sqplus/SqPlus.cpp delete mode 100644 src/sdk/scripting/sqplus/SquirrelBindingsUtils.cpp delete mode 100644 src/sdk/scripting/sqplus/SquirrelBindingsUtilsWin32.cpp delete mode 100644 src/sdk/scripting/sqplus/SquirrelObject.cpp delete mode 100644 src/sdk/scripting/sqplus/SquirrelVM.cpp delete mode 100644 src/sdk/scripting/sqplus/sqplus.cbp delete mode 100644 src/sdk/scripting/sqplus/sqplus.vcproj delete mode 100644 src/sdk/scripting/sqplus/sqplus71.vcproj diff --git a/src/include/scripting/sqplus/Makefile.am b/src/include/scripting/sqplus/Makefile.am deleted file mode 100644 index 8ae7c68715..0000000000 --- a/src/include/scripting/sqplus/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -sdkdir=$(includedir)/codeblocks/scripting/sqplus - -sdk_HEADERS = SqPlusConst.h \ - SquirrelBindingsUtils.h \ - SquirrelVM.h \ - sqplus.h \ - SquirrelObject.h - -EXTRA_DIST = SquirrelBindingsUtilsWin32.h \ - sqplusWin32.h diff --git a/src/include/scripting/sqplus/SqPlusConst.h b/src/include/scripting/sqplus/SqPlusConst.h deleted file mode 100644 index 8e923454c0..0000000000 --- a/src/include/scripting/sqplus/SqPlusConst.h +++ /dev/null @@ -1,343 +0,0 @@ -// SqPlusConst.h -// SqPlus constant type and constant member function support created by Simon Michelmore. -// Modular integration 11/14/05 jcs. - -#ifdef SQPLUS_DECLARE_INSTANCE_TYPE_CONST -#undef SQPLUS_DECLARE_INSTANCE_TYPE_CONST - -// Kamaitati's NULL_INSTANCE support. 5/28/06 jcs - -#ifdef SQPLUS_SUPPORT_NULL_INSTANCES - -#define DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,NAME) \ -DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) \ -namespace SqPlus { \ -inline void Push(HSQUIRRELVM v,const TYPE * value) { \ - if (!value) sq_pushnull(v); \ - else if (!CreateNativeClassInstance(v,GetTypeName(*value),(TYPE*)value,0)) \ - throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \ -inline void Push(HSQUIRRELVM v,const TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \ -inline bool Match(TypeWrapper,HSQUIRRELVM v,int idx) { return GetInstance(v,idx) != NULL; } \ -inline const TYPE & Get(TypeWrapper,HSQUIRRELVM v,int idx) { return *GetInstance(v,idx); } \ -} // nameSpace SqPlus - -#else - -#define DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,NAME) \ -DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) \ -namespace SqPlus { \ -inline void Push(HSQUIRRELVM v,const TYPE * value) { if (!CreateNativeClassInstance(v,GetTypeName(*value),(TYPE*)value,0)) throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \ -inline void Push(HSQUIRRELVM /*v*/,const TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \ -inline bool Match(TypeWrapper,HSQUIRRELVM v,int idx) { return GetInstance(v,idx) != NULL; } \ -inline const TYPE & Get(TypeWrapper,HSQUIRRELVM v,int idx) { return *GetInstance(v,idx); } \ -} // nameSpace SqPlus - -#endif - -#define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,TYPE) -#define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,NAME) -#endif - -#ifdef SQPLUS_CALL_CONST_MFUNC_RET0 -#undef SQPLUS_CALL_CONST_MFUNC_RET0 -template -static int Call(Callee & callee,RT (Callee::*func)() const,HSQUIRRELVM v,int /*index*/) { - RT ret = (callee.*func)(); - Push(v,ret); - return 1; -} - -// C::B patch: so it builds on 64bit -#ifdef _WIN64 -template -static int Call(Callee & callee,RT (Callee::*func)() const,HSQUIRRELVM v,SQInteger /*index*/) { - RT ret = (callee.*func)(); - Push(v,ret); - return 1; -} -#endif - -template -static int Call(Callee & callee,RT (Callee::*func)(P1) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0) - ); - Push(v,ret); - return 1; -} - -template -static int Call(Callee & callee,RT (Callee::*func)(P1,P2) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1) - ); - Push(v,ret); - return 1; -} - -template -static int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2) - ); - Push(v,ret); - return 1; -} - -template -static int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3) - ); - Push(v,ret); - return 1; -} - -template -static int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4) - ); - Push(v,ret); - return 1; -} - -template -static int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5) - ); - Push(v,ret); - return 1; -} - -template -static int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - sq_argassert(7,index + 6); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5), - Get(TypeWrapper(),v,index + 6) - ); - Push(v,ret); - return 1; -} -#endif - -#ifdef SQPLUS_CALL_CONST_MFUNC_NORET -#undef SQPLUS_CALL_CONST_MFUNC_NORET -template -static int Call(Callee & callee,void (Callee::*func)() const,HSQUIRRELVM,int /*index*/) { - (callee.*func)(); - return 0; -} - -template -static int Call(Callee & callee,void (Callee::*func)(P1) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - (callee.*func)( - Get(TypeWrapper(),v,index + 0) - ); - return 0; -} - -template -static int Call(Callee & callee,void (Callee::*func)(P1,P2) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1) - ); - return 0; -} - -template -static int Call(Callee & callee,void (Callee::*func)(P1,P2,P3) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2) - ); - return 0; -} - -template -static int Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3) - ); - return 0; -} - -template -static int Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4) - ); - return 0; -} - -template -static int Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5) - ); - return 0; -} - -template -static int Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6,P7) const,HSQUIRRELVM v,int index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - sq_argassert(7,index + 6); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5), - Get(TypeWrapper(),v,index + 6) - ); - return 0; -} -#endif - -#ifdef SQPLUS_CALL_CONST_MFUNC_RET1 -#undef SQ_REG_CONST_STATIC_VAR -template -int Call(Callee & callee, RT (Callee::*func)() const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -int Call(Callee & callee,RT (Callee::*func)(P1) const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -int Call(Callee & callee,RT (Callee::*func)(P1,P2) const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3) const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4) const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5) const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6) const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -int Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7) const,HSQUIRRELVM v,int index) { - return ReturnSpecialization::Call(callee,func,v,index); -} -#undef SQPLUS_CALL_CONST_MFUNC_RET1 -#endif - -#ifdef SQ_REG_CONST_STATIC_VAR -template -SQClassDef & staticVar(const VarType * pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_ONLY) { - struct CV { - const VarType * var; - } cv; // Cast Variable helper. - cv.var = pvar; - RegisterInstanceVariable(newClass,ClassType::type(),*(VarType **)&cv,name_,VarAccessType(access|VAR_ACCESS_STATIC)); - return *this; -} // staticVar -#endif - -// SqPlusConst.h diff --git a/src/include/scripting/sqplus/SquirrelBindingsUtils.h b/src/include/scripting/sqplus/SquirrelBindingsUtils.h deleted file mode 100644 index a924caa02f..0000000000 --- a/src/include/scripting/sqplus/SquirrelBindingsUtils.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef SQUIRREL_BINDINGS_UTILS_H -#define SQUIRREL_BINDINGS_UTILS_H - -struct ScriptClassMemberDecl { - const SQChar *name; - SQFUNCTION func; - SQInteger params; - const SQChar *typemask; -}; - -struct SquirrelClassDecl { - const SQChar *name; - const SQChar *base; - const ScriptClassMemberDecl *members; -}; - -struct ScriptConstantDecl { - const SQChar *name; - SQObjectType type; - union value { - value(float v){ f = v; } - value(int v){ i = v; } - value(long int v){ li = v; } - value(const SQChar *v){ s = v; } - float f; - int i; - long int li; - const SQChar *s; - } val; -}; - -struct ScriptNamespaceDecl { - const SQChar *name; - const ScriptClassMemberDecl *members; - const ScriptConstantDecl *constants; - const ScriptClassMemberDecl *delegate; -}; - -#define _BEGIN_CLASS(classname) \ - SQInteger __##classname##__typeof(HSQUIRRELVM v) \ - { \ - sq_pushstring(v,sqT(#classname),-1); \ - return 1; \ - } \ - struct ScriptClassMemberDecl __##classname##_members[] = { \ - {sqT("_typeof"),__##classname##__typeof,1,NULL}, - -#define _BEGIN_NAMESPACE(xnamespace) struct ScriptClassMemberDecl __##xnamespace##_members[] = { -#define _BEGIN_NAMESPACE_CONSTANTS(xnamespace) {NULL,NULL,0,NULL}}; \ - struct ScriptConstantDecl __##xnamespace##_constants[] = { - -#define _BEGIN_DELEGATE(xnamespace) struct ScriptClassMemberDecl __##xnamespace##_delegate[] = { -#define _DELEGATE(xnamespace) __##xnamespace##_delegate -#define _END_DELEGATE(classname) {NULL,NULL,NULL,NULL}}; - -#define _CONSTANT(name,type,val) {sqT(#name),type,val}, -#define _CONSTANT_IMPL(name,type) {sqT(#name),type,name}, - -#define _MEMBER_FUNCTION(classname,name,nparams,typemask) \ - {sqT(#name),__##classname##_##name,nparams,typemask}, - -#define _END_NAMESPACE(classname,delegate) {NULL,OT_NULL,0}}; \ -struct ScriptNamespaceDecl __##classname##_decl = { \ - sqT(#classname), __##classname##_members,__##classname##_constants,delegate }; - -#define _END_CLASS(classname) {NULL,NULL,0,NULL}}; \ -struct SquirrelClassDecl __##classname##_decl = { \ - sqT(#classname), NULL, __##classname##_members }; - - -#define _END_CLASS_INHERITANCE(classname,base) {NULL,NULL,NULL,NULL}}; \ -struct SquirrelClassDecl __##classname##_decl = { \ - sqT(#classname), sqT(#base), __##classname##_members }; - -#define _MEMBER_FUNCTION_IMPL(classname,name) \ - SQInteger __##classname##_##name(HSQUIRRELVM v) - -#define _INIT_STATIC_NAMESPACE(classname) CreateStaticNamespace(SquirrelVM::GetVMPtr(),&__##classname##_decl); -#define _INIT_CLASS(classname)CreateClass(SquirrelVM::GetVMPtr(),&__##classname##_decl); - -#define _DECL_STATIC_NAMESPACE(xnamespace) extern struct ScriptNamespaceDecl __##xnamespace##_decl; -#define _DECL_CLASS(classname) extern struct SquirrelClassDecl __##classname##_decl; - -#define _CHECK_SELF(cppclass,scriptclass) \ - cppclass *self = NULL; \ - if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)&__##scriptclass##_decl))) { \ - return sq_throwerror(v,sqT("invalid instance type"));\ - } - -#define _CHECK_INST_PARAM(pname,idx,cppclass,scriptclass) \ - cppclass *pname = NULL; \ - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&pname,(SQUserPointer)&__##scriptclass##_decl))) { \ - return sq_throwerror(v,sqT("invalid instance type"));\ - } \ - -#define _CHECK_INST_PARAM_BREAK(pname,idx,cppclass,scriptclass) \ - cppclass *pname = NULL; \ - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&pname,(SQUserPointer)&__##scriptclass##_decl))) { \ - break; \ - } \ - -#define _CLASS_TAG(classname) ((unsigned int)&__##classname##_decl) - - -#define _DECL_NATIVE_CONSTRUCTION(classname,cppclass) \ - BOOL_T push_##classname(cppclass &quat); \ - SquirrelObject new_##classname(cppclass &quat); - -#define _IMPL_NATIVE_CONSTRUCTION(classname,cppclass) \ -static SQInteger classname##_release_hook(SQUserPointer p, SQInteger size) \ -{ \ - if(p) { \ - cppclass *pv = (cppclass *)p; \ - delete pv; \ - } \ - return 0; \ -} \ -BOOL_T push_##classname(cppclass &quat) \ -{ \ - cppclass *newquat = new cppclass; \ - *newquat = quat; \ - if(!CreateNativeClassInstance(SquirrelVM::GetVMPtr(),sqT(#classname),newquat,classname##_release_hook)) { \ - delete newquat; \ - return FALSE; \ - } \ - return TRUE; \ -} \ -SquirrelObject new_##classname(cppclass &quat) \ -{ \ - SquirrelObject ret; \ - if(push_##classname(quat)) { \ - ret.AttachToStackObject(-1); \ - sq_pop(SquirrelVM::GetVMPtr(),1); \ - } \ - return ret; \ -} \ -SQInteger construct_##classname(cppclass *p) \ -{ \ - sq_setinstanceup(SquirrelVM::GetVMPtr(),1,p); \ - sq_setreleasehook(SquirrelVM::GetVMPtr(),1,classname##_release_hook); \ - return 1; \ -} - -BOOL_T CreateStaticClass(HSQUIRRELVM v,SquirrelClassDecl *cd); -BOOL_T CreateStaticNamespace(HSQUIRRELVM v,ScriptNamespaceDecl *sn); -BOOL_T CreateClass(HSQUIRRELVM v,SquirrelClassDecl *cd); -BOOL_T InitScriptClasses(HSQUIRRELVM v); -BOOL_T CreateNativeClassInstance(HSQUIRRELVM v,const SQChar *classname,SQUserPointer ud,SQRELEASEHOOK hook); - -#endif // SQUIRREL_BINDINGS_UTILS_H - diff --git a/src/include/scripting/sqplus/SquirrelBindingsUtilsWin32.h b/src/include/scripting/sqplus/SquirrelBindingsUtilsWin32.h deleted file mode 100644 index 443ab5fac6..0000000000 --- a/src/include/scripting/sqplus/SquirrelBindingsUtilsWin32.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef SQUIRREL_BINDINGS_UTILS_WIN32_H -#define SQUIRREL_BINDINGS_UTILS_WIN32_H - -#ifndef _INC_WINDOWS -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include -#endif -#ifndef __IUnknown_INTERFACE_DEFINED__ -#include -#endif - -#include "sqplus.h" - -#ifndef SQUIRREL_BINDINGS_UTILS_H -#include "SquirrelBindingsUtils.h" -#endif - -#define _DECLARE_REFCOUNTED_NEW(cppclass,classname) \ - SquirrelObject new_##classname(cppclass *ptr) { \ - if(CreateRefCountedInstance(SquirrelVM::GetVMPtr(),sqT(#classname),ptr)) { \ - HSQOBJECT o; \ - sq_getstackobj(SquirrelVM::GetVMPtr(),-1,&o); \ - SquirrelObject tmp = o; \ - sq_pop(SquirrelVM::GetVMPtr(),1); \ - return tmp; \ - } \ - return SquirrelObject() ; \ - } - -#define _RETURN_REFCOUNTED_INSTANCE(classname,ptr) \ - if(!CreateRefCountedInstance(SquirrelVM::GetVMPtr(),sqT(#classname),ptr)) { \ - return sa.ThrowError(sqT("cannot create the class instance")); \ - } \ - return 1; - -BOOL CreateRefCountedInstance(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC); -BOOL CreateRefCountedInstanceChached(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC); -SQInteger refcounted_release_hook(SQUserPointer p, SQInteger size); -SQInteger construct_RefCounted(IUnknown *p); - -#endif // SQUIRREL_BINDINGS_UTILS_WIN32_H - diff --git a/src/include/scripting/sqplus/SquirrelObject.h b/src/include/scripting/sqplus/SquirrelObject.h deleted file mode 100644 index 537001468d..0000000000 --- a/src/include/scripting/sqplus/SquirrelObject.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef _SQUIRREL_OBJECT_H_ -#define _SQUIRREL_OBJECT_H_ - -// C::B patch: Include required, so references are found -#include "sqplus.h" - -class SquirrelObject -{ - friend class SquirrelVM; -public: - SquirrelObject(); - virtual ~SquirrelObject(); - SquirrelObject(const SquirrelObject &o); - SquirrelObject(HSQOBJECT o); - SquirrelObject & operator =(const SquirrelObject &o); - SquirrelObject & operator =(SQInteger n); - void AttachToStackObject(SQInteger idx); - void Reset(void); // Release (any) reference and reset _o. - SquirrelObject Clone(); - BOOL_T SetValue(const SquirrelObject &key,const SquirrelObject &val); - - BOOL_T SetValue(SQInteger key,const SquirrelObject &val); - BOOL_T SetValue(INT_T key,bool b); // Compiler treats SQBool as INT_T. - BOOL_T SetValue(INT_T key,INT_T n); - BOOL_T SetValue(INT_T key,FLOAT_T f); - BOOL_T SetValue(INT_T key,const SQChar *s); - - BOOL_T SetValue(const SQChar *key,const SquirrelObject &val); - BOOL_T SetValue(const SQChar *key,bool b); - BOOL_T SetValue(const SQChar *key,INT_T n); - BOOL_T SetValue(const SQChar *key,FLOAT_T f); - BOOL_T SetValue(const SQChar *key,const SQChar *s); - - BOOL_T SetUserPointer(const SQChar * key,SQUserPointer up); - SQUserPointer GetUserPointer(const SQChar * key); - BOOL_T SetUserPointer(INT_T key,SQUserPointer up); - SQUserPointer GetUserPointer(INT_T key); - - BOOL_T NewUserData(const SQChar * key,INT_T size,SQUserPointer * typetag=0); - BOOL_T GetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag=0); - BOOL_T RawGetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag=0); - - // === BEGIN Arrays === - - BOOL_T ArrayResize(INT_T newSize); - BOOL_T ArrayExtend(INT_T amount); - BOOL_T ArrayReverse(void); - SquirrelObject ArrayPop(SQBool returnPoppedVal=SQTrue); - - void ArrayAppend(const SquirrelObject &o); - - template - BOOL_T ArrayAppend(T item); - - // === END Arrays === - - BOOL_T SetInstanceUP(SQUserPointer up); - BOOL_T IsNull() const; - SQInteger IsNumeric() const; - SQInteger Len() const; - BOOL_T SetDelegate(SquirrelObject &obj); - SquirrelObject GetDelegate(); - const SQChar* ToString(); - bool ToBool(); - SQInteger ToInteger(); - SQFloat ToFloat(); - SQUserPointer GetInstanceUP(SQUserPointer tag) const; - SquirrelObject GetValue(const SQChar *key) const; - BOOL_T Exists(const SQChar *key) const; - FLOAT_T GetFloat(const SQChar *key) const; - INT_T GetInt(const SQChar *key) const; - const SQChar *GetString(const SQChar *key) const; - bool GetBool(const SQChar *key) const; - SquirrelObject GetValue(INT_T key) const; - FLOAT_T GetFloat(INT_T key) const; - INT_T GetInt(INT_T key) const; - const SQChar *GetString(INT_T key) const; - bool GetBool(INT_T key) const; - SquirrelObject GetAttributes(const SQChar *key = NULL); - SQObjectType GetType(); - HSQOBJECT & GetObjectHandle(){return _o;} - BOOL_T BeginIteration(); - BOOL_T Next(SquirrelObject &key,SquirrelObject &value); - void EndIteration(); - - BOOL_T GetTypeTag(SQUserPointer * typeTag); - - // === Get the type name of item/object through string key in a table or class. Returns NULL if the type name is not set (not an SqPlus registered type). - const SQChar * GetTypeName(const SQChar * key); - // === Get the type name of item/object through INT_T key in a table or class. Returns NULL if the type name is not set (not an SqPlus registered type). - const SQChar * GetTypeName(INT_T key); - // === Get the type name of this object, else return NULL if not an SqPlus registered type. - const SQChar * GetTypeName(void); - - -private: - BOOL_T GetSlot(const SQChar *name) const; - BOOL_T RawGetSlot(const SQChar *name) const; - BOOL_T GetSlot(INT_T key) const; - HSQOBJECT _o; -}; - -struct StackHandler { - StackHandler(HSQUIRRELVM vm) { - _top = sq_gettop(vm); - this->v = vm; - } - SQFloat GetFloat(SQInteger idx) { - SQFloat x = 0.0f; - if(idx > 0 && idx <= _top) { - sq_getfloat(v,idx,&x); - } - return x; - } - SQInteger GetInt(SQInteger idx) { - SQInteger x = 0; - if(idx > 0 && idx <= _top) { - sq_getinteger(v,idx,&x); - } - return x; - } - HSQOBJECT GetObjectHandle(SQInteger idx) { - HSQOBJECT x; - if(idx > 0 && idx <= _top) { - sq_resetobject(&x); - sq_getstackobj(v,idx,&x); - } - return x; - } - const SQChar *GetString(SQInteger idx) - { - const SQChar *x = NULL; - if(idx > 0 && idx <= _top) { - sq_getstring(v,idx,&x); - } - return x; - } - SQUserPointer GetUserPointer(SQInteger idx) - { - SQUserPointer x = 0; - if(idx > 0 && idx <= _top) { - sq_getuserpointer(v,idx,&x); - } - return x; - } - SQUserPointer GetInstanceUp(SQInteger idx,SQUserPointer tag) - { - SQUserPointer self; - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&self,tag))) - return NULL; - return self; - } - SQUserPointer GetUserData(SQInteger idx,SQUserPointer tag=0) - { - SQUserPointer otag; - SQUserPointer up; - if(idx > 0 && idx <= _top) { - if(SQ_SUCCEEDED(sq_getuserdata(v,idx,&up,&otag))) { - if(tag == otag) - return up; - } - } - return NULL; - } - BOOL_T GetBool(SQInteger idx) - { - SQBool ret; - if(idx > 0 && idx <= _top) { - if(SQ_SUCCEEDED(sq_getbool(v,idx,&ret))) - return ret; - } - return FALSE; - } - SQInteger GetType(SQInteger idx) - { - if(idx > 0 && idx <= _top) { - return sq_gettype(v,idx); - } - return -1; - } - - SQInteger GetParamCount() { - return _top; - } - SQInteger Return(const SQChar *s) - { - sq_pushstring(v,s,-1); - return 1; - } - SQInteger Return(FLOAT_T f) - { - sq_pushfloat(v,f); - return 1; - } - SQInteger Return(INT_T i) - { - sq_pushinteger(v,i); - return 1; - } - SQInteger Return(bool b) - { - sq_pushbool(v,b); - return 1; - } - SQInteger Return(SQUserPointer p) { - sq_pushuserpointer(v,p); - return 1; - } - SQInteger Return(SquirrelObject &o) - { - sq_pushobject(v,o.GetObjectHandle()); - return 1; - } - SQInteger Return() { return 0; } - SQInteger ThrowError(const SQChar *error) { - return sq_throwerror(v,error); - } - HSQUIRRELVM GetVMPtr() { return v; } -private: - SQInteger _top; - HSQUIRRELVM v; -}; - -#endif //_SQUIRREL_OBJECT_H_ diff --git a/src/include/scripting/sqplus/SquirrelVM.h b/src/include/scripting/sqplus/SquirrelVM.h deleted file mode 100644 index 340e261ec1..0000000000 --- a/src/include/scripting/sqplus/SquirrelVM.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef _SQUIRREL_VM_H_ -#define _SQUIRREL_VM_H_ - -struct SquirrelError { - SquirrelError(); - SquirrelError(const SQChar* s):desc(s){} - const SQChar *desc; -}; - -struct SquirrelVMSys { - HSQUIRRELVM _VM; - SquirrelObject * _root; -}; - -// C::B patch: Add additional initilisation flags -enum SquirrelInitFlags -{ - sqifIO = 0x01, - sqifBlob = 0x02, - sqifMath = 0x04, - sqifString = 0x08, - - sqifAll = 0xFF -}; - -class SquirrelVM -{ - friend class SquirrelObject; - friend struct SquirrelError; -public: - // C::B patch: Add additional initilisation flags - static void Init(SquirrelInitFlags flags = sqifAll); - static BOOL_T IsInitialized(){return _VM == NULL?FALSE:TRUE;} - static void Shutdown(); - static void Cleanup(); - static BOOL_T Update(); //debugger and maybe GC later - static SquirrelObject CompileScript(const SQChar *s); - static SquirrelObject CompileBuffer(const SQChar *s,const SQChar * debugInfo=sqT("console_buffer")); - static SquirrelObject RunScript(const SquirrelObject &o,SquirrelObject *_this = NULL); - static void PrintFunc(HSQUIRRELVM v,const SQChar* s,...); - static BOOL_T BeginCall(const SquirrelObject &func); - static BOOL_T BeginCall(const SquirrelObject &func,SquirrelObject &_this); - static void PushParam(const SquirrelObject &o); - static void PushParam(const SQChar *s); - static void PushParam(SQInteger n); - static void PushParam(SQFloat f); - static void PushParam(SQUserPointer up); - static void PushParamNull(); - static SquirrelObject EndCall(); - static SquirrelObject CreateString(const SQChar *s); - static SquirrelObject CreateTable(); - static SquirrelObject CreateArray(SQInteger size); - static SquirrelObject CreateInstance(SquirrelObject &oclass); // oclass is an existing class. Create an 'instance' (OT_INSTANCE) of oclass. - static SquirrelObject CreateFunction(SQFUNCTION func); - static SquirrelObject CreateUserData(SQInteger size); - - static const SquirrelObject &GetRootTable(); - static HSQUIRRELVM GetVMPtr() { return _VM; } - -#if 0 - static void SetVMPtr(HSQUIRRELVM v) { - _VM = v; - } // setVMPtr -#endif - - static void GetVMSys(SquirrelVMSys & vmSys) { - vmSys._VM = _VM; - vmSys._root = _root; - } // GetVMSys - - static void SetVMSys(const SquirrelVMSys & vmSys) { - _VM = vmSys._VM; - _root = vmSys._root; - } // SetVMSys - - static void PushValue(INT_T val) { - sq_pushinteger(_VM,val); - } // PushValue - static void PushValue(FLOAT_T val) { - sq_pushfloat(_VM,val); - } // PushValue - static void PushValue(bool val) { // Compiler treats SQBool as INT_T. - sq_pushbool(_VM,val); - } // PushValue - static void PushValue(SQChar * val) { - sq_pushstring(_VM,val,-1); - } // PushValue - static void PushValue(SQUserPointer val) { - sq_pushuserpointer(_VM,val); - } // PushValue - static void PushValue(const SQChar * val) { - sq_pushstring(_VM,val,-1); - } // PushValue - static void PushObject(SquirrelObject & so) { - sq_pushobject(_VM,so._o); - } // PushObject - static void Pop(SQInteger nelemstopop) { - sq_pop(_VM,nelemstopop); - } // Pop - static void PushRootTable(void); - // Create/bind a function on the table currently on the stack. - static SquirrelObject CreateFunction(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0); - // Create/bind a function on the table so. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args. - static SquirrelObject CreateFunction(SquirrelObject & so,SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0); - // Create/bind a function to the root table. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args. - static SquirrelObject CreateFunctionGlobal(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0); - -private: - static HSQUIRRELVM _VM; - static SQInteger _CallState; - static SquirrelObject * _root; -}; - -template -inline BOOL_T SquirrelObject::ArrayAppend(T item) { - sq_pushobject(SquirrelVM::_VM,GetObjectHandle()); - SquirrelVM::PushValue(item); - BOOL_T res = sq_arrayappend(SquirrelVM::_VM,-2) == SQ_OK; - sq_pop(SquirrelVM::_VM,1); - return res; -} // ArrayAppend - -#endif //_SQUIRREL_VM_H_ - diff --git a/src/include/scripting/sqplus/sqplus.h b/src/include/scripting/sqplus/sqplus.h deleted file mode 100644 index 796e372076..0000000000 --- a/src/include/scripting/sqplus/sqplus.h +++ /dev/null @@ -1,1998 +0,0 @@ -// SqPlus.h -// Created by John Schultz 9/05/05, major update 10/05/05. -// Template function call design from LuaPlusCD by Joshua C. Jensen, -// inspired by luabind which was inspired by boost::python. -// Const argument, const member functions, and Mac OS-X changes by Simon Michelmore. -// DECLARE_INSTANCE_TYPE_NAME changes by Ben (Project5) from http://www.squirrel-lang.org/forums/. -// Added Kamaitati's changes 5/28/06. -// Free for any use. - -#ifndef _SQ_PLUS_H_ -#define _SQ_PLUS_H_ - -#include - -#ifdef __APPLE__ - #include -#else - // C::B patch: support for FreeBSD - #ifdef __FreeBSD__ - #include - #else - #include - #endif -#endif -#include -#if defined(_MSC_VER) || defined(__BORLANDC__) - #include - #ifndef UNICODE - #define SCSNPRINTF _snprintf - #define SCPUTS puts - #else - #define SCSNPRINTF _snwprintf - #define SCPUTS _putws - #endif -#else - // C::B patch: Convert conflicting _T() to sqT() --> applies to nearly *all* files! -// #define _T(n) n - #define sqT(n) n - #define SCSNPRINTF snprintf - #include // for snprintf - #define SCPUTS puts -#endif - -#if 1 -#define SQ_CALL_RAISE_ERROR SQTrue -#else -#define SQ_CALL_RAISE_ERROR SQFalse -#endif - -#include "squirrel.h" - -// C::B patch: so it builds on 64bit, ecapsulate bool/int/float using Squirrel types (this patch applies everywhere, where threse types are used) -typedef SQInteger BOOL_T; -typedef SQInteger INT_T; -typedef SQFloat FLOAT_T; -#define TRUE 1 -#define FALSE 0 - -#include "SquirrelObject.h" -#include "SquirrelVM.h" -#include "SquirrelBindingsUtils.h" - -namespace SqPlus { - -// === Class Inheritance Support === -// Inheritance in Squirrel allows one class to inherit a base class's functions and variables. -// Variables are merged: if Derived has a var name 'val' and Base has a var of the same name, -// the resulting var 'val' will take Derived's initialization value. -// Functions are not merged, and can be called via Squirrel scoping rules. - -// Define SQ_USE_CLASS_INHERITANCE to enable class inheritance support -// (requires slightly more memory and adds some CPU overhead). -// Can also be useful for debugging, as class type information is checked before -// dispatching instance function calls and before accessing instance member variables. -#define SQ_USE_CLASS_INHERITANCE - -// Comment out to turn off instance type info support (to save a small amount of memory). -#define SQ_SUPPORT_INSTANCE_TYPE_INFO - -// === Constant argument and constant member function support === -// Define SQPLUS_CONST_OPT before including SqPlus.h for constant argument + constant member function support. -// C::B patch: Enable this option -#define SQPLUS_CONST_OPT - -// === Uncomment to support std::string === -//#define SQPLUS_SUPPORT_STD_STRING - -// === Uncomment to support typedef std::basic_string sq_std_string === -//#define SQPLUS_SUPPORT_SQ_STD_STRING - -// === Uncomment to support NULL INSTANCE arguments === -//#define SQPLUS_SUPPORT_NULL_INSTANCES - -// === Uncomment to support C++ style inheritance -#define CPP_STYLE_INHERITANCE - -// === Uncomment to skip sq_argassert() === -//#define SQ_SKIP_ARG_ASSERT - -template struct TypeWrapper {}; -struct SquirrelNull {}; -struct SQAnything { void * anything; }; // Needed for binding pointers to variables (cannot dereference void *). -typedef SQAnything * SQAnythingPtr; -typedef SQChar * SQCharPtr; - -// === Do not use directly: use one of the predefined sizes below === - -struct ScriptStringVarBase { - //const unsigned char MaxLength; // Real length is MaxLength+1. - const SQInteger MaxLength; // C::B patch- to eliminate compiler warning - SQChar s[1]; - ScriptStringVarBase(SQInteger _MaxLength) : MaxLength(_MaxLength) {} - operator SQChar * () { return &s[0]; } - operator void * () { return (void *)&s[0]; } - const SQChar * operator = (const SQChar * _s) { - return safeStringCopy(s,_s,MaxLength); - } - // Special safe string copy where MaxLength is 1 less than true buffer length. - // strncpy() pads out nulls for the full length of the buffer specified by MaxLength. - static inline SQChar * safeStringCopy(SQChar * d,const SQChar * s,SQInteger MaxLength) { - SQInteger i=0; - while (s[i]) { - d[i] = s[i]; - i++; - if (i == MaxLength) break; - } // while - d[i] = 0; // Null terminate. - return d; - } // safeStringCopy -}; - -// === Do not use directly: use one of the predefined sizes below === - -template // MAXLENGTH is max printable characters (trailing NULL is accounted for in ScriptStringVarBase::s[1]). -struct ScriptStringVar : ScriptStringVarBase { - SQChar ps[MAXLENGTH]; - ScriptStringVar() : ScriptStringVarBase(MAXLENGTH) { - s[0] = 0; - } - ScriptStringVar(const SQChar * _s) : ScriptStringVarBase(MAXLENGTH) { - *this = _s; - } - const SQChar * operator = (const SQChar * _s) { - return safeStringCopy(s,_s,MaxLength); - } - const SQChar * operator = (const ScriptStringVar & _s) { - return safeStringCopy(s,_s.s,MaxLength); - } - bool operator == (const ScriptStringVar & _s) { - return _strcmp(s,_s.s) == 0; - } - bool compareCaseInsensitive(const ScriptStringVar & _s) { - return _stricmp(s,_s.s) == 0; - } -}; - -// === Fixed size strings for scripting === - -typedef ScriptStringVar<8> ScriptStringVar8; -typedef ScriptStringVar<16> ScriptStringVar16; -typedef ScriptStringVar<32> ScriptStringVar32; -typedef ScriptStringVar<64> ScriptStringVar64; -typedef ScriptStringVar<128> ScriptStringVar128; -typedef ScriptStringVar<256> ScriptStringVar256; - -// === Script Variable Types === - -enum ScriptVarType {VAR_TYPE_NONE=-1,VAR_TYPE_INT=0,VAR_TYPE_FLOAT,VAR_TYPE_BOOL,VAR_TYPE_CONST_STRING,VAR_TYPE_STRING,VAR_TYPE_USER_POINTER,VAR_TYPE_INSTANCE}; - -template -struct TypeInfo { - const SQChar * typeName; - enum {TypeID=VAR_TYPE_NONE,Size=0}; -}; - -// === Common Variable Types === - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("int")) {} - enum {TypeID=VAR_TYPE_INT,Size=sizeof(INT_T)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("float")) {} - enum {TypeID=VAR_TYPE_FLOAT,Size=sizeof(FLOAT_T)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("bool")) {} - enum {TypeID=VAR_TYPE_BOOL,Size=sizeof(BOOL_T)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("SQUserPointer")) {} - enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("SQUserPointer")) {} - enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("const SQChar *")) {} - enum {TypeID=VAR_TYPE_CONST_STRING,Size=sizeof(const SQChar *)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("ScriptStringVarBase")) {} - enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVarBase)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -// === Fixed String Variants === - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("ScriptStringVar8")) {} - enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar8)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("ScriptStringVar16")) {} - enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar16)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("ScriptStringVar32")) {} - enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar32)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("ScriptStringVar64")) {} - enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar64)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("ScriptStringVar128")) {} - enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar128)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -template<> -struct TypeInfo { - const SQChar * typeName; - TypeInfo() : typeName(sqT("ScriptStringVar256")) {} - enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar256)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } -}; - -enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2}; - -// See VarRef and ClassType<> below: for instance assignment. -typedef void (*CopyVarFunc)(void * dst,void * src); - -// === Variable references for script access === - -#define SQ_PLUS_TYPE_TABLE sqT("__SqTypes") - -struct VarRef { - // In this case 'offsetOrAddrOrConst' is simpler than using an anonymous union. - void * offsetOrAddrOrConst; // Instance member variable offset from 'this' pointer base (as size_t), or address if static variable (void *), or constant value. - ScriptVarType type; // Variable type (from enum above). - SQUserPointer instanceType; // Unique ID for the containing class instance (for instance vars only). When the var is an instance, its type is encoded in copyFunc. - CopyVarFunc copyFunc; // Function pointer to copy variables (for instance variables only). - //short size; // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length. - SQInteger size; // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length. - short access; // VarAccessType. - const SQChar * typeName; // Type name string (to create instances by name). - VarRef() : offsetOrAddrOrConst(0), type(VAR_TYPE_NONE), instanceType((SQUserPointer)-1), copyFunc(0), size(0), access(VAR_ACCESS_READ_WRITE) {} - VarRef(void * _offsetOrAddrOrConst, ScriptVarType _type, SQUserPointer _instanceType, CopyVarFunc _copyFunc, SQInteger _size,VarAccessType _access,const SQChar * _typeName) : - offsetOrAddrOrConst(_offsetOrAddrOrConst), type(_type), instanceType(_instanceType), copyFunc(_copyFunc), size(_size), access(_access), typeName(_typeName) { -#ifdef SQ_SUPPORT_INSTANCE_TYPE_INFO - SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE); - if (typeTable.IsNull()) { - typeTable = SquirrelVM::CreateTable(); - SquirrelObject root = SquirrelVM::GetRootTable(); - root.SetValue(SQ_PLUS_TYPE_TABLE,typeTable); - } // if - typeTable.SetValue(INT_T((size_t)copyFunc),typeName); -#endif - } -}; - -typedef VarRef * VarRefPtr; - -// Internal use only. -inline void getVarNameTag(SQChar * buff,INT_T maxSize,const SQChar * scriptName) { -// assert(maxSize > 3); -#if 1 - SQChar * d = buff; - d[0] = '_'; - d[1] = 'v'; - d = &d[2]; - maxSize -= (2+1); // +1 = space for null. - SQInteger pos=0; - while (scriptName[pos] && pos < maxSize) { - d[pos] = scriptName[pos]; - pos++; - } // while - d[pos] = 0; // null terminate. -#else - SCSNPRINTF(buff,maxSize,sqT("_v%s"),scriptName); -#endif -} // getVarNameTag - -// Internal use only. -SQInteger setVarFunc(HSQUIRRELVM v); -SQInteger getVarFunc(HSQUIRRELVM v); -SQInteger setInstanceVarFunc(HSQUIRRELVM v); -SQInteger getInstanceVarFunc(HSQUIRRELVM v); - -// === BEGIN Helpers === - -inline void createTableSetGetHandlers(SquirrelObject & so) { - SquirrelObject delegate = so.GetDelegate(); - if (!delegate.Exists(sqT("_set"))) { - delegate = SquirrelVM::CreateTable(); - SquirrelVM::CreateFunction(delegate,setVarFunc,sqT("_set"),sqT("sn|b|s")); // String var name = number(SQInteger or float) or bool or string. - SquirrelVM::CreateFunction(delegate,getVarFunc,sqT("_get"),sqT("s")); // String var name. - so.SetDelegate(delegate); - } // if -} // createTableSetGetHandlers - -inline VarRefPtr createVarRef(SquirrelObject & so,const SQChar * scriptVarName) { - VarRefPtr pvr=0; - ScriptStringVar256 scriptVarTagName; getVarNameTag(scriptVarTagName,sizeof(scriptVarTagName),scriptVarName); - if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) { - so.NewUserData(scriptVarTagName,sizeof(*pvr)); - if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) throw SquirrelError(sqT("Could not create UserData.")); - } // if - return pvr; -} // createVarRef - -template -void validateConstantType(T /*constant*/) { - switch(TypeInfo()) { - case VAR_TYPE_INT: - case VAR_TYPE_FLOAT: - case VAR_TYPE_BOOL: - case VAR_TYPE_CONST_STRING: - break; - default: - throw SquirrelError(sqT("validateConstantType(): type must be INT, FLOAT, BOOL, or CONST CHAR *.")); - } // case -} // validateConstantType - -inline void createInstanceSetGetHandlers(SquirrelObject & so) { - if (!so.Exists(sqT("_set"))) { - SquirrelVM::CreateFunction(so,setInstanceVarFunc,sqT("_set"),sqT("sn|b|s|x")); // String var name = number(SQInteger or float) or bool or string or instance. - SquirrelVM::CreateFunction(so,getInstanceVarFunc,sqT("_get"),sqT("s")); // String var name. - } // if -} // createInstanceSetGetHandlers - -// === END Helpers === - -// === Class Type Helper class: returns a unique number for each class type === - -template -struct ClassType { - static SQUserPointer type(void) { return (SQUserPointer)© } - static CopyVarFunc getCopyFunc(void) { return (CopyVarFunc)© } - static void copy(T * dst,T * src) { - *dst = *src; - } // copy -}; - -// === Bind a global or pre-allocated (not instance) class member variable or constant (for tables only (not classes)) === - -template -void BindVariable(SquirrelObject & so,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) { - VarRefPtr pvr = createVarRef(so,scriptVarName); - *pvr = VarRef(var,TypeInfo(),0,ClassType::getCopyFunc(),sizeof(*var),access,TypeInfo().typeName); - createTableSetGetHandlers(so); -} // BindVariable - -// === Bind a constant by value: INT_T, FLOAT_T, BOOL_T, or CONST CHAR * (for tables only (not classes)) === - -template -void BindConstant(SquirrelObject & so,T constant,const SQChar * scriptVarName) { - validateConstantType(constant); - VarRefPtr pvr = createVarRef(so,scriptVarName); - // C::B patch: Handler for newer compilers -#if __cplusplus>=201103L - static_assert(sizeof(constant)<=sizeof(void*), "using larger type"); -#endif - void *ptr = reinterpret_cast(constant); - *pvr = VarRef(ptr,TypeInfo(),0,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo().typeName); - createTableSetGetHandlers(so); -} // BindConstant - -template -void BindVariable(T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) { - SquirrelObject so = SquirrelVM::GetRootTable(); - BindVariable(so,var,scriptVarName,access); -} // BindVariable - -template -void BindConstant(T constant,const SQChar * scriptVarName) { - SquirrelObject so = SquirrelVM::GetRootTable(); - BindConstant(so,constant,scriptVarName); -} // BindConstant - -// === Register a class instance member variable or constant. var argument provides type and offset ( effectively &((ClassType *)0)->var ) === - -// classType is the type of the member variable's containing class. -template -void RegisterInstanceVariable(SquirrelObject & so,SQUserPointer classType,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) { - VarRef * pvr = createVarRef(so,scriptVarName); - void * offsetOrAddrOrConst = (void *)var; // var must be passed in as &obj->var, where obj = 0 (the address is the offset), or as static/global address. - *pvr = VarRef(offsetOrAddrOrConst,TypeInfo(),classType,ClassType::getCopyFunc(),sizeof(*var),access,TypeInfo().typeName); - createInstanceSetGetHandlers(so); -} // RegisterInstanceVariable - -template -void RegisterInstanceConstant(SquirrelObject & so,SQUserPointer classType,T constant,const SQChar * scriptVarName) { - validateConstantType(constant); - VarRef * pvr = createVarRef(so,scriptVarName); - struct CV { - T var; - size_t pad; - } cv; // Cast Variable helper. - cv.var = constant; - *pvr = VarRef(*(void **)&cv,TypeInfo(),classType,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo().typeName); - createInstanceSetGetHandlers(so); -} // RegisterInstanceConstant - -////////////////////////////////////////////////////////////////////////// -/////////// BEGIN Generalized Class/Struct Instance Support ////////////// -////////////////////////////////////////////////////////////////////////// - -//BOOL_T CreateNativeClassInstance(HSQUIRRELVM v,const SQChar * classname,SQUserPointer ud,SQRELEASEHOOK hook); // In SquirrelBindingUtils.cpp. - -// Create native class instance and leave on stack. -inline BOOL_T CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className) { - SQInteger oldtop = sq_gettop(v); - sq_pushroottable(v); - sq_pushstring(v,className,-1); - if (SQ_FAILED(sq_rawget(v,-2))) { // Get the class (created with sq_newclass()). - sq_settop(v,oldtop); - return FALSE; - } // if -#if 0 - sq_remove(v,-3); // Remove the root table. - sq_push(v,1); // Push the 'this'. -#else // Kamaitati's change. 5/28/06 jcs. - sq_remove(v,-2); // Remove the root table. - sq_pushroottable(v); // Push the 'this'. -#endif - if (SQ_FAILED(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR))) { // Call ClassName(): creates new instance and calls constructor (instead of sq_createinstance() where constructor is not called). - sq_settop(v,oldtop); - return FALSE; - } // if - sq_remove(v,-2); // Remove the class. - // SQInteger newtop = sq_gettop(v); - return TRUE; -} // CreateConstructNativeClassInstance - -// Create new instance, copy 'classToCopy', and store result on stack. -template -inline BOOL_T CreateCopyInstance(const SQChar * className,const T & classToCopy) { - HSQUIRRELVM v = SquirrelVM::GetVMPtr(); - if (!CreateConstructNativeClassInstance(v,className)) { - return FALSE; - } // if - SQUserPointer up=0; - sq_getinstanceup(v,-1,&up,ClassType::type()); - if (!up) return FALSE; - T * newClass = (T *)up; - *newClass = classToCopy; // Optimized version that uses the copy constructor. - return TRUE; -} // CreateCopyInstance - -// Create a new copy of type 'className' and copy 'classToCopy', return result via SquirrelObject. -template -inline SquirrelObject NewClassCopy(const SQChar * className,const T & classToCopy) { - SquirrelObject ret; - if (CreateCopyInstance(className,classToCopy)) { - ret.AttachToStackObject(-1); - sq_poptop(SquirrelVM::GetVMPtr()); - } else { - throw SquirrelError(sqT("NewClassCopy(): could not create class")); - } // if - return ret; -} // NewClassCopy - -// Return a new class copy on the stack from a varArgs function call. -template -inline SQInteger ReturnCopy(HSQUIRRELVM v,const T & classToCopy) { - SquirrelObject so(NewClassCopy(GetTypeName(classToCopy),classToCopy)); - return StackHandler(v).Return(so); -} // ReturnCopy - -// Katsuaki Kawachi's GetInstance<> exception change. 6/27/06 jcs - -// Get an instance of type T from the stack at idx (for function calls). -template -T * GetInstance(HSQUIRRELVM v,SQInteger idx) { - SQUserPointer up=0; - sq_getinstanceup(v,idx,&up,ClassType::type()); - if (ExceptionOnError) { // This code block should be compiled out when ExceptionOnError is false. In any case, the compiler should not generate a test condition (include or exclude the enclosed code block). - if (!up) throw SquirrelError(sqT("GetInstance: Invalid argument type")); - } // if - return (T *)up; -} // GetInstance - -// NAME and macro changes from Ben's (Project5) forum post. 2/26/06 jcs -// Kamaitati's NULL_INSTANCE support. 5/28/06 jcs - -#ifdef SQPLUS_SUPPORT_NULL_INSTANCES - -#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \ - inline const SQChar * GetTypeName(const TYPE & /*n*/) { return sqT(#NAME); } \ - inline void Push(HSQUIRRELVM v,TYPE * value) { \ - if (!value) sq_pushnull(v); \ - else if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) \ - throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \ - inline void Push(HSQUIRRELVM /*v*/,TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \ - inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return GetInstance(v,idx) != NULL; } \ - inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { \ - return (sq_gettype(v,idx)==OT_NULL) || (GetInstance(v,idx) != NULL); } \ - inline TYPE & Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return *GetInstance(v,idx); } \ - inline TYPE * Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { \ - if (sq_gettype(v,idx)==OT_NULL) return NULL; \ - return GetInstance(v,idx); } \ - template<> \ - struct TypeInfo { \ - const SQChar * typeName; \ - TypeInfo() : typeName(sqT(#NAME)) {} \ - enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \ - operator ScriptVarType() { return ScriptVarType(TypeID); } \ - }; \ -} // nameSpace SqPlus - -#else - -#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \ - inline const SQChar * GetTypeName(const TYPE & /*n*/) { return sqT(#NAME); } \ - inline void Push(HSQUIRRELVM v,TYPE * value) { if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \ - inline void Push(HSQUIRRELVM /*v*/,TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \ - inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return GetInstance(v,idx) != NULL; } \ - inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return GetInstance(v,idx) != NULL; } \ - inline TYPE & Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return *GetInstance(v,idx); } \ - inline TYPE * Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return GetInstance(v,idx); } \ - template<> \ - struct TypeInfo { \ - const SQChar * typeName; \ - TypeInfo() : typeName(sqT(#NAME)) {} \ - enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \ - operator ScriptVarType() { return ScriptVarType(TypeID); } \ - }; \ -} // nameSpace SqPlus - -#endif - -// TYPE or NAME below must match the string name used in SqClassDef<>, otherwise name lookup won't match and Squirrel will throw a "can't create instance" error. -#ifndef SQPLUS_CONST_OPT -#define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_(TYPE,TYPE) -#define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) -#else -#define SQPLUS_DECLARE_INSTANCE_TYPE_CONST -#include "SqPlusConst.h" -#endif - -////////////////////////////////////////////////////////////////////////// -//////////// END Generalized Class/Struct Instance Support /////////////// -////////////////////////////////////////////////////////////////////////// - -#ifndef SQ_SKIP_ARG_ASSERT - #define sq_argassert(arg,_index_) if (!Match(TypeWrapper(),v,_index_)) return sq_throwerror(v,sqT("Incorrect function argument")) -#else - #define sq_argassert(arg,_index_) -#endif - -// === Return value variants === - -template -struct ReturnSpecialization { - - // === Standard Function calls === - - static SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger /*index*/) { - RT ret = func(); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - RT ret = func( - Get(TypeWrapper(),v,index + 0) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - RT ret = func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - RT ret = func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - RT ret = func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - RT ret = func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - RT ret = func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - sq_argassert(7,index + 6); - RT ret = func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5), - Get(TypeWrapper(),v,index + 6) - ); - Push(v,ret); - return 1; - } - - // === Member Function calls === - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(),HSQUIRRELVM v,SQInteger /*index*/) { - RT ret = (callee.*func)(); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5) - ); - Push(v,ret); - return 1; - } - - template - static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - sq_argassert(7,index + 6); - RT ret = (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5), - Get(TypeWrapper(),v,index + 6) - ); - Push(v,ret); - return 1; - } - -#ifdef SQPLUS_CONST_OPT -#define SQPLUS_CALL_CONST_MFUNC_RET0 -#include "SqPlusConst.h" -#endif -}; - -// === No return value variants === - -template<> -struct ReturnSpecialization { - - // === Standard function calls === - - static SQInteger Call(void (*func)(),HSQUIRRELVM v,SQInteger /*index*/) { - (void)v; - func(); - return 0; - } - - template - static SQInteger Call(void (*func)(P1),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - func( - Get(TypeWrapper(),v,index + 0) - ); - return 0; - } - - template - static SQInteger Call(void (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1) - ); - return 0; - } - - template - static SQInteger Call(void (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2) - ); - return 0; - } - - template - static SQInteger Call(void (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3) - ); - return 0; - } - - template - static SQInteger Call(void (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4) - ); - return 0; - } - - template - static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5) - ); - return 0; - } - - template - static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - sq_argassert(7,index + 6); - func( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5), - Get(TypeWrapper(),v,index + 6) - ); - return 0; - } - - // === Member function calls === - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(),HSQUIRRELVM,SQInteger /*index*/) { - (callee.*func)(); - return 0; - } - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - (callee.*func)( - Get(TypeWrapper(),v,index + 0) - ); - return 0; - } - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1) - ); - return 0; - } - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2) - ); - return 0; - } - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3) - ); - return 0; - } - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4) - ); - return 0; - } - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5) - ); - return 0; - } - - template - static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) { - sq_argassert(1,index + 0); - sq_argassert(2,index + 1); - sq_argassert(3,index + 2); - sq_argassert(4,index + 3); - sq_argassert(5,index + 4); - sq_argassert(6,index + 5); - sq_argassert(7,index + 6); - (callee.*func)( - Get(TypeWrapper(),v,index + 0), - Get(TypeWrapper(),v,index + 1), - Get(TypeWrapper(),v,index + 2), - Get(TypeWrapper(),v,index + 3), - Get(TypeWrapper(),v,index + 4), - Get(TypeWrapper(),v,index + 5), - Get(TypeWrapper(),v,index + 6) - ); - return 0; - } - -#ifdef SQPLUS_CONST_OPT -#define SQPLUS_CALL_CONST_MFUNC_NORET -#include "SqPlusConst.h" -#endif - -}; - -// === STANDARD Function return value specialized call handlers === - -template -SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -template -SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -template -SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -template -SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -template -SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -template -SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -template -SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -template -SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(func,v,index); -} - -// === MEMBER Function return value specialized call handlers === - -template -SQInteger Call(Callee & callee, RT (Callee::*func)(),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -template -SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) { - return ReturnSpecialization::Call(callee,func,v,index); -} - -#ifdef SQPLUS_CONST_OPT -#define SQPLUS_CALL_CONST_MFUNC_RET1 -#include "SqPlusConst.h" -#endif - -// === Direct Call Standard Function handler === - -template -struct DirectCallFunction { - static inline SQInteger Dispatch(HSQUIRRELVM v) { - StackHandler sa(v); - SQInteger paramCount = sa.GetParamCount(); - Func * func = (Func *)sa.GetUserData(paramCount); - return Call(*func,v,2); - } // Dispatch -}; - -// === Direct Call Member Function handler === - -template -class DirectCallMemberFunction { -public: - static inline SQInteger Dispatch(HSQUIRRELVM v) { - StackHandler sa(v); - SQInteger paramCount = sa.GetParamCount(); - unsigned char * ud = (unsigned char *)sa.GetUserData(paramCount); - // C::B patch: Handle invalid instance type here - if (!*(Callee**)ud) { - return sq_throwerror(v,sqT("Invalid Instance Type")); - } // if - return Call(**(Callee**)ud,*(Func*)(ud + sizeof(Callee*)),v,2); - } // Dispatch -}; - -// === Direct Call Instance Member Function handler === - -#define SQ_CLASS_OBJECT_TABLE_NAME sqT("__ot") -#define SQ_CLASS_HIER_ARRAY sqT("__ca") - -template -class DirectCallInstanceMemberFunction { -public: - static inline SQInteger Dispatch(HSQUIRRELVM v) { - StackHandler sa(v); - Callee * instance = (Callee *)sa.GetInstanceUp(1,0); - SQInteger paramCount = sa.GetParamCount(); - Func * func = (Func *)sa.GetUserData(paramCount); - // C::B patch: Let the compiler search (comment out the whole block) -//#ifdef SQ_USE_CLASS_INHERITANCE -// SquirrelObject so(sa.GetObjectHandle(1)); // 'this' -// SQUserPointer typetag; so.GetTypeTag(&typetag); -// SQUserPointer calleeType = ClassType::type(); -// if (typetag != calleeType) { -// SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); -// instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType::type())); // 64-bit compatible version. -// if (!instance) { -// return sq_throwerror(v,sqT("Invalid Instance Type")); -// } // if -// } // if -//#endif - // C::B patch: If not instance -> return Ok anyways - if (!instance) - return SQ_OK; - return Call(*instance,*func,v,2); - } // Dispatch -}; - -// === Direct Call Instance Member Function Variable Argument handler === - -template -class DirectCallInstanceMemberFunctionVarArgs { -public: - typedef SQInteger (Callee::*FuncType)(HSQUIRRELVM); - static inline SQInteger Dispatch(HSQUIRRELVM v) { - StackHandler sa(v); - Callee * instance = (Callee *)sa.GetInstanceUp(1,0); - SQInteger paramCount = sa.GetParamCount(); - FuncType func = *(FuncType *)sa.GetUserData(paramCount); - // C::B patch: Let the compiler search (comment out the whole block) -//#ifdef SQ_USE_CLASS_INHERITANCE -// SquirrelObject so(sa.GetObjectHandle(1)); // 'this' -// SQUserPointer typetag; so.GetTypeTag(&typetag); -// SQUserPointer calleeType = ClassType::type(); -// if (typetag != calleeType) { -// SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); -// instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType::type())); // 64-bit compatible version. -// if (!instance) { -// return sq_throwerror(v,sqT("Invalid Instance Type")); -// } // if -// } // if -//#endif - sq_poptop(v); // Remove UserData from stack: so sa.GetParamCount() returns actual param count. - // C::B patch: If not instance -> return Ok anyways - if (!instance) - return SQ_OK; - return (instance->*func)(v); - } // Dispatch -}; - -// Code fragment useful for debugging new implementations. -#if 0 -HSQOBJECT ho = sa.GetObjectHandle(paramCount); -SquirrelObject so(ho); -SQObjectType sot = so.GetType(); -#endif - -// === Standard function call === - -template -inline void sq_pushdirectclosure(HSQUIRRELVM v,Func func,SQUnsignedInteger nupvalues) { - SQUserPointer up = sq_newuserdata(v,sizeof(func)); // Also pushed on stack. - memcpy(up,&func,sizeof(func)); - sq_newclosure(v,DirectCallFunction::Dispatch,nupvalues+1); -} // sq_pushdirectclosure - -// === Fixed Class pointer call (always calls with object pointer that was registered) === - -template -inline void sq_pushdirectclosure(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) { - unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(Callee*)+sizeof(func)); // Also pushed on stack. - const SQUserPointer pCallee = (SQUserPointer)&callee; - memcpy(up,&pCallee,sizeof(Callee*)); - memcpy(up + sizeof(Callee*),&func,sizeof(func)); - sq_newclosure(v,DirectCallMemberFunction::Dispatch,nupvalues+1); -} // sq_pushdirectclosure - -// === Class Instance call: class pointer retrieved from script class instance === - -template -inline void sq_pushdirectinstanceclosure(HSQUIRRELVM v,const Callee & /*callee*/,Func func,SQUnsignedInteger nupvalues) { - unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack. - memcpy(up,&func,sizeof(func)); - sq_newclosure(v,DirectCallInstanceMemberFunction::Dispatch,nupvalues+1); -} // sq_pushdirectinstanceclosure - -// === Class Instance call: class pointer retrieved from script class instance (variable arguments) === - -template -inline void sq_pushdirectinstanceclosurevarargs(HSQUIRRELVM v,const Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),SQUnsignedInteger nupvalues) { - unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack. - memcpy(up,&func,sizeof(func)); - sq_newclosure(v,DirectCallInstanceMemberFunctionVarArgs::Dispatch,nupvalues+1); -} // sq_pushdirectinstanceclosurevarargs - -// === Register a STANDARD function (table or class on stack) === - -template -inline void Register(HSQUIRRELVM v,Func func,const SQChar * name) { - sq_pushstring(v,name,-1); - sq_pushdirectclosure(v,func,0); - sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call). -} // Register - -// === Register a MEMBER function (table or class on stack) === - -template -inline void Register(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) { - sq_pushstring(v,name,-1); - sq_pushdirectclosure(v,callee,func,0); - sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call). -} // Register - -// === Register a STANDARD global function (root table) === - -template -inline void RegisterGlobal(HSQUIRRELVM v,Func func,const SQChar * name) { - sq_pushroottable(v); - Register(v,func,name); - sq_poptop(v); // Remove root table. -} // RegisterGlobal - -template -inline void RegisterGlobal(Func func,const SQChar * name) { - RegisterGlobal(SquirrelVM::GetVMPtr(),func,name); -} // RegisterGlobal - -// === Register a MEMBER global function (root table) === - -template -inline void RegisterGlobal(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) { - sq_pushroottable(v); - Register(v,callee,func,name); - sq_poptop(v); // Remove root table. -} // RegisterGlobal - -template -inline void RegisterGlobal(Callee & callee,Func func,const SQChar * name) { - RegisterGlobal(SquirrelVM::GetVMPtr(),callee,func,name); -} // RegisterGlobal - -// === Register a STANDARD function (hso is table or class) === - -template -inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Func func,const SQChar * name) { - sq_pushobject(v,hso); - Register(v,func,name); - sq_poptop(v); // Remove hso. -} // Register - -// === Register a MEMBER function (hso is table or class) === -// === Fixed Class pointer call (always calls with object pointer that was registered) === - -template -inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Callee & callee,Func func,const SQChar * name) { - sq_pushobject(v,hso); - Register(v,callee,func,name); - sq_poptop(v); // Remove hso. -} // Register - -// === Register an INSTANCE MEMBER function === -// === Class Instance call: class pointer retrieved from script class instance === - -template -inline void RegisterInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Func func,const SQChar * name) { - sq_pushobject(v,hclass); - sq_pushstring(v,name,-1); - sq_pushdirectinstanceclosure(v,callee,func,0); - sq_createslot(v,-3); - sq_poptop(v); // Remove hclass. -} // RegisterInstance - - -#ifdef _MSC_VER -#pragma warning(disable : 4995) // Deprecated _snprintf -#endif - -// === Register an INSTANCE MEMBER function Variable Arguments === -// typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case). -// All the other Squirrel type-masks are passed normally. - -template -inline void RegisterInstanceVarArgs(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),const SQChar * name,const SQChar * typeMask=sqT("*")) { - sq_pushobject(v,hclass); - sq_pushstring(v,name,-1); - sq_pushdirectinstanceclosurevarargs(v,callee,func,0); - SQChar tm[64]; - SQChar * ptm = tm; - SQInteger numParams = SQ_MATCHTYPEMASKSTRING; - if (typeMask) { - if (typeMask[0] == '*') { - ptm = 0; // Variable args: don't check parameters. -// numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()). - } else { - if (SCSNPRINTF(tm,sizeof(tm),sqT("x%s"),typeMask) < 0) { // Must be an instance. - throw SquirrelError(sqT("RegisterInstanceVarArgs: typeMask string too long.")); - } // if - } // if - } else { // Need to check object type on stack: table, class, instance, etc. -// _snprintf(tm,sizeof(tm),"x"); // instance. - tm[0] = 'x'; - tm[1] = 0; - } // if - if (ptm) { // If ptm == 0, don't check type. - sq_setparamscheck(v,numParams,ptm); // Determine arg count from type string. - } // if -#ifdef _DEBUG - sq_setnativeclosurename(v,-1,name); // For debugging only. -#endif - sq_createslot(v,-3); - sq_poptop(v); // Remove hclass. -} // RegisterInstanceVarArgs - -#ifdef _MSC_VER -#pragma warning(default : 4995) -#endif - -// === Call Squirrel Functions from C/C++ === -// No type checking is performed for Squirrel functions as Squirrel types are dynamic: -// Incoming types are passed unchanged to Squirrel functions. The parameter count is checked: an exception is thrown if mismatched. -// Return values must match the RT template argument type, else an exception can be thrown on return. - -template -struct SquirrelFunction { - HSQUIRRELVM v; - SquirrelObject object; // Table or class. - SquirrelObject func; - SquirrelFunction() : v(0) {} - SquirrelFunction(HSQUIRRELVM _v,const SquirrelObject & _object,const SquirrelObject & _func) : v(_v), object(_object), func(_func) {} - SquirrelFunction(const SquirrelObject & _object,const SquirrelObject & _func) : v(SquirrelVM::GetVMPtr()), object(_object), func(_func) {} - SquirrelFunction(const SquirrelObject & _object,const SQChar * name) { - v = SquirrelVM::GetVMPtr(); - object = _object; - func = object.GetValue(name); - } - SquirrelFunction(const SQChar * name) { - v = SquirrelVM::GetVMPtr(); - object = SquirrelVM::GetRootTable(); - func = object.GetValue(name); - } - - // Release references and reset internal objects to null. - void reset(void) { - func.Reset(); - object.Reset(); - } // Reset - -#define SQPLUS_CHECK_FNCALL(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("SquirrelFunction<> call failed")) - - RT operator()(void) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - SQPLUS_CHECK_FNCALL(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - - template - RT operator()(P1 p1) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - Push(v,p1); - SQPLUS_CHECK_FNCALL(sq_call(v,2,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - - template - RT operator()(P1 p1,P2 p2) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - Push(v,p1); - Push(v,p2); - SQPLUS_CHECK_FNCALL(sq_call(v,3,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - - template - RT operator()(P1 p1,P2 p2,P3 p3) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - Push(v,p1); - Push(v,p2); - Push(v,p3); - SQPLUS_CHECK_FNCALL(sq_call(v,4,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - - template - RT operator()(P1 p1,P2 p2,P3 p3,P4 p4) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - Push(v,p1); - Push(v,p2); - Push(v,p3); - Push(v,p4); - SQPLUS_CHECK_FNCALL(sq_call(v,5,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - - template - RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - Push(v,p1); - Push(v,p2); - Push(v,p3); - Push(v,p4); - Push(v,p5); - SQPLUS_CHECK_FNCALL(sq_call(v,6,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - - template - RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - Push(v,p1); - Push(v,p2); - Push(v,p3); - Push(v,p4); - Push(v,p5); - Push(v,p6); - SQPLUS_CHECK_FNCALL(sq_call(v,7,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - - template - RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7) { - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,object.GetObjectHandle()); - Push(v,p1); - Push(v,p2); - Push(v,p3); - Push(v,p4); - Push(v,p5); - Push(v,p6); - Push(v,p7); - SQPLUS_CHECK_FNCALL(sq_call(v,8,SQTrue,SQ_CALL_RAISE_ERROR)); - return GetRet(TypeWrapper(),v,-1); - } - -}; - -// === Class/Struct registration === - -#define SQ_DELETE_CLASS(CLASSTYPE) if (up) { CLASSTYPE * self = (CLASSTYPE *)up; delete self;} return 0 -#define SQ_DECLARE_RELEASE(CLASSTYPE) \ - static SQInteger release(SQUserPointer up, SQInteger /*size*/) { \ - SQ_DELETE_CLASS(CLASSTYPE); \ - } - -template -struct ReleaseClassPtrPtr { - static SQInteger release(SQUserPointer up,SQInteger size) { - if (up) { - T ** self = (T **)up; - delete *self; - } // if - return 0; - } // release -}; - -template -struct ReleaseClassPtr { - static SQInteger release(SQUserPointer up,SQInteger size) { - if (up) { - T * self = (T *)up; - delete self; - } // if - return 0; - } // release -}; - -BOOL_T CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName=0); - -#define SQ_ANCESTOR_CLASS_INDEX sqT("__ci") - -// Call PostConstruct() at the end of custom constructors. -template -inline SQInteger PostConstruct(HSQUIRRELVM v,T * newClass,SQRELEASEHOOK hook) { -#ifdef SQ_USE_CLASS_INHERITANCE - StackHandler sa(v); - HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE - SquirrelObject instance(ho); - INT_T classIndex = instance.GetValue(SQ_ANCESTOR_CLASS_INDEX).ToInteger(); - if (classIndex == -1) { // Is this the most-derived C/C++ class? If so, create all ancestors (if present). - - SquirrelObject newObjectTable = SquirrelVM::CreateTable(); // 11/2/05: Create a new table for this instance. - newObjectTable.SetUserPointer(INT_T((size_t)ClassType::type()),newClass); // 64-bit compatible version. - instance.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,newObjectTable); - - SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY); - INT_T count = classHierArray.Len(); - if (count > 1) { // This will be true when more than one C/C++ class is in the hierarchy. - --count; // Skip the most-derived class. - for (INT_T i=0; i < count; i++) { -#ifdef CPP_STYLE_INHERITANCE // Kamaitati's changes for C++ inheritance support. jcs 5/28/06 - SquirrelObject so = classHierArray.GetValue(i); - sq_pushobject(v,so.GetObjectHandle()); - SQUserPointer typeTag; - sq_gettypetag(v,-1,&typeTag); - newObjectTable.SetUserPointer(INT_T(size_t(typeTag)),newClass); - sq_poptop(v); -#else - instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,i); // Store ancestor class index for recursive constructor calls to come. - INT_T top = sq_gettop(v); - SquirrelObject so = classHierArray.GetValue(i); // Need to create UserData struct: store pointer to class, set release hook. - SquirrelObject func = so.GetValue(sqT("constructor")); - sq_pushobject(v,func.GetObjectHandle()); - sq_pushobject(v,instance.GetObjectHandle()); // The 'instance' is the real Squirrel 'this' for all ancestors (as opposed to an instance created from the defining class, which does not happen). - sq_call(v,1,SQFalse,SQ_CALL_RAISE_ERROR); // Call constructor: no arguments are passed other than the 'instance'. - sq_settop(v,top); -#endif - } // for - instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,SquirrelObject()); // Store an OT_NULL object to free SQ_ANCESTOR_CLASS_INDEX var. - } // if - } else { // Ancestor: Construct class and set release hook. - - SquirrelObject objectTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); // 11/2/05: Get the existing object table. - objectTable.SetUserPointer(INT_T((size_t)ClassType::type()),newClass); // 64-bit compatible version. - - INT_T top = sq_gettop(v); - T ** ud = (T **)sq_newuserdata(v,sizeof(T *)); // Create UserData and push onto stack. - *ud = newClass; - // C::B patch: Disable releasing of objects (due to private/protected dtors) (Note: This is evil, but no other possibility found.) -// sq_setreleasehook(v,-1,ReleaseClassPtrPtr::release); // Set release hook for UserData on stack. - SquirrelObject userData; - userData.AttachToStackObject(-1); - SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY); - classHierArray.SetValue(classIndex,userData); // Replace the class entry with UserData: will be freed during most-derived class destruction. - sq_settop(v,top); - return TRUE; - } // if -#endif - sq_setinstanceup(v,1,newClass); - sq_setreleasehook(v,1,hook); - return 1; -} // PostConstruct - -template -struct ConstructReleaseClass { - static SQInteger construct(HSQUIRRELVM v) { - return PostConstruct(v,new T(),release); - } // construct - // C::B patch: Add empty constructor - static SQInteger no_construct(HSQUIRRELVM v) { - return PostConstruct(v,0,0); - } // no_construct - SQ_DECLARE_RELEASE(T) -}; - -template -inline SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,const SQChar * baseScriptClassName=0) { - SQInteger top = sq_gettop(v); - SquirrelObject newClass; - if (CreateClass(v,newClass,(SQUserPointer)ClassType::type(),scriptClassName,baseScriptClassName)) { - SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass::no_construct,sqT("constructor")); -#ifdef SQ_USE_CLASS_INHERITANCE - // New member vars cannot be added to instances (OT_INSTANCE): additions must occur on the defining class (OT_CLASS), before any instances are instantiated. - if (!newClass.Exists(SQ_CLASS_OBJECT_TABLE_NAME)) { // Will always get table from most-derived registered class. - SquirrelObject objectTable = SquirrelVM::CreateTable(); - newClass.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable); // Constructors must add their 'this' pointer indexed by type to this table. See PostConstruct() above. - // 11/2/05: This table will behave as a static global for each instance unless overwritten during construction (see PostConstruct() above). - } // if - SquirrelObject classHierArray; - if (!newClass.Exists(SQ_CLASS_HIER_ARRAY)) { // Will always get table from most-derived registered class. - classHierArray = SquirrelVM::CreateArray(0); // The only constructor called will be the most-derived class: this array contains all classes in the hierarchy to be constructed. - newClass.SetValue(SQ_CLASS_HIER_ARRAY,classHierArray); - } else { - classHierArray = newClass.GetValue(SQ_CLASS_HIER_ARRAY); - } // if - classHierArray.ArrayAppend(newClass); // Add the class to the hierarchy array. The array values will be released and replaced with UserData to free created ancestor classes. - // C::B patch for 64bit builds - newClass.SetValue(SQ_ANCESTOR_CLASS_INDEX,(SQInteger)-1); // When the class hierarchy is created, this var will be used to help in recursively creating ancestor classes. -#endif - } // if - sq_settop(v,top); - return newClass; -} // RegisterClassType - -// === Define and register a C++ class and its members for use with Squirrel === -// Constructors+destructors are automatically created. Custom constructors must use the -// standard SQFUNCTION signature if variable argument types are required (overloads). -// See testSqPlus2.cpp for examples. - -template -struct SQClassDef { - HSQUIRRELVM v; - const SQChar * name; - const SQChar * base; - SquirrelObject newClass; - -#ifdef SQ_USE_CLASS_INHERITANCE - // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM). - SQClassDef(HSQUIRRELVM _v,const SQChar * _name,const SQChar * _base=0) : v(_v), name(_name), base(_base) { - newClass = RegisterClassType(v,name,base); - } - // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM). - SQClassDef(const SQChar * _name,const SQChar * _base=0) : name(_name), base(_base) { - v = SquirrelVM::GetVMPtr(); - newClass = RegisterClassType(v,name,base); - } -#else - SQClassDef(HSQUIRRELVM _v,const SQChar * _name) : v(_v), name(_name) { - newClass = RegisterClassType(v,name); - } - - SQClassDef(const SQChar * _name) : name(_name) { - v = SquirrelVM::GetVMPtr(); - newClass = RegisterClassType(v,name); - } -#endif - - // C::B patch: Add empty constructor - SQClassDef & emptyCtor() { - SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass::construct,sqT("constructor")); - return *this; - } // emptyCtor - - // Register a member function. - template - SQClassDef & func(Func pfunc,const SQChar * name_) { - RegisterInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_); - return *this; - } // func - - // Register a variable-argument member function (supports variable+multiple return values). - // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case). - // All the other Squirrel type-masks are passed normally. - template - SQClassDef & funcVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) { - RegisterInstanceVarArgs(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_,typeMask); - return *this; - } // funcVarArgs - - // === BEGIN static-member+global function registration === - - // === This version is for static member functions only, such as custom constructors where 'this' is not yet valid === - // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case). - // All the other Squirrel type-masks are passed normally. - - template - SQClassDef & staticFuncVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) { - SquirrelVM::PushObject(newClass); - SquirrelVM::CreateFunction(pfunc,name_,typeMask); - SquirrelVM::Pop(1); - return *this; - } // staticFuncVarArgs - - // Register a standard global function (effectively embedding a global function in TClassType's script namespace: does not need or use a 'this' pointer). - template - SQClassDef & staticFunc(Func pfunc,const SQChar * name_) { - Register(v,newClass.GetObjectHandle(),pfunc,name_); - return *this; - } // staticFunc - - // Register a function to a pre-allocated class/struct member function: will use callee's 'this' (effectively embedding a global function in TClassType's script namespace). - template - SQClassDef & staticFunc(Callee & callee,Func pfunc,const SQChar * name_) { - Register(v,newClass.GetObjectHandle(),callee,pfunc,name_); - return *this; - } // staticFunc - - // === END static+global function registration === - - // Register a member variable. - template - SQClassDef & var(VarType TClassType::* pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) { - struct CV { - VarType TClassType::* var; - } cv; // Cast Variable helper. - cv.var = pvar; - RegisterInstanceVariable(newClass,ClassType::type(),*(VarType **)&cv,name_,access); - return *this; - } // var - - // Register a member variable as a UserPointer (read only). - template - SQClassDef & varAsUserPointer(VarType TClassType::* pvar,const SQChar * name_) { - struct CV { - VarType TClassType::* var; - } cv; // Cast Variable helper. - cv.var = pvar; - RegisterInstanceVariable(newClass,ClassType::type(),*(SQAnything **)&cv,name_,VAR_ACCESS_READ_ONLY); - return *this; - } // varAsUserPointer - - template - SQClassDef & staticVar(VarType * pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) { - struct CV { - VarType * var; - } cv; // Cast Variable helper. - cv.var = pvar; - RegisterInstanceVariable(newClass,ClassType::type(),*(VarType **)&cv,name_,VarAccessType(access|VAR_ACCESS_STATIC)); - return *this; - } // staticVar - -#ifdef SQPLUS_CONST_OPT -#define SQ_REG_CONST_STATIC_VAR -#include "SqPlusConst.h" -#endif - - // Register a constant (read-only in script, passed by value (only INT_T, FLOAT_T, or BOOL_T types)). - template - SQClassDef & constant(ConstantType constant_,const SQChar * name_) { - RegisterInstanceConstant(newClass,ClassType::type(),constant_,name_); - return *this; - } // constant - - // Register an enum as an integer (read-only in script). - SQClassDef & enumInt(SQInteger constant_,const SQChar * name_) { - RegisterInstanceConstant(newClass,ClassType::type(),constant_,name_); - return *this; - } // enumInt - -}; - -// === BEGIN Function Call Handlers === - -inline void Push(HSQUIRRELVM v,char value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,unsigned char value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,short value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,unsigned short value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,int value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,unsigned int value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,long value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,long long value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,unsigned long value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,unsigned long long value) { sq_pushinteger(v,value); } -inline void Push(HSQUIRRELVM v,double value) { sq_pushfloat(v,(FLOAT_T)value); } -inline void Push(HSQUIRRELVM v,float value) { sq_pushfloat(v,(FLOAT_T)value); } -inline void Push(HSQUIRRELVM v,const SQChar * value) { sq_pushstring(v,value,-1); } -inline void Push(HSQUIRRELVM v,const SquirrelNull &) { sq_pushnull(v); } -inline void Push(HSQUIRRELVM v,SQFUNCTION value) { sq_pushuserpointer(v,(void*)value); } -inline void Push(HSQUIRRELVM v,SQAnythingPtr value) { sq_pushuserpointer(v,(void*)value); } // Cast to SQAnythingPtr instead of void * if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler. -inline void Push(HSQUIRRELVM v,SquirrelObject & so) { sq_pushobject(v,so.GetObjectHandle()); } - - -#define USE_ARGUMENT_DEPENDANT_OVERLOADS -#ifdef USE_ARGUMENT_DEPENDANT_OVERLOADS -#ifdef _MSC_VER -#pragma warning (disable:4675) // Disable warning: "resolved overload was found by argument-dependent lookup" when class/struct pointers are used as function arguments. -#endif -// === BEGIN Argument Dependent Overloads === -inline void Push(HSQUIRRELVM v,bool value) { sq_pushbool(v,value); } // Pass bool as SQInteger if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler. -inline void Push(HSQUIRRELVM v,const void * value) { sq_pushuserpointer(v,(void*)value); } // Pass SQAnythingPtr instead of void * " " -inline void Push(HSQUIRRELVM v,const SQUserPointer & value) { sq_pushuserpointer(v,(void*)value); } -// === END Argument Dependent Overloads === -#endif - -#define SQPLUS_CHECK_GET(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("sq_get*() failed (type error)")) - -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_BOOL; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; } -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; } -inline bool Match(TypeWrapper,HSQUIRRELVM /*v*/,SQInteger /*idx*/){ return true; } // See Get() for HSQUIRRELVM below (v is always present). -inline bool Match(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_USERPOINTER; } -inline bool Match(TypeWrapper,HSQUIRRELVM /*v*/,SQInteger /*idx*/) { return true; } // See sq_getstackobj(): always returns true. - -inline void Get(TypeWrapper,HSQUIRRELVM /*v*/,int) { ; } -inline bool Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { SQBool b; SQPLUS_CHECK_GET(sq_getbool(v,idx,&b)); return b != 0; } -inline char Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline unsigned char Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline short Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline unsigned short Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline int Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return i; } -inline unsigned int Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline long Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline long long Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline unsigned long Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline unsigned long long Get(TypeWrapper, HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast(i); } -inline float Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return f; } -inline double Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return static_cast(f); } -inline const SQChar * Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return s; } -inline SquirrelNull Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { (void)v, (void)idx; return SquirrelNull(); } -inline void * Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { SQUserPointer p; SQPLUS_CHECK_GET(sq_getuserpointer(v,idx,&p)); return p; } -inline HSQUIRRELVM Get(TypeWrapper,HSQUIRRELVM v,SQInteger /*idx*/) { sq_poptop(v); return v; } // sq_poptop(v): remove UserData from stack so GetParamCount() matches normal behavior. -inline SquirrelObject Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { HSQOBJECT o; SQPLUS_CHECK_GET(sq_getstackobj(v,idx,&o)); return SquirrelObject(o); } - -#ifdef SQPLUS_SUPPORT_STD_STRING -inline void Push(HSQUIRRELVM v,const std::string& value) { sq_pushstring(v,value.c_str(),-1); } -inline bool Match(TypeWrapper, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; } -inline std::string Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return std::string(s); } -#endif - -// Added jflanglois suggestion, 8/20/06. jcs -#ifdef SQPLUS_SUPPORT_SQ_STD_STRING -typedef std::basic_string sq_std_string; -inline void Push(HSQUIRRELVM v,const sq_std_string & value) { sq_pushstring(v,value.c_str(),-1); } -inline bool Match(TypeWrapper, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; } -inline sq_std_string Get(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return sq_std_string(s); } -#endif - -// GetRet() restores the stack for SquirrelFunction<>() calls. -template -inline RT GetRet(TypeWrapper,HSQUIRRELVM v,SQInteger idx) { RT ret = Get(TypeWrapper(),v,idx); sq_pop(v,2); return ret; } // sq_pop(v,2): restore stack after function call. - -// Specialization to support void return type. -inline void GetRet(TypeWrapper,HSQUIRRELVM v,SQInteger /*idx*/) { sq_pop(v,2); } - -// === END Function Call Handlers === - -// === Example SQClassDef usage (see testSqPlus2.cpp): === - -#if 0 - SQClassDef sqClass(sqT("NewTestObj"); - sqClass.func(NewTestObj::newtestR1,sqT("newtestR1")); - sqClass.var(&NewTestObj::val,sqT("val")); - sqClass.var(&NewTestObj::s1,sqT("s1")); - sqClass.var(&NewTestObj::s2,sqT("s2")); - sqClass.funcVarArgs(&NewTestObj::multiArgs,sqT("multiArgs")); - -// Shorthand form: - - SQClassDef(sqT("NewTestObj"). - func(NewTestObj::newtestR1,sqT("newtestR1")). - var(&NewTestObj::val,sqT("val")). - var(&NewTestObj::s1,sqT("s1")). - var(&NewTestObj::s2,sqT("s2")). - funcVarArgs(NewTestObj::multiArgs,sqT("multiArgs")); -#endif - -// === Macros for old style registration. SQClassDef registration is now easier to use (SQ_DECLARE_CLASS() is not needed) === - -#define SQ_DECLARE_CLASS(CLASSNAME) \ -static SQInteger _##CLASSNAME##_release(SQUserPointer up,SQInteger size) { \ - if (up) { \ - CLASSNAME * self = (CLASSNAME *)up; \ - delete self; \ - } \ - return 0; \ -} \ -static SQInteger _##CLASSNAME##_constructor(HSQUIRRELVM v) { \ - CLASSNAME * pc = new CLASSNAME(); \ - sq_setinstanceup(v,1,pc); \ - sq_setreleasehook(v,1,_##CLASSNAME##_release); \ - return 1; \ -} - -#define SQ_REGISTER_CLASS(CLASSNAME) \ - RegisterClassType(SquirrelVM::GetVMPtr(),sqT(#CLASSNAME),_##CLASSNAME##_constructor) - -#define SQ_REGISTER_INSTANCE(NEWSQCLASS,CCLASS,FUNCNAME) \ - RegisterInstance(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME)); - -#define SQ_REGISTER_INSTANCE_VARARGS(NEWSQCLASS,CCLASS,FUNCNAME) \ - RegisterInstanceVarArgs(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME)); - -#define SQ_REGISTER_INSTANCE_VARIABLE(NEWSQCLASS,CCLASS,VARNAME) \ - RegisterInstanceVariable(NEWSQCLASS,&((CCLASS *)0)->VARNAME,sqT(#VARNAME)); - -#if defined(USE_ARGUMENT_DEPENDANT_OVERLOADS) && defined(_MSC_VER) -#pragma warning (default:4675) -#endif - -}; // namespace SqPlus - -#endif //_SQ_PLUS_H_ diff --git a/src/include/scripting/sqplus/sqplusWin32.h b/src/include/scripting/sqplus/sqplusWin32.h deleted file mode 100644 index bf46fd6cf2..0000000000 --- a/src/include/scripting/sqplus/sqplusWin32.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _SQ_PLUS_WIN32_H_ -#define _SQ_PLUS_WIN32_H_ - -#include "sqplus.h" -#include "SquirrelBindingsUtilsWin32.h" - -#endif //_SQ_PLUS_WIN32_H_ \ No newline at end of file diff --git a/src/sdk/scripting/sqplus/Makefile.am b/src/sdk/scripting/sqplus/Makefile.am deleted file mode 100644 index 2cdd579ef2..0000000000 --- a/src/sdk/scripting/sqplus/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src/include/scripting/include \ - -I$(top_srcdir)/src/include/scripting/sqplus - -noinst_LTLIBRARIES = libsqplus.la - -libsqplus_la_SOURCES = SqPlus.cpp \ - SquirrelVM.cpp \ - SquirrelBindingsUtils.cpp \ - SquirrelObject.cpp - -EXTRA_DIST = sqplus71.vcproj \ - sqplus.cbp \ - sqplus.vcproj \ - SquirrelBindingsUtilsWin32.cpp diff --git a/src/sdk/scripting/sqplus/SqPlus.cpp b/src/sdk/scripting/sqplus/SqPlus.cpp deleted file mode 100644 index 145bb892f5..0000000000 --- a/src/sdk/scripting/sqplus/SqPlus.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "sqplus.h" -#include - -namespace SqPlus { - -static SQInteger getVarInfo(StackHandler & sa,VarRefPtr & vr) { - HSQOBJECT htable = sa.GetObjectHandle(1); - SquirrelObject table(htable); -#ifdef _DEBUG - SQObjectType type = (SQObjectType)sa.GetType(2); -#endif - const SQChar * el = sa.GetString(2); - ScriptStringVar256 varNameTag; - getVarNameTag(varNameTag,sizeof(varNameTag),el); - SQUserPointer data=0; - if (!table.RawGetUserData(varNameTag,&data)) { -// throw SquirrelError("getVarInfo: Could not retrieve UserData"); - return sa.ThrowError(sqT("getVarInfo: Could not retrieve UserData")); // Results in variable not being found error. - } // if - vr = (VarRefPtr)data; - return SQ_OK; -} // getVarInfo - -static SQInteger getInstanceVarInfo(StackHandler & sa,VarRefPtr & vr,SQUserPointer & data) { - HSQOBJECT ho = sa.GetObjectHandle(1); - SquirrelObject instance(ho); -#ifdef _DEBUG - SQObjectType type = (SQObjectType)sa.GetType(2); -#endif - const SQChar * el = sa.GetString(2); - ScriptStringVar256 varNameTag; - getVarNameTag(varNameTag,sizeof(varNameTag),el); - SQUserPointer ivrData=0; - if (!instance.RawGetUserData(varNameTag,&ivrData)) { -// throw SquirrelError("getInstanceVarInfo: Could not retrieve UserData"); - return sa.ThrowError(sqT("getInstanceVarInfo: Could not retrieve UserData")); // Results in variable not being found error. - } // if - vr = (VarRefPtr)ivrData; - unsigned char * up; - if (!(vr->access & (VAR_ACCESS_STATIC|VAR_ACCESS_CONSTANT))) { -#ifdef SQ_USE_CLASS_INHERITANCE - SQUserPointer typetag; instance.GetTypeTag(&typetag); - if (typetag != vr->instanceType) { - SquirrelObject typeTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); - up = (unsigned char *)typeTable.GetUserPointer(INT_T((size_t)vr->instanceType)); // 64-bit compatible version. - if (!up) { - throw SquirrelError(sqT("Invalid Instance Type")); - } // if - } else { - up = (unsigned char *)instance.GetInstanceUP(0); - } // if -#else - up = (unsigned char *)instance.GetInstanceUP(0); -#endif - up += (size_t)vr->offsetOrAddrOrConst; // Offset - } else { - up = (unsigned char *)vr->offsetOrAddrOrConst; // Address - } // if - data = up; - return SQ_OK; -} // getInstanceVarInfo - -static SQInteger setVar(StackHandler & sa,VarRef * vr,void * data) { - if (vr->access & (VAR_ACCESS_READ_ONLY|VAR_ACCESS_CONSTANT)) { - ScriptStringVar256 msg; - const SQChar * el = sa.GetString(2); - SCSNPRINTF(msg.s,sizeof(msg.s),sqT("setVar(): Cannot write to constant: %s"),el); - throw SquirrelError(msg.s); - } // if - switch (vr->type) { - case TypeInfo::TypeID: { - INT_T * val = (INT_T *)data; // Address - if (val) { - *val = sa.GetInt(3); - return sa.Return(*val); - } // if - break; - } // case - case TypeInfo::TypeID: { - FLOAT_T * val = (FLOAT_T *)data; // Address - if (val) { - *val = sa.GetFloat(3); - return sa.Return(*val); - } // if - break; - } // case - case TypeInfo::TypeID: { - bool * val = (bool *)data; // Address - if (val) { - *val = sa.GetBool(3) ? true : false; - return sa.Return(*val); - } // if - break; - } // case - case VAR_TYPE_INSTANCE: { - // C::B patch: Comment out unused variable - //HSQUIRRELVM v = sa.GetVMPtr(); - // vr->copyFunc is the LHS variable type: the RHS var's type is ClassType<>::type() (both point to ClassType<>::copy()). - // src will be null if the LHS and RHS types don't match. - SQUserPointer src = sa.GetInstanceUp(3,(SQUserPointer)vr->copyFunc); // Effectively performs: ClassType<>::type() == ClassType<>getCopyFunc(). - if (!src) throw SquirrelError(sqT("INSTANCE type assignment mismatch")); - vr->copyFunc(data,src); -#if 0 // Return an instance on the stack (allocates memory) - if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address - ScriptStringVar256 msg; - SCSNPRINTF(msg.s,sizeof(msg),sqT("getVar(): Could not create instance: %s"),vr->typeName); - throw SquirrelError(msg.s); - } // if - return 1; -#else // Don't return on stack. - return 0; -#endif - } - case TypeInfo::TypeID: { - ScriptStringVar256 msg; - const SQChar * el = sa.GetString(2); - SCSNPRINTF(msg.s,sizeof(msg.s),sqT("setVar(): Cannot write to an SQUserPointer: %s"),el); - throw SquirrelError(msg.s); - } // case - case TypeInfo::TypeID: { - ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address - if (val) { - const SQChar * strVal = sa.GetString(3); - if (strVal) { - *val = strVal; - return sa.Return(val->s); - } // if - } // if - break; - } // case - // C::B patch: Handle all switch cases - default: break; - } // switch - return SQ_ERROR; -} // setVar - -static SQInteger getVar(StackHandler & sa,VarRef * vr,void * data) { - switch (vr->type) { - case TypeInfo::TypeID: { - if (!(vr->access & VAR_ACCESS_CONSTANT)) { - INT_T * val = (INT_T *)data; // Address - if (val) { - return sa.Return(*val); - } // if - } else { - INT_T * val = (INT_T *)&data; // Constant value - return sa.Return(*val); - } // if - break; - } // case - case TypeInfo::TypeID: { - if (!(vr->access & VAR_ACCESS_CONSTANT)) { - FLOAT_T * val = (FLOAT_T *)data; // Address - if (val) { - return sa.Return(*val); - } // if - } else { - FLOAT_T * val = (FLOAT_T *)&data; // Constant value - return sa.Return(*val); - } // if - break; - } // case - case TypeInfo::TypeID: { - if (!(vr->access & VAR_ACCESS_CONSTANT)) { - bool * val = (bool *)data; // Address - if (val) { - return sa.Return(*val); - } // if - } else { - bool * val = (bool *)&data; // Constant value - return sa.Return(*val); - } // if - break; - } // case - case VAR_TYPE_INSTANCE: - if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address. Allocates memory. - ScriptStringVar256 msg; - SCSNPRINTF(msg.s,sizeof(msg.s),sqT("getVar(): Could not create instance: %s"),vr->typeName); - throw SquirrelError(msg.s); - } // if - return 1; - case TypeInfo::TypeID: { - return sa.Return(data); // The address of member variable, not the variable itself. - } // case - case TypeInfo::TypeID: { - if (!(vr->access & VAR_ACCESS_CONSTANT)) { - ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address - if (val) { - return sa.Return(val->s); - } // if - } else { - throw SquirrelError(sqT("getVar(): Invalid type+access: 'ScriptStringVarBase' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)")); - } // if - break; - } // case - case TypeInfo::TypeID: { - if (!(vr->access & VAR_ACCESS_CONSTANT)) { - throw SquirrelError(sqT("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT")); - } else { - return sa.Return((const SQChar *)data); // Address - } // if - break; - } // case - // C::B patch: Handle all switch cases - default: break; - } // switch - return SQ_ERROR; -} // getVar - -// === Global Vars === - -SQInteger setVarFunc(HSQUIRRELVM v) { - StackHandler sa(v); - if (sa.GetType(1) == OT_TABLE) { - VarRefPtr vr; - SQInteger res = getVarInfo(sa,vr); - if (res != SQ_OK) return res; - return setVar(sa,vr,vr->offsetOrAddrOrConst); - } // if - return SQ_ERROR; -} // setVarFunc - -SQInteger getVarFunc(HSQUIRRELVM v) { - StackHandler sa(v); - if (sa.GetType(1) == OT_TABLE) { - VarRefPtr vr; - SQInteger res = getVarInfo(sa,vr); - if (res != SQ_OK) return res; - return getVar(sa,vr,vr->offsetOrAddrOrConst); - } // if - return SQ_ERROR; -} // getVarFunc - -// === Instance Vars === - -SQInteger setInstanceVarFunc(HSQUIRRELVM v) { - StackHandler sa(v); - if (sa.GetType(1) == OT_INSTANCE) { - VarRefPtr vr; - void * data; - SQInteger res = getInstanceVarInfo(sa,vr,data); - if (res != SQ_OK) return res; - return setVar(sa,vr,data); - } // if - return SQ_ERROR; -} // setInstanceVarFunc - -SQInteger getInstanceVarFunc(HSQUIRRELVM v) { - StackHandler sa(v); - if (sa.GetType(1) == OT_INSTANCE) { - VarRefPtr vr; - void * data; - SQInteger res = getInstanceVarInfo(sa,vr,data); - if (res != SQ_OK) return res; - return getVar(sa,vr,data); - } // if - return SQ_ERROR; -} // getInstanceVarFunc - -// === Classes === - -BOOL_T CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName) { - // C::B patch: Comment out unused variable - //SQInteger n = 0; - SQInteger oldtop = sq_gettop(v); - sq_pushroottable(v); - sq_pushstring(v,name,-1); - if (baseName) { - sq_pushstring(v,baseName,-1); - if (SQ_FAILED(sq_get(v,-3))) { // Make sure the base exists if specified by baseName. - sq_settop(v,oldtop); - return FALSE; - } // if - } // if - if (SQ_FAILED(sq_newclass(v,baseName ? 1 : 0))) { // Will inherit from base class on stack from sq_get() above. - sq_settop(v,oldtop); - return FALSE; - } // if - newClass.AttachToStackObject(-1); - sq_settypetag(v,-1,classType); - sq_createslot(v,-3); - sq_pop(v,1); - return TRUE; -} // CreateClass - -SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,SQUserPointer classType,SQFUNCTION constructor) { - SQInteger top = sq_gettop(v); - SquirrelObject newClass; - if (CreateClass(v,newClass,classType,scriptClassName)) { - SquirrelVM::CreateFunction(newClass,constructor,sqT("constructor")); - } // if - sq_settop(v,top); - return newClass; -} // RegisterClassType - -}; // namespace SqPlus - -// sqPlus diff --git a/src/sdk/scripting/sqplus/SquirrelBindingsUtils.cpp b/src/sdk/scripting/sqplus/SquirrelBindingsUtils.cpp deleted file mode 100644 index 0c10baefe1..0000000000 --- a/src/sdk/scripting/sqplus/SquirrelBindingsUtils.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "sqplus.h" - - - -BOOL_T CreateStaticNamespace(HSQUIRRELVM v,ScriptNamespaceDecl *sn) -{ - SQInteger n = 0; - sq_pushroottable(v); - sq_pushstring(v,sn->name,-1); - sq_newtable(v); - const ScriptClassMemberDecl *members = sn->members; - const ScriptClassMemberDecl *m = NULL; - while(members[n].name) { - m = &members[n]; - sq_pushstring(v,m->name,-1); - sq_newclosure(v,m->func,0); - sq_setparamscheck(v,m->params,m->typemask); - sq_setnativeclosurename(v,-1,m->name); - sq_createslot(v,-3); - n++; - } - const ScriptConstantDecl *consts = sn->constants; - const ScriptConstantDecl *c = NULL; - n = 0; - while(consts[n].name) { - c = &consts[n]; - sq_pushstring(v,c->name,-1); - switch(c->type) { - case OT_STRING: sq_pushstring(v,c->val.s,-1);break; - case OT_INTEGER: sq_pushinteger(v,c->val.i);break; - case OT_FLOAT: sq_pushfloat(v,c->val.f);break; - // C::B patch: Handle all switch cases - default: break; - } - sq_createslot(v,-3); - n++; - } - if(sn->delegate) { - // C::B patch: Fix shadowed variable warning - members = sn->delegate; - m = NULL; - sq_newtable(v); - while(members[n].name) { - m = &members[n]; - sq_pushstring(v,m->name,-1); - sq_newclosure(v,m->func,0); - sq_setparamscheck(v,m->params,m->typemask); - sq_setnativeclosurename(v,-1,m->name); - sq_createslot(v,-3); - n++; - } - sq_setdelegate(v,-2); - } - sq_createslot(v,-3); - sq_pop(v,1); - - return TRUE; -} - -BOOL_T CreateClass(HSQUIRRELVM v,SquirrelClassDecl *cd) -{ - SQInteger n = 0; - SQInteger oldtop = sq_gettop(v); - sq_pushroottable(v); - sq_pushstring(v,cd->name,-1); - if(cd->base) { - sq_pushstring(v,cd->base,-1); - if(SQ_FAILED(sq_get(v,-3))) { // Make sure the base exists if specified by cd->base name. - sq_settop(v,oldtop); - return FALSE; - } - } - if(SQ_FAILED(sq_newclass(v,cd->base?1:0))) { // Will inherit from base class on stack from sq_get() above. - sq_settop(v,oldtop); - return FALSE; - } -// sq_settypetag(v,-1,(unsigned int)cd); -// C::B patch: Use pragmas only for MS compilers -#if defined(_WIN32) && defined(_MSC_VER) -#pragma warning(disable : 4311) -#endif - sq_settypetag(v,-1,reinterpret_cast(cd)); - const ScriptClassMemberDecl *members = cd->members; - const ScriptClassMemberDecl *m = NULL; - if (members) { - while(members[n].name) { - m = &members[n]; - sq_pushstring(v,m->name,-1); - sq_newclosure(v,m->func,0); - sq_setparamscheck(v,m->params,m->typemask); - sq_setnativeclosurename(v,-1,m->name); - sq_createslot(v,-3); - n++; - } - } // if - sq_createslot(v,-3); - sq_pop(v,1); - return TRUE; -} - -BOOL_T CreateNativeClassInstance(HSQUIRRELVM v,const SQChar *classname,SQUserPointer ud,SQRELEASEHOOK hook) -{ - SQInteger oldtop = sq_gettop(v); - sq_pushroottable(v); - sq_pushstring(v,classname,-1); - if(SQ_FAILED(sq_rawget(v,-2))){ // Get the class (created with sq_newclass()). - sq_settop(v,oldtop); - return FALSE; - } - //sq_pushroottable(v); - if(SQ_FAILED(sq_createinstance(v,-1))) { - sq_settop(v,oldtop); - return FALSE; - } - sq_remove(v,-3); //removes the root table - sq_remove(v,-2); //removes the class - if(SQ_FAILED(sq_setinstanceup(v,-1,ud))) { - sq_settop(v,oldtop); - return FALSE; - } - sq_setreleasehook(v,-1,hook); - return TRUE; -} diff --git a/src/sdk/scripting/sqplus/SquirrelBindingsUtilsWin32.cpp b/src/sdk/scripting/sqplus/SquirrelBindingsUtilsWin32.cpp deleted file mode 100644 index 1641972d67..0000000000 --- a/src/sdk/scripting/sqplus/SquirrelBindingsUtilsWin32.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//#include "sqplus.h" - -//#include "SquirrelObject.h" -//#include "SquirrelVM.h" -#include "SquirrelBindingsUtilsWin32.h" - -// C::B patch: Comment out unused variable -SQInteger refcounted_release_hook(SQUserPointer p, SQInteger /* size */) -{ - IUnknown *pRC = (IUnknown*)p; - pRC->Release(); - return 0; -} - -static BOOL __CreateRefCountedInstance(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC,SQRELEASEHOOK hook) -{ - if(!CreateNativeClassInstance(v,classname,pRC,hook)) return FALSE; - return TRUE; -} - -SQInteger construct_RefCounted(IUnknown *p) -{ - sq_setinstanceup(SquirrelVM::GetVMPtr(),1,p); - sq_setreleasehook(SquirrelVM::GetVMPtr(),1,refcounted_release_hook); - return 1; -} - - -BOOL CreateRefCountedInstance(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC) -{ - return __CreateRefCountedInstance(v,classname,pRC,refcounted_release_hook); -} diff --git a/src/sdk/scripting/sqplus/SquirrelObject.cpp b/src/sdk/scripting/sqplus/SquirrelObject.cpp deleted file mode 100644 index 7d2d975375..0000000000 --- a/src/sdk/scripting/sqplus/SquirrelObject.cpp +++ /dev/null @@ -1,639 +0,0 @@ -#include "sqplus.h" - -SquirrelObject::SquirrelObject(void) -{ - sq_resetobject(&_o); -} - -SquirrelObject::~SquirrelObject() -{ - if(SquirrelVM::_VM) - sq_release(SquirrelVM::_VM,&_o); -} - -SquirrelObject::SquirrelObject(const SquirrelObject &o) -{ - _o = o._o; - sq_addref(SquirrelVM::_VM,&_o); -} - -SquirrelObject::SquirrelObject(HSQOBJECT o) -{ - _o = o; - sq_addref(SquirrelVM::_VM,&_o); -} - -void SquirrelObject::Reset(void) { - if(SquirrelVM::_VM) - sq_release(SquirrelVM::_VM,&_o); - sq_resetobject(&_o); -} // SquirrelObject::Reset - -SquirrelObject SquirrelObject::Clone() -{ - SquirrelObject ret; - if(GetType() == OT_TABLE || GetType() == OT_ARRAY) - { - sq_pushobject(SquirrelVM::_VM,_o); - sq_clone(SquirrelVM::_VM,-1); - ret.AttachToStackObject(-1); - sq_pop(SquirrelVM::_VM,2); - } - return ret; - -} - -SquirrelObject & SquirrelObject::operator =(const SquirrelObject &o) -{ - HSQOBJECT t; - t = o._o; - sq_addref(SquirrelVM::_VM,&t); - sq_release(SquirrelVM::_VM,&_o); - _o = t; - return *this; -} - -SquirrelObject & SquirrelObject::operator =(SQInteger n) -{ - sq_pushinteger(SquirrelVM::_VM,n); - AttachToStackObject(-1); - sq_pop(SquirrelVM::_VM,1); - return *this; -} - -void SquirrelObject::ArrayAppend(const SquirrelObject &o) -{ - if(sq_isarray(_o)) { - sq_pushobject(SquirrelVM::_VM,_o); - sq_pushobject(SquirrelVM::_VM,o._o); - sq_arrayappend(SquirrelVM::_VM,-2); - sq_pop(SquirrelVM::_VM,1); - } -} - -void SquirrelObject::AttachToStackObject(SQInteger idx) -{ - HSQOBJECT t; - sq_getstackobj(SquirrelVM::_VM,idx,&t); - sq_addref(SquirrelVM::_VM,&t); - sq_release(SquirrelVM::_VM,&_o); - _o = t; -} - -BOOL_T SquirrelObject::SetDelegate(SquirrelObject &obj) -{ - if(obj.GetType() == OT_TABLE || - obj.GetType() == OT_NULL) { - switch(_o._type) { - case OT_USERDATA: - case OT_TABLE: - sq_pushobject(SquirrelVM::_VM,_o); - sq_pushobject(SquirrelVM::_VM,obj._o); - if(SQ_SUCCEEDED(sq_setdelegate(SquirrelVM::_VM,-2))) - return TRUE; - break; - // C::B patch: Handle all switch cases - default: break; - } - } - return FALSE; -} - -SquirrelObject SquirrelObject::GetDelegate() -{ - SquirrelObject ret; - if(_o._type == OT_TABLE || _o._type == OT_USERDATA) - { - SQInteger top = sq_gettop(SquirrelVM::_VM); - sq_pushobject(SquirrelVM::_VM,_o); - sq_getdelegate(SquirrelVM::_VM,-1); - ret.AttachToStackObject(-1); - sq_settop(SquirrelVM::_VM,top); -// sq_pop(SquirrelVM::_VM,2); - } - return ret; -} - -BOOL_T SquirrelObject::IsNull() const -{ - return sq_isnull(_o); -} - -BOOL_T SquirrelObject::IsNumeric() const -{ - return sq_isnumeric(_o); -} - -SQInteger SquirrelObject::Len() const -{ - SQInteger ret = 0; - if(sq_isarray(_o) || sq_istable(_o) || sq_isstring(_o)) { - sq_pushobject(SquirrelVM::_VM,_o); - ret = sq_getsize(SquirrelVM::_VM,-1); - sq_pop(SquirrelVM::_VM,1); - } - return ret; -} - -#define _SETVALUE_INT_BEGIN \ - BOOL_T ret = FALSE; \ - SQInteger top = sq_gettop(SquirrelVM::_VM); \ - sq_pushobject(SquirrelVM::_VM,_o); \ - sq_pushinteger(SquirrelVM::_VM,key); - -#define _SETVALUE_INT_END \ - if(SQ_SUCCEEDED(sq_rawset(SquirrelVM::_VM,-3))) { \ - ret = TRUE; \ - } \ - sq_settop(SquirrelVM::_VM,top); \ - return ret; - -BOOL_T SquirrelObject::SetValue(INT_T key,const SquirrelObject &val) -{ - _SETVALUE_INT_BEGIN - sq_pushobject(SquirrelVM::_VM,val._o); - _SETVALUE_INT_END -} - -BOOL_T SquirrelObject::SetValue(INT_T key,INT_T n) -{ - _SETVALUE_INT_BEGIN - sq_pushinteger(SquirrelVM::_VM,n); - _SETVALUE_INT_END -} - -BOOL_T SquirrelObject::SetValue(INT_T key,FLOAT_T f) -{ - _SETVALUE_INT_BEGIN - sq_pushfloat(SquirrelVM::_VM,f); - _SETVALUE_INT_END -} - -BOOL_T SquirrelObject::SetValue(INT_T key,const SQChar *s) -{ - _SETVALUE_INT_BEGIN - sq_pushstring(SquirrelVM::_VM,s,-1); - _SETVALUE_INT_END -} - -BOOL_T SquirrelObject::SetValue(INT_T key,bool b) -{ - _SETVALUE_INT_BEGIN - sq_pushbool(SquirrelVM::_VM,b); - _SETVALUE_INT_END -} - -BOOL_T SquirrelObject::SetValue(const SquirrelObject &key,const SquirrelObject &val) -{ - BOOL_T ret = FALSE; - SQInteger top = sq_gettop(SquirrelVM::_VM); - sq_pushobject(SquirrelVM::_VM,_o); - sq_pushobject(SquirrelVM::_VM,key._o); - sq_pushobject(SquirrelVM::_VM,val._o); - if(SQ_SUCCEEDED(sq_rawset(SquirrelVM::_VM,-3))) { - ret = TRUE; - } - sq_settop(SquirrelVM::_VM,top); - return ret; -} - -#define _SETVALUE_STR_BEGIN \ - BOOL_T ret = FALSE; \ - SQInteger top = sq_gettop(SquirrelVM::_VM); \ - sq_pushobject(SquirrelVM::_VM,_o); \ - sq_pushstring(SquirrelVM::_VM,key,-1); - -#define _SETVALUE_STR_END \ - if(SQ_SUCCEEDED(sq_rawset(SquirrelVM::_VM,-3))) { \ - ret = TRUE; \ - } \ - sq_settop(SquirrelVM::_VM,top); \ - return ret; - -BOOL_T SquirrelObject::SetValue(const SQChar *key,const SquirrelObject &val) -{ - _SETVALUE_STR_BEGIN - sq_pushobject(SquirrelVM::_VM,val._o); - _SETVALUE_STR_END -} - -BOOL_T SquirrelObject::SetValue(const SQChar *key,INT_T n) -{ - _SETVALUE_STR_BEGIN - sq_pushinteger(SquirrelVM::_VM,n); - _SETVALUE_STR_END -} - -BOOL_T SquirrelObject::SetValue(const SQChar *key,FLOAT_T f) -{ - _SETVALUE_STR_BEGIN - sq_pushfloat(SquirrelVM::_VM,f); - _SETVALUE_STR_END -} - -BOOL_T SquirrelObject::SetValue(const SQChar *key,const SQChar *s) -{ - _SETVALUE_STR_BEGIN - sq_pushstring(SquirrelVM::_VM,s,-1); - _SETVALUE_STR_END -} - -BOOL_T SquirrelObject::SetValue(const SQChar *key,bool b) -{ - _SETVALUE_STR_BEGIN - sq_pushbool(SquirrelVM::_VM,b); - _SETVALUE_STR_END -} - -// === BEGIN User Pointer, User Data === - -BOOL_T SquirrelObject::SetUserPointer(const SQChar * key,SQUserPointer up) { - _SETVALUE_STR_BEGIN - sq_pushuserpointer(SquirrelVM::_VM,up); - _SETVALUE_STR_END -} // SquirrelObject::SetUserPointer - -SQUserPointer SquirrelObject::GetUserPointer(const SQChar * key) { - SQUserPointer ret = NULL; - if (GetSlot(key)) { - sq_getuserpointer(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } // if - sq_pop(SquirrelVM::_VM,1); - return ret; -} // SquirrelObject::GetUserPointer - -BOOL_T SquirrelObject::SetUserPointer(INT_T key,SQUserPointer up) { - _SETVALUE_INT_BEGIN - sq_pushuserpointer(SquirrelVM::_VM,up); - _SETVALUE_INT_END -} // SquirrelObject::SetUserPointer - -SQUserPointer SquirrelObject::GetUserPointer(INT_T key) { - SQUserPointer ret = NULL; - if (GetSlot(key)) { - sq_getuserpointer(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } // if - sq_pop(SquirrelVM::_VM,1); - return ret; -} // SquirrelObject::GetUserPointer - -// === User Data === - -BOOL_T SquirrelObject::NewUserData(const SQChar * key,INT_T size,SQUserPointer * typetag) { - _SETVALUE_STR_BEGIN - sq_newuserdata(SquirrelVM::_VM,size); - if (typetag) { - sq_settypetag(SquirrelVM::_VM,-1,typetag); - } // if - _SETVALUE_STR_END -} // SquirrelObject::NewUserData - -BOOL_T SquirrelObject::GetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag) { - BOOL_T ret = false; - if (GetSlot(key)) { - sq_getuserdata(SquirrelVM::_VM,-1,data,typetag); - sq_pop(SquirrelVM::_VM,1); - ret = true; - } // if - sq_pop(SquirrelVM::_VM,1); - return ret; -} // SquirrelObject::GetUserData - -BOOL_T SquirrelObject::RawGetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag) { - BOOL_T ret = false; - if (RawGetSlot(key)) { - sq_getuserdata(SquirrelVM::_VM,-1,data,typetag); - sq_pop(SquirrelVM::_VM,1); - ret = true; - } // if - sq_pop(SquirrelVM::_VM,1); - return ret; -} // SquirrelObject::RawGetUserData - -// === END User Pointer === - -// === BEGIN Arrays === - -BOOL_T SquirrelObject::ArrayResize(INT_T newSize) { -// SQInteger top = sq_gettop(SquirrelVM::_VM); - sq_pushobject(SquirrelVM::_VM,GetObjectHandle()); - BOOL_T res = sq_arrayresize(SquirrelVM::_VM,-1,newSize) == SQ_OK; - sq_pop(SquirrelVM::_VM,1); -// sq_settop(SquirrelVM::_VM,top); - return res; -} // SquirrelObject::ArrayResize - -BOOL_T SquirrelObject::ArrayExtend(INT_T amount) { - SQInteger newLen = Len()+amount; - return ArrayResize(newLen); -} // SquirrelObject::ArrayExtend - -BOOL_T SquirrelObject::ArrayReverse(void) { - sq_pushobject(SquirrelVM::_VM,GetObjectHandle()); - BOOL_T res = sq_arrayreverse(SquirrelVM::_VM,-1) == SQ_OK; - sq_pop(SquirrelVM::_VM,1); - return res; -} // SquirrelObject::ArrayReverse - -SquirrelObject SquirrelObject::ArrayPop(SQBool returnPoppedVal) { - SquirrelObject ret; - SQInteger top = sq_gettop(SquirrelVM::_VM); - sq_pushobject(SquirrelVM::_VM,GetObjectHandle()); - if (sq_arraypop(SquirrelVM::_VM,-1,returnPoppedVal) == SQ_OK) { - if (returnPoppedVal) { - ret.AttachToStackObject(-1); - } // if - } // if - sq_settop(SquirrelVM::_VM,top); - return ret; -} // SquirrelObject::ArrayPop - -// === END Arrays === - -SQObjectType SquirrelObject::GetType() -{ - return _o._type; -} - -BOOL_T SquirrelObject::GetSlot(INT_T key) const -{ - sq_pushobject(SquirrelVM::_VM,_o); - sq_pushinteger(SquirrelVM::_VM,key); - if(SQ_SUCCEEDED(sq_get(SquirrelVM::_VM,-2))) { - return TRUE; - } - - return FALSE; -} - - -SquirrelObject SquirrelObject::GetValue(INT_T key)const -{ - SquirrelObject ret; - if(GetSlot(key)) { - ret.AttachToStackObject(-1); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -FLOAT_T SquirrelObject::GetFloat(INT_T key) const -{ - FLOAT_T ret = 0.0f; - if(GetSlot(key)) { - sq_getfloat(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -INT_T SquirrelObject::GetInt(INT_T key) const -{ - INT_T ret = 0; - if(GetSlot(key)) { - sq_getinteger(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -const SQChar *SquirrelObject::GetString(INT_T key) const -{ - const SQChar *ret = NULL; - if(GetSlot(key)) { - sq_getstring(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -bool SquirrelObject::GetBool(INT_T key) const -{ - SQBool ret = FALSE; - if(GetSlot(key)) { - sq_getbool(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret?true:false; -} - -BOOL_T SquirrelObject::Exists(const SQChar *key) const -{ - BOOL_T ret = FALSE; - if(GetSlot(key)) { - ret = TRUE; - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} -//////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -BOOL_T SquirrelObject::GetSlot(const SQChar *name) const -{ - sq_pushobject(SquirrelVM::_VM,_o); - sq_pushstring(SquirrelVM::_VM,name,-1); - if(SQ_SUCCEEDED(sq_get(SquirrelVM::_VM,-2))) { - return TRUE; - } - - return FALSE; -} - -BOOL_T SquirrelObject::RawGetSlot(const SQChar *name) const { - sq_pushobject(SquirrelVM::_VM,_o); - sq_pushstring(SquirrelVM::_VM,name,-1); - if(SQ_SUCCEEDED(sq_rawget(SquirrelVM::_VM,-2))) { - return TRUE; - } - return FALSE; -} // SquirrelObject::RawGetSlot - -SquirrelObject SquirrelObject::GetValue(const SQChar *key)const -{ - SquirrelObject ret; - if(GetSlot(key)) { - ret.AttachToStackObject(-1); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -FLOAT_T SquirrelObject::GetFloat(const SQChar *key) const -{ - FLOAT_T ret = 0.0f; - if(GetSlot(key)) { - sq_getfloat(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -INT_T SquirrelObject::GetInt(const SQChar *key) const -{ - INT_T ret = 0; - if(GetSlot(key)) { - sq_getinteger(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -const SQChar *SquirrelObject::GetString(const SQChar *key) const -{ - const SQChar *ret = NULL; - if(GetSlot(key)) { - sq_getstring(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret; -} - -bool SquirrelObject::GetBool(const SQChar *key) const -{ - SQBool ret = FALSE; - if(GetSlot(key)) { - sq_getbool(SquirrelVM::_VM,-1,&ret); - sq_pop(SquirrelVM::_VM,1); - } - sq_pop(SquirrelVM::_VM,1); - return ret?true:false; -} - -SQUserPointer SquirrelObject::GetInstanceUP(SQUserPointer tag) const -{ - SQUserPointer up; - sq_pushobject(SquirrelVM::_VM,_o); - if (SQ_FAILED(sq_getinstanceup(SquirrelVM::_VM,-1,(SQUserPointer*)&up,tag))) { - sq_reseterror(SquirrelVM::_VM); - up = NULL; - } // if - sq_pop(SquirrelVM::_VM,1); - return up; -} - -BOOL_T SquirrelObject::SetInstanceUP(SQUserPointer up) -{ - if(!sq_isinstance(_o)) return FALSE; - sq_pushobject(SquirrelVM::_VM,_o); - sq_setinstanceup(SquirrelVM::_VM,-1,up); - sq_pop(SquirrelVM::_VM,1); - return TRUE; -} - -SquirrelObject SquirrelObject::GetAttributes(const SQChar *key) -{ - SquirrelObject ret; - SQInteger top = sq_gettop(SquirrelVM::_VM); - sq_pushobject(SquirrelVM::_VM,_o); - if(key) - sq_pushstring(SquirrelVM::_VM,key,-1); - else - sq_pushnull(SquirrelVM::_VM); - if(SQ_SUCCEEDED(sq_getattributes(SquirrelVM::_VM,-2))) { - ret.AttachToStackObject(-1); - } - sq_settop(SquirrelVM::_VM,top); - return ret; -} - -BOOL_T SquirrelObject::BeginIteration() -{ - if(!sq_istable(_o) && !sq_isarray(_o) && !sq_isclass(_o)) - return FALSE; - sq_pushobject(SquirrelVM::_VM,_o); - sq_pushnull(SquirrelVM::_VM); - return TRUE; -} - -BOOL_T SquirrelObject::Next(SquirrelObject &key,SquirrelObject &val) -{ - if(SQ_SUCCEEDED(sq_next(SquirrelVM::_VM,-2))) { - key.AttachToStackObject(-2); - val.AttachToStackObject(-1); - sq_pop(SquirrelVM::_VM,2); - return TRUE; - } - return FALSE; -} - -BOOL_T SquirrelObject::GetTypeTag(SQUserPointer * typeTag) { - if (SQ_SUCCEEDED(sq_getobjtypetag(&_o,typeTag))) { - return TRUE; - } // if - return FALSE; -} // SquirrelObject::GetTypeTag - -const SQChar * SquirrelObject::GetTypeName(const SQChar * key) { -#if 1 - // This version will work even if SQ_SUPPORT_INSTANCE_TYPE_INFO is not enabled. - SqPlus::ScriptStringVar256 varNameTag; - SqPlus::getVarNameTag(varNameTag,sizeof(varNameTag),key); - SQUserPointer data=0; - if (!RawGetUserData(varNameTag,&data)) { - return NULL; - } // if - SqPlus::VarRefPtr vr = (SqPlus::VarRefPtr)data; - return vr->typeName; -#else // This version will only work if SQ_SUPPORT_INSTANCE_TYPE_INFO is enabled. - SquirrelObject so = GetValue(key); - if (so.IsNull()) return NULL; - return so.GetTypeName(); -#endif -} // SquirrelObject::GetTypeName - -const SQChar * SquirrelObject::GetTypeName(INT_T key) { - SquirrelObject so = GetValue(key); - if (so.IsNull()) return NULL; - return so.GetTypeName(); -} // SquirrelObject::GetTypeName - -const SQChar * SquirrelObject::GetTypeName(void) { - SQUserPointer typeTag=NULL; - if (SQ_SUCCEEDED(sq_getobjtypetag(&_o,&typeTag))) { - SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE); - if (typeTable.IsNull()) { - return NULL; // Not compiled with SQ_SUPPORT_INSTANCE_TYPE_INFO enabled. - } // if - return typeTable.GetString(INT_T((size_t)typeTag)); - } // if - return NULL; -} // SquirrelObject::GetTypeName - -const SQChar* SquirrelObject::ToString() -{ - return sq_objtostring(&_o); -} - -SQInteger SquirrelObject::ToInteger() -{ - return sq_objtointeger(&_o); -} - -SQFloat SquirrelObject::ToFloat() -{ - return sq_objtofloat(&_o); -} - -bool SquirrelObject::ToBool() -{ - //<> - return _o._unVal.nInteger?true:false; -} - -void SquirrelObject::EndIteration() -{ - sq_pop(SquirrelVM::_VM,2); -} - diff --git a/src/sdk/scripting/sqplus/SquirrelVM.cpp b/src/sdk/scripting/sqplus/SquirrelVM.cpp deleted file mode 100644 index 388900c370..0000000000 --- a/src/sdk/scripting/sqplus/SquirrelVM.cpp +++ /dev/null @@ -1,347 +0,0 @@ -#include -#include -#include - -#define _DEBUG_DUMP - -#include "sqplus.h" - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#define STRLEN(n) _tcslen(n) -#else -#define STRLEN(n) strlen(n) -#endif - -HSQUIRRELVM SquirrelVM::_VM = NULL; -SQInteger SquirrelVM::_CallState = -1; -SquirrelObject * SquirrelVM::_root = NULL; - -SquirrelError::SquirrelError() -{ - const SQChar *s; - sq_getlasterror(SquirrelVM::_VM); - sq_getstring(SquirrelVM::_VM,-1,&s); - if(s) { - desc = s; - } - else { - desc = sqT("unknown error"); - } -} - -// C::B patch: Add additional initialisation flags -void SquirrelVM::Init(SquirrelInitFlags flags) -{ - _VM = sq_open(1024); - sq_setprintfunc(_VM,SquirrelVM::PrintFunc); -// sq_setprintfunc(_VM,SquirrelVM::PrintFunc,SquirrelVM::PrintFunc); - sq_pushroottable(_VM); - // C::B patch: Add additional initialisation flags - if (flags & sqifIO) sqstd_register_iolib(_VM); - if (flags & sqifBlob) sqstd_register_bloblib(_VM); - if (flags & sqifMath) sqstd_register_mathlib(_VM); - if (flags & sqifString) sqstd_register_stringlib(_VM); - sqstd_seterrorhandlers(_VM); - _root = new SquirrelObject(); - _root->AttachToStackObject(-1); - sq_pop(_VM,1); - //TODO error handler, compiler error handler -} - -BOOL_T SquirrelVM::Update() -{ - //update remote debugger - return TRUE; -} - -void SquirrelVM::Cleanup() -{ - //cleans the root table - sq_pushnull(_VM); - sq_setroottable(_VM); -} - -void SquirrelVM::Shutdown() -{ - if (_VM) { - Cleanup(); -#if 0 - sq_release(_VM,&_root->_o); - sq_resetobject(&_root->_o); -#endif - delete _root; - _root = NULL; - HSQUIRRELVM v = _VM; - _VM = NULL; - sq_close(v); - } // if -} - -void SquirrelVM::PrintFunc(HSQUIRRELVM /*v*/,const SQChar* s,...) -{ - static SQChar temp[2048]; - va_list vl; - va_start(vl, s); - scvsprintf( temp,s, vl); - SCPUTS(temp); - va_end(vl); -} - -SquirrelObject SquirrelVM::CompileScript(const SQChar *s) -{ -#define MAX_EXPANDED_PATH 1023 - SquirrelObject ret; - if(SQ_SUCCEEDED(sqstd_loadfile(_VM,s,1))) { - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; - } - throw SquirrelError(); -} - -SquirrelObject SquirrelVM::CompileBuffer(const SQChar *s,const SQChar * debugInfo) -{ - SquirrelObject ret; - if(SQ_SUCCEEDED(sq_compilebuffer(_VM,s,(int)STRLEN(s)*sizeof(SQChar),debugInfo,1))) { - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; - } - throw SquirrelError(); -} - -SquirrelObject SquirrelVM::RunScript(const SquirrelObject &o,SquirrelObject *_this) -{ - SquirrelObject ret; - sq_pushobject(_VM,o._o); - if(_this) { - sq_pushobject(_VM,_this->_o); - } - else { - sq_pushroottable(_VM); - } - if(SQ_SUCCEEDED(sq_call(_VM,1,SQTrue,SQ_CALL_RAISE_ERROR))) { - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; - } - sq_pop(_VM,1); - throw SquirrelError(); - -} - - -BOOL_T SquirrelVM::BeginCall(const SquirrelObject &func) -{ - if(_CallState != -1) - return FALSE; - _CallState = 1; - sq_pushobject(_VM,func._o); - sq_pushroottable(_VM); - return TRUE; -} - -BOOL_T SquirrelVM::BeginCall(const SquirrelObject &func,SquirrelObject &_this) -{ - if(_CallState != -1) - throw SquirrelError(sqT("call already initialized")); - _CallState = 1; - sq_pushobject(_VM,func._o); - sq_pushobject(_VM,_this._o); - return TRUE; -} - -#define _CHECK_CALL_STATE \ - if(_CallState == -1) \ - throw SquirrelError(sqT("call not initialized")); - -void SquirrelVM::PushParam(const SquirrelObject &o) -{ - _CHECK_CALL_STATE - sq_pushobject(_VM,o._o); - _CallState++; -} - -void SquirrelVM::PushParam(const SQChar *s) -{ - _CHECK_CALL_STATE - sq_pushstring(_VM,s,-1); - _CallState++; -} - -void SquirrelVM::PushParam(SQInteger n) -{ - _CHECK_CALL_STATE - sq_pushinteger(_VM,n); - _CallState++; -} - -void SquirrelVM::PushParam(SQFloat f) -{ - _CHECK_CALL_STATE - sq_pushfloat(_VM,f); - _CallState++; -} - -void SquirrelVM::PushParamNull() -{ - _CHECK_CALL_STATE - sq_pushnull(_VM); - _CallState++; -} - -void SquirrelVM::PushParam(SQUserPointer up) -{ - _CHECK_CALL_STATE - sq_pushuserpointer(_VM,up); - _CallState++; -} - -SquirrelObject SquirrelVM::EndCall() -{ - SquirrelObject ret; - if(_CallState >= 0) { - SQInteger oldtop = sq_gettop(_VM); - SQInteger nparams = _CallState; - _CallState = -1; - if(SQ_SUCCEEDED(sq_call(_VM,nparams,SQTrue,SQ_CALL_RAISE_ERROR))) { - ret.AttachToStackObject(-1); - sq_pop(_VM,2); - }else { - sq_settop(_VM,oldtop-(nparams+1)); - throw SquirrelError(); - } - - } - return ret; -} - -SquirrelObject SquirrelVM::CreateInstance(SquirrelObject &oclass) -{ - SquirrelObject ret; - SQInteger oldtop = sq_gettop(_VM); - sq_pushobject(_VM,oclass._o); - if(SQ_FAILED(sq_createinstance(_VM,-1))) { - sq_settop(_VM,oldtop); - throw SquirrelError(); - } - ret.AttachToStackObject(-1); - sq_pop(_VM,2); - return ret; -} - -SquirrelObject SquirrelVM::CreateTable() -{ - SquirrelObject ret; - sq_newtable(_VM); - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; -} - -SquirrelObject SquirrelVM::CreateString(const SQChar *s) -{ - SquirrelObject ret; - sq_pushstring(_VM,s,-1); - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; -} - - -SquirrelObject SquirrelVM::CreateArray(SQInteger size) -{ - SquirrelObject ret; - sq_newarray(_VM,size); - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; -} - -SquirrelObject SquirrelVM::CreateFunction(SQFUNCTION func) -{ - SquirrelObject ret; - sq_newclosure(_VM,func,0); - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; -} - -SquirrelObject SquirrelVM::CreateUserData(SQInteger size) { - SquirrelObject ret; - sq_newuserdata(_VM,size); - ret.AttachToStackObject(-1); - sq_pop(_VM,1); - return ret; -} - -const SquirrelObject &SquirrelVM::GetRootTable() -{ - return *_root; -} - -void SquirrelVM::PushRootTable(void) { - sq_pushroottable(_VM); -} // SquirrelVM::PushRootTable - -// Creates a function in the table or class currently on the stack. -//void CreateFunction(HSQUIRRELVM v,const SQChar * scriptFuncName,SQFUNCTION func,SQInteger numParams=0,const SQChar * typeMask=0) { -SquirrelObject SquirrelVM::CreateFunction(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) { - sq_pushstring(_VM,scriptFuncName,-1); - sq_newclosure(_VM,func,0); - SquirrelObject ret; - ret.AttachToStackObject(-1); - SQChar tm[64]; - SQChar * ptm = tm; - SQInteger numParams = SQ_MATCHTYPEMASKSTRING; - if (typeMask) { - if (typeMask[0] == '*') { - ptm = 0; // Variable args: don't check parameters. - numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()). - } else { - if (SCSNPRINTF(tm,sizeof(tm),sqT("t|y|x%s"),typeMask) < 0) { -// sq_throwerror(_VM,sqT("CreateFunction: typeMask string too long.")); - throw SquirrelError(sqT("CreateFunction: typeMask string too long.")); - } // if - } // if - } else { // Need to check object type on stack: table, class, instance, etc. - SCSNPRINTF(tm,sizeof(tm),sqT("%s"),sqT("t|y|x")); // table, class, instance. -// tm[0] = 't'; -// tm[1] = 0; - } // if -#if 0 - sq_setparamscheck(_VM,numParams+1,ptm); // Parameters are table+args (thus, the +1). -#else - if (ptm) { - sq_setparamscheck(_VM,numParams,ptm); // Determine arg count from type string. - } // if -#endif -#ifdef _DEBUG - sq_setnativeclosurename(_VM,-1,scriptFuncName); // For debugging only. -#endif - sq_createslot(_VM,-3); // Create slot in table or class (assigning function to slot at scriptNameFunc). - return ret; -} // SquirrelVM::CreateFunction - -SquirrelObject SquirrelVM::CreateFunction(SquirrelObject & so,SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) { - PushObject(so); - SquirrelObject ret = CreateFunction(func,scriptFuncName,typeMask); - Pop(1); - return ret; -} // SquirrelVM::CreateFunction - -// Create a Global function on the root table. -//void CreateFunctionGlobal(HSQUIRRELVM v,const SQChar * scriptFuncName,SQFUNCTION func,SQInteger numParams=0,const SQChar * typeMask=0) { -SquirrelObject SquirrelVM::CreateFunctionGlobal(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) { - PushRootTable(); // Push root table. - // CreateFunction(scriptFuncName,func,numParams,typeMask); - SquirrelObject ret = CreateFunction(func,scriptFuncName,typeMask); - Pop(1); // Pop root table. - return ret; -} // SquirrelVM::CreateFunctionGlobal diff --git a/src/sdk/scripting/sqplus/sqplus.cbp b/src/sdk/scripting/sqplus/sqplus.cbp deleted file mode 100644 index 97991d2473..0000000000 --- a/src/sdk/scripting/sqplus/sqplus.cbp +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/sdk/scripting/sqplus/sqplus.vcproj b/src/sdk/scripting/sqplus/sqplus.vcproj deleted file mode 100644 index 70876fd099..0000000000 --- a/src/sdk/scripting/sqplus/sqplus.vcproj +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/sdk/scripting/sqplus/sqplus71.vcproj b/src/sdk/scripting/sqplus/sqplus71.vcproj deleted file mode 100644 index 872b3be55d..0000000000 --- a/src/sdk/scripting/sqplus/sqplus71.vcproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From e75ebbda6246ef3ef419316cebfe686cabc8c4e6 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Sun, 24 Apr 2016 18:49:17 +0200 Subject: [PATCH 03/16] [NOT COMPILE] Add sqrat binding library Add the new sqrat binding library does not update project files will not compile --- src/include/scripting/sqrat.h | 69 + src/include/scripting/sqrat/sqratAllocator.h | 863 +++ src/include/scripting/sqrat/sqratArray.h | 555 ++ src/include/scripting/sqrat/sqratClass.h | 1052 ++++ src/include/scripting/sqrat/sqratClassType.h | 250 + src/include/scripting/sqrat/sqratConst.h | 200 + src/include/scripting/sqrat/sqratFunction.h | 2673 ++++++++ .../scripting/sqrat/sqratGlobalMethods.h | 2382 +++++++ .../scripting/sqrat/sqratMemberMethods.h | 5597 +++++++++++++++++ src/include/scripting/sqrat/sqratObject.h | 557 ++ .../scripting/sqrat/sqratOverloadMethods.h | 1175 ++++ src/include/scripting/sqrat/sqratScript.h | 243 + src/include/scripting/sqrat/sqratTable.h | 541 ++ src/include/scripting/sqrat/sqratTypes.h | 1121 ++++ src/include/scripting/sqrat/sqratUtil.h | 1197 ++++ src/include/scripting/sqrat/sqratVM.h | 348 + src/include/scripting/sqrat/sqratext_Ref.h | 47 + 17 files changed, 18870 insertions(+) create mode 100644 src/include/scripting/sqrat.h create mode 100644 src/include/scripting/sqrat/sqratAllocator.h create mode 100644 src/include/scripting/sqrat/sqratArray.h create mode 100644 src/include/scripting/sqrat/sqratClass.h create mode 100644 src/include/scripting/sqrat/sqratClassType.h create mode 100644 src/include/scripting/sqrat/sqratConst.h create mode 100644 src/include/scripting/sqrat/sqratFunction.h create mode 100644 src/include/scripting/sqrat/sqratGlobalMethods.h create mode 100644 src/include/scripting/sqrat/sqratMemberMethods.h create mode 100644 src/include/scripting/sqrat/sqratObject.h create mode 100644 src/include/scripting/sqrat/sqratOverloadMethods.h create mode 100644 src/include/scripting/sqrat/sqratScript.h create mode 100644 src/include/scripting/sqrat/sqratTable.h create mode 100644 src/include/scripting/sqrat/sqratTypes.h create mode 100644 src/include/scripting/sqrat/sqratUtil.h create mode 100644 src/include/scripting/sqrat/sqratVM.h create mode 100644 src/include/scripting/sqrat/sqratext_Ref.h diff --git a/src/include/scripting/sqrat.h b/src/include/scripting/sqrat.h new file mode 100644 index 0000000000..3ad372aa59 --- /dev/null +++ b/src/include/scripting/sqrat.h @@ -0,0 +1,69 @@ +// +// Sqrat: Squirrel C++ Binding Utility +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +/*! \mainpage Sqrat Main Page + * + * \section intro_sec Introduction + * + * Sqrat is a C++ library for Squirrel that facilitates exposing classes and other native functionality to Squirrel scripts. It models the underlying Squirrel API closely to give access to a wider range of functionality than other binding libraries. In addition to the binding library, Sqrat features a threading library and a module import library. + * + * \section install_sec Installation + * + * Sqrat only contains C++ headers so for installation you just need to copy the files in the include directory to some common header path. + * + * \section sec_faq Frequently Asked Questions + * + * Q: My application is crashing when I call sq_close. Why is this happening?
+ * A: All Sqrat::Object instances and derived type instances must be destroyed before calling sq_close. + * + * \section discuss_sec Discussion and User Support + * + * Discussion about Sqrat happens at the Squirrel language forum, the Bindings section + * http://squirrel-lang.org/forums/default.aspx?g=topics&f=4 + * + * \section bug_sec Bug Reporting + * + * Bug reports or feature enhancement requests and patches can be submitted at the SourceForge Sqrat site + * https://sourceforge.net/p/scrat/sqrat/ + * + * You're invited to make documentation suggestions for Sqrat. Together, we can make Sqrat as easy to understand as possible! + */ + +#if !defined(_SCRAT_MAIN_H_) +#define _SCRAT_MAIN_H_ + +#include + +#include "sqrat/sqratTable.h" +#include "sqrat/sqratClass.h" +#include "sqrat/sqratFunction.h" +#include "sqrat/sqratConst.h" +#include "sqrat/sqratUtil.h" +#include "sqrat/sqratScript.h" +#include "sqrat/sqratArray.h" + +#endif diff --git a/src/include/scripting/sqrat/sqratAllocator.h b/src/include/scripting/sqrat/sqratAllocator.h new file mode 100644 index 0000000000..9fb23a2b05 --- /dev/null +++ b/src/include/scripting/sqrat/sqratAllocator.h @@ -0,0 +1,863 @@ +// +// SqratAllocator: Custom Class Allocation/Deallocation +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_ALLOCATOR_H_) +#define _SCRAT_ALLOCATOR_H_ + +#include +#include + +#include "sqratObject.h" +#include "sqratTypes.h" + +namespace Sqrat { + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @cond DEV +/// utility taken from http://stackoverflow.com/questions/2733377/is-there-a-way-to-test-whether-a-c-class-has-a-default-constructor-other-than/2770326#2770326 +/// may be obsolete in C++ 11 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template< class T > +class is_default_constructible { + template + class receive_size{}; + + template< class U > + static int sfinae( receive_size< sizeof U() > * ); + + template< class U > + static char sfinae( ... ); + +public: + enum { value = sizeof( sfinae(0) ) == sizeof(int) }; +}; +/// @endcond + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// DefaultAllocator is the allocator to use for Class that can both be constructed and copied +/// +/// \tparam C Type of class +/// +/// \remarks +/// There is mechanisms defined in this class that allow the Class::Ctor method to work properly (e.g. iNew). +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class DefaultAllocator { + + template + struct NewC + { + T* p; + NewC() + { + p = new T(); + } + }; + + template + struct NewC + { + T* p; + NewC() + { + p = 0; + } + }; + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param ptr Should be the return value from a call to the new operator + /// + /// \remarks + /// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr) + { + ClassData* cd = ClassType::getClassData(vm); + sq_setinstanceup(vm, idx, new std::pair::type> >(ptr, cd->instances)); + sq_setreleasehook(vm, idx, &Delete); + sq_getstackobj(vm, idx, &((*cd->instances)[ptr])); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up an instance on the stack for the template class + /// + /// \param vm VM that has an instance object of the correct type at position 1 in its stack + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger New(HSQUIRRELVM vm) { + SetInstance(vm, 1, NewC::value >().p); + return 0; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// @cond DEV + /// following iNew functions are used only if constructors are bound via Ctor() in Sqrat::Class (safe to ignore) + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger iNew(HSQUIRRELVM vm) { + return New(vm); + } + + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + /// @endcond + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param value A pointer to data of the same type as the instance object + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) { + SetInstance(vm, idx, new C(*static_cast(value))); + return 0; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to delete an instance's data + /// + /// \param ptr Pointer to the data contained by the instance + /// \param size Size of the data contained by the instance + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Delete(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + std::pair::type> >* instance = reinterpret_cast::type> >*>(ptr); + instance->second->erase(instance->first); + delete instance->first; + delete instance; + return 0; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// NoConstructor is the allocator to use for Class that can NOT be constructed or copied +/// +/// \tparam C Type of class +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class NoConstructor { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param ptr Should be the return value from a call to the new operator + /// + /// \remarks + /// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr) + { + ClassData* cd = ClassType::getClassData(vm); + sq_setinstanceup(vm, idx, new std::pair::type> >(ptr, cd->instance)); + sq_setreleasehook(vm, idx, &Delete); + sq_getstackobj(vm, idx, &((*cd->instances)[ptr])); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up an instance on the stack for the template class (not allowed in this allocator) + /// + /// \param vm VM that has an instance object of the correct type at position 1 in its stack + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger New(HSQUIRRELVM vm) { +#if !defined (SCRAT_NO_ERROR_CHECKING) + return sq_throwerror(vm, (ClassType::ClassName() + string(_SC(" constructing is not allowed"))).c_str()); +#else + SQUNUSED(vm); + return 0; +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type (not used in this allocator) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param value A pointer to data of the same type as the instance object + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) { + SQUNUSED(vm); + SQUNUSED(idx); + SQUNUSED(value); + return sq_throwerror(vm, (ClassType::ClassName() + string(_SC(" cloning is not allowed"))).c_str()); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to delete an instance's data + /// + /// \param ptr Pointer to the data contained by the instance + /// \param size Size of the data contained by the instance + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Delete(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + std::pair::type> >* instance = reinterpret_cast::type> >*>(ptr); + instance->second->erase(instance->first); + delete instance->first; + delete instance; + return 0; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// CopyOnly is the allocator to use for Class that can be copied but not constructed +/// +/// \tparam C Type of class +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class CopyOnly { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param ptr Should be the return value from a call to the new operator + /// + /// \remarks + /// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr) + { + ClassData* cd = ClassType::getClassData(vm); + sq_setinstanceup(vm, idx, new std::pair::type> >(ptr, cd->instances)); + sq_setreleasehook(vm, idx, &Delete); + sq_getstackobj(vm, idx, &((*cd->instances)[ptr])); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up an instance on the stack for the template class (not allowed in this allocator) + /// + /// \param vm VM that has an instance object of the correct type at position 1 in its stack + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger New(HSQUIRRELVM vm) { +#if !defined (SCRAT_NO_ERROR_CHECKING) + return sq_throwerror(vm, (ClassType::ClassName() + string(_SC(" constructing is not allowed"))).c_str()); +#else + SQUNUSED(vm); + return 0; +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param value A pointer to data of the same type as the instance object + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) { + SetInstance(vm, idx, new C(*static_cast(value))); + return 0; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to delete an instance's data + /// + /// \param ptr Pointer to the data contained by the instance + /// \param size Size of the data contained by the instance + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Delete(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + std::pair::type> >* instance = reinterpret_cast::type> >*>(ptr); + instance->second->erase(instance->first); + delete instance->first; + delete instance; + return 0; + } +}; + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// NoCopy is the allocator to use for Class that can be constructed but not copied +/// +/// \tparam C Type of class +/// +/// \remarks +/// There is mechanisms defined in this class that allow the Class::Ctor method to work properly (e.g. iNew). +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class NoCopy { + + template + struct NewC + { + T* p; + NewC() + { + p = new T(); + } + }; + + template + struct NewC + { + T* p; + NewC() + { + p = 0; + } + }; + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param ptr Should be the return value from a call to the new operator + /// + /// \remarks + /// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr) + { + ClassData* cd = ClassType::getClassData(vm); + sq_setinstanceup(vm, idx, new std::pair::type> >(ptr, cd->instances)); + sq_setreleasehook(vm, idx, &Delete); + sq_getstackobj(vm, idx, &((*cd->instances)[ptr])); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up an instance on the stack for the template class + /// + /// \param vm VM that has an instance object of the correct type at position 1 in its stack + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger New(HSQUIRRELVM vm) { + SetInstance(vm, 1, NewC::value >().p); + return 0; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// @cond DEV + /// following iNew functions are used only if constructors are bound via Ctor() in Sqrat::Class (safe to ignore) + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger iNew(HSQUIRRELVM vm) { + return New(vm); + } + + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + template + static SQInteger iNew(HSQUIRRELVM vm) { + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SetInstance(vm, 1, new C( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + )); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + /// @endcond + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type (not used in this allocator) + /// + /// \param vm VM that has an instance object of the correct type at idx + /// \param idx Index of the stack that the instance object is at + /// \param value A pointer to data of the same type as the instance object + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) { + SQUNUSED(vm); + SQUNUSED(idx); + SQUNUSED(value); + return sq_throwerror(vm, (ClassType::ClassName() + string(_SC(" cloning is not allowed"))).c_str()); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat to delete an instance's data + /// + /// \param ptr Pointer to the data contained by the instance + /// \param size Size of the data contained by the instance + /// + /// \return Squirrel error code + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static SQInteger Delete(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + std::pair::type> >* instance = reinterpret_cast::type> >*>(ptr); + instance->second->erase(instance->first); + delete instance->first; + delete instance; + return 0; + } +}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratArray.h b/src/include/scripting/sqrat/sqratArray.h new file mode 100644 index 0000000000..bd1c0aaf2b --- /dev/null +++ b/src/include/scripting/sqrat/sqratArray.h @@ -0,0 +1,555 @@ +// +// SqratArray: Array Binding +// + +// +// Copyright 2011 Alston Chen +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_ARRAY_H_) +#define _SCRAT_ARRAY_H_ + +#include +#include + +#include "sqratObject.h" +#include "sqratFunction.h" +#include "sqratGlobalMethods.h" + +namespace Sqrat { + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// The base class for Array that implements almost all of its functionality +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class ArrayBase : public Object { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor (null) + /// + /// \param v VM that the array will exist in + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ArrayBase(HSQUIRRELVM v = DefaultVM::Get()) : Object(v, true) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the ArrayBase from an Object that already exists + /// + /// \param obj An Object that should already represent a Squirrel array + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ArrayBase(const Object& obj) : Object(obj) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the ArrayBase from a HSQOBJECT and HSQUIRRELVM that already exist + /// + /// \param o Squirrel object that should already represent a Squirrel array + /// \param v Squirrel VM that contains the Squirrel object given + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ArrayBase(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : Object(o, v) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a Table or Class to the Array (can be used to facilitate namespaces) + /// + /// \param index The index in the array being assigned a Table or Class + /// \param obj Table or Class that is being placed in the Array + /// + /// \remarks + /// Bind cannot be called "inline" like other functions because it introduces order-of-initialization bugs. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Bind(const SQInteger index, Object& obj) { + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); + sq_pushobject(vm, obj.GetObject()); + sq_set(vm, -3); + sq_pop(vm,1); // pop array + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a raw Squirrel closure to the Array + /// + /// \param index The index in the array being assigned a function + /// \param func Squirrel function that is being placed in the Array + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ArrayBase& SquirrelFunc(const SQInteger index, SQFUNCTION func) { + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); + sq_newclosure(vm, func, 0); + sq_set(vm, -3); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets an index in the Array to a specific value + /// + /// \param index The index in the array being assigned a value + /// \param val Value that is being placed in the Array + /// + /// \tparam V Type of value (usually doesnt need to be defined explicitly) + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + ArrayBase& SetValue(const SQInteger index, const V& val) { + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); + PushVar(vm, val); + sq_set(vm, -3); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets an index in the Array to a specific instance (like a reference) + /// + /// \param index The index in the array being assigned a value + /// \param val Pointer to the instance that is being placed in the Array + /// + /// \tparam V Type of instance (usually doesnt need to be defined explicitly) + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + ArrayBase& SetInstance(const SQInteger index, V* val) { + BindInstance(index, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets an index in the Array to a specific function + /// + /// \param index The index in the array being assigned a value + /// \param method Function that is being placed in the Array + /// + /// \tparam F Type of function (only define this if you need to choose a certain template specialization or overload) + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + ArrayBase& Func(const SQInteger index, F method) { + BindFunc(index, &method, sizeof(method), SqGlobalFunc(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns the element at a given index + /// + /// \param index Index of the element + /// + /// \tparam T Type of element (fails if element is not of this type) + /// + /// \return SharedPtr containing the element (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr GetValue(int index) + { + sq_pushobject(vm, obj); + sq_pushinteger(vm, index); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + SQTHROW(vm, _SC("illegal index")); + return SharedPtr(); + } +#else + sq_get(vm, -2); +#endif + SQTRY() + Var > element(vm, -1); + SQCATCH_NOEXCEPT(vm) { + sq_pop(vm, 2); + return SharedPtr(); + } + sq_pop(vm, 2); + return element.value; + SQCATCH(vm) { +#if defined (SCRAT_USE_EXCEPTIONS) + SQUNUSED(e); // avoid "unreferenced local variable" warning +#endif + sq_pop(vm, 2); + SQRETHROW(vm); + } + return SharedPtr(); // avoid "not all control paths return a value" warning + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets a Function from an index in the Array + /// + /// \param index The index in the array that contains the Function + /// + /// \return Function found in the Array (null if failed) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function GetFunction(const SQInteger index) { + HSQOBJECT funcObj; + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + return Function(); + } + SQObjectType value_type = sq_gettype(vm, -1); + if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) { + sq_pop(vm, 2); + return Function(); + } +#else + sq_get(vm, -2); +#endif + sq_getstackobj(vm, -1, &funcObj); + Function ret(vm, GetObject(), funcObj); // must addref before the pop! + sq_pop(vm, 2); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Fills a C array with the elements of the Array + /// + /// \param array C array to be filled + /// \param size The amount of elements to fill the C array with + /// + /// \tparam T Type of elements (fails if any elements in Array are not of this type) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void GetArray(T* array, int size) + { + HSQOBJECT value = GetObject(); + sq_pushobject(vm, value); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (size > sq_getsize(vm, -1)) { + sq_pop(vm, 1); + SQTHROW(vm, _SC("array buffer size too big")); + return; + } +#endif + sq_pushnull(vm); + SQInteger i; + while (SQ_SUCCEEDED(sq_next(vm, -2))) { + sq_getinteger(vm, -2, &i); + if (i >= size) break; + SQTRY() + Var element(vm, -1); + SQCATCH_NOEXCEPT(vm) { + sq_pop(vm, 4); + return; + } + sq_pop(vm, 2); + array[i] = element.value; + SQCATCH(vm) { +#if defined (SCRAT_USE_EXCEPTIONS) + SQUNUSED(e); // avoid "unreferenced local variable" warning +#endif + sq_pop(vm, 4); + SQRETHROW(vm); + } + } + sq_pop(vm, 2); // pops the null iterator and the array object + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Appends a value to the end of the Array + /// + /// \param val Value that is being placed in the Array + /// + /// \tparam V Type of value (usually doesnt need to be defined explicitly) + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + ArrayBase& Append(const V& val) { + sq_pushobject(vm, GetObject()); + PushVar(vm, val); + sq_arrayappend(vm, -2); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Appends an instance to the end of the Array (like a reference) + /// + /// \param val Pointer to the instance that is being placed in the Array + /// + /// \tparam V Type of instance (usually doesnt need to be defined explicitly) + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + ArrayBase& Append(V* val) { + sq_pushobject(vm, GetObject()); + PushVar(vm, val); + sq_arrayappend(vm, -2); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Inserts a value in a position in the Array + /// + /// \param destpos Index to put the new value in + /// \param val Value that is being placed in the Array + /// + /// \tparam V Type of value (usually doesnt need to be defined explicitly) + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + ArrayBase& Insert(const SQInteger destpos, const V& val) { + sq_pushobject(vm, GetObject()); + PushVar(vm, val); + sq_arrayinsert(vm, -2, destpos); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Inserts an instance in a position in the Array (like a reference) + /// + /// \param destpos Index to put the new value in + /// \param val Pointer to the instance that is being placed in the Array + /// + /// \tparam V Type of instance (usually doesnt need to be defined explicitly) + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + ArrayBase& Insert(const SQInteger destpos, V* val) { + sq_pushobject(vm, GetObject()); + PushVar(vm, val); + sq_arrayinsert(vm, -2, destpos); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Removes the last element from the Array + /// + /// \return Object for the element that was removed (null if failed) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Object Pop() { + HSQOBJECT slotObj; + sq_pushobject(vm, GetObject()); + if(SQ_FAILED(sq_arraypop(vm, -1, true))) { + sq_pop(vm, 1); + return Object(); // Return a NULL object + } else { + sq_getstackobj(vm, -1, &slotObj); + Object ret(slotObj, vm); + sq_pop(vm, 2); + return ret; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Removes an element at a specific index from the Array + /// + /// \param itemidx Index of the element being removed + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ArrayBase& Remove(const SQInteger itemidx) { + sq_pushobject(vm, GetObject()); + sq_arrayremove(vm, -1, itemidx); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Resizes the Array + /// + /// \param newsize Desired size of the Array in number of elements + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ArrayBase& Resize(const SQInteger newsize) { + sq_pushobject(vm, GetObject()); + sq_arrayresize(vm, -1, newsize); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Reverses the elements of the array in place + /// + /// \return The Array itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ArrayBase& Reverse() { + sq_pushobject(vm, GetObject()); + sq_arrayreverse(vm, -1); + sq_pop(vm,1); // pop array + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns the length of the Array + /// + /// \return Length in number of elements + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SQInteger Length() const + { + sq_pushobject(vm, obj); + SQInteger r = sq_getsize(vm, -1); + sq_pop(vm, 1); + return r; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Represents an array in Squirrel +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Array : public ArrayBase { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor (null) + /// + /// \remarks + /// The Array is invalid until it is given a VM to exist in. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Array() { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs an Array + /// + /// \param v VM to create the Array in + /// \param size An optional size hint + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Array(HSQUIRRELVM v, const SQInteger size = 0) : ArrayBase(v) { + sq_newarray(vm, size); + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(vm,1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the Array from an Object that already exists + /// + /// \param obj An Object that should already represent a Squirrel array + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Array(const Object& obj) : ArrayBase(obj) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the Array from a HSQOBJECT and HSQUIRRELVM that already exist + /// + /// \param o Squirrel object that should already represent a Squirrel array + /// \param v Squirrel VM that contains the Squirrel object given + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Array(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : ArrayBase(o, v) { + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Array instances to and from the stack as references (arrays are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + Array value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as an Array + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + HSQOBJECT obj; + sq_resetobject(&obj); + sq_getstackobj(vm,idx,&obj); + value = Array(obj, vm); +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQObjectType value_type = sq_gettype(vm, idx); + if (value_type != OT_ARRAY) { + SQTHROW(vm, FormatTypeError(vm, idx, _SC("array"))); + } +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put an Array reference on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const Array& value) { + HSQOBJECT obj; + sq_resetobject(&obj); + obj = value.GetObject(); + sq_pushobject(vm,obj); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Array instances to and from the stack as references (arrays are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var {Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {}}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Array instances to and from the stack as references (arrays are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var {Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {}}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratClass.h b/src/include/scripting/sqrat/sqratClass.h new file mode 100644 index 0000000000..da0698116c --- /dev/null +++ b/src/include/scripting/sqrat/sqratClass.h @@ -0,0 +1,1052 @@ +// +// SqratClass: Class Binding +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_CLASS_H_) +#define _SCRAT_CLASS_H_ + +#include +#include +#include + +#include "sqratObject.h" +#include "sqratClassType.h" +#include "sqratMemberMethods.h" +#include "sqratAllocator.h" +#include "sqratTypes.h" + +namespace Sqrat +{ + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Facilitates exposing a C++ class with no base class to Squirrel +/// +/// \tparam C Class type to expose +/// \tparam A An allocator to use when instantiating and destroying class instances of this type in Squirrel +/// +/// \remarks +/// DefaultAllocator is used if no allocator is specified. This should be sufficent for most classes, +/// but if specific behavior is desired, it can be overridden. If the class should not be instantiated from +/// Squirrel the NoConstructor allocator may be used. See NoCopy and CopyOnly too. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template > +class Class : public Object +{ +private: + + static SQInteger cleanup_hook(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + ClassData** ud = reinterpret_cast**>(ptr); + delete *ud; + return 0; + } + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs the Class object + /// + /// A Class object doesnt do anything on its own. + /// It must be told what methods and variables it contains. + /// This is done using Class methods such as Class::Func and Class::Var. + /// Then the Class must be exposed to Squirrel. + /// This is usually done by calling TableBase::Bind on a RootTable with the Class. + /// + /// \param v Squirrel virtual machine to create the Class for + /// \param className A necessarily unique name for the class that can appear in error messages + /// \param createClass Should class type data be created? (almost always should be true - don't worry about it) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Class(HSQUIRRELVM v, const string& className, bool createClass = true) : Object(v, false) { + if (createClass && !ClassType::hasClassData(v)) { + sq_pushregistrytable(v); + sq_pushstring(v, "__classes", -1); + if (SQ_FAILED(sq_rawget(v, -2))) { + sq_newtable(v); + sq_pushstring(v, "__classes", -1); + sq_push(v, -2); + sq_rawset(v, -4); + } + sq_pushstring(v, className.c_str(), -1); + ClassData** ud = reinterpret_cast**>(sq_newuserdata(v, sizeof(ClassData*))); + *ud = new ClassData; + sq_setreleasehook(v, -1, &cleanup_hook); + sq_rawset(v, -3); + sq_pop(v, 2); + + ClassData* cd = *ud; + + if (ClassType::getStaticClassData().Expired()) { + cd->staticData.Init(new StaticClassData); + cd->staticData->copyFunc = &A::Copy; + cd->staticData->className = string(className); + cd->staticData->baseClass = NULL; + + ClassType::getStaticClassData() = cd->staticData; + } else { + cd->staticData = ClassType::getStaticClassData().Lock(); + } + + HSQOBJECT& classObj = cd->classObj; + sq_resetobject(&classObj); + + sq_newclass(v, false); + sq_getstackobj(v, -1, &classObj); + sq_addref(v, &classObj); // must addref before the pop! + sq_pop(v, 1); + InitClass(cd); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel object for this Class (copy) + /// + /// \return Squirrel object representing the Squirrel class + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual HSQOBJECT GetObject() const { + return ClassType::getClassData(vm)->classObj; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel object for this Class (reference) + /// + /// \return Squirrel object representing the Squirrel class + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual HSQOBJECT& GetObject() { + return ClassType::getClassData(vm)->classObj; + } + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assigns a static class slot a value + /// + /// \param name Name of the static slot + /// \param val Value to assign + /// + /// \tparam V Type of value (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// Static values are read-only in Squirrel. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& SetStaticValue(const SQChar* name, const V& val) { + BindValue(name, val, true); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assigns a class slot a value + /// + /// \param name Name of the slot + /// \param val Value to assign + /// + /// \tparam V Type of value (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& SetValue(const SQChar* name, const V& val) { + BindValue(name, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a class variable + /// + /// \param name Name of the variable as it will appear in Squirrel + /// \param var Variable to bind + /// + /// \tparam V Type of variable (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// If V is not a pointer or reference, then it must have a default constructor. + /// See Sqrat::Class::Prop to work around this requirement + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Var(const SQChar* name, V C::* var) { + ClassData* cd = ClassType::getClassData(vm); + + // Add the getter + BindAccessor(name, &var, sizeof(var), &sqDefaultGet, cd->getTable); + + // Add the setter + BindAccessor(name, &var, sizeof(var), &sqDefaultSet, cd->setTable); + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a class variable without a setter + /// + /// \param name Name of the variable as it will appear in Squirrel + /// \param var Variable to bind + /// + /// \tparam V Type of variable (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// If V is not a pointer or reference, then it must have a default constructor. + /// See Sqrat::Class::Prop to work around this requirement + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& ConstVar(const SQChar* name, V C::* var) { + ClassData* cd = ClassType::getClassData(vm); + + // Add the getter + BindAccessor(name, &var, sizeof(var), &sqDefaultGet, cd->getTable); + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Bind a class static variable + /// + /// \param name Name of the variable as it will appear in Squirrel + /// \param var Variable to bind + /// + /// \tparam V Type of variable (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// If V is not a pointer or reference, then it must have a default constructor. + /// See Sqrat::Class::Prop to work around this requirement + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& StaticVar(const SQChar* name, V* var) { + ClassData* cd = ClassType::getClassData(vm); + + // Add the getter + BindAccessor(name, &var, sizeof(var), &sqStaticGet, cd->getTable); + + // Add the setter + BindAccessor(name, &var, sizeof(var), &sqStaticSet, cd->setTable); + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a class property + /// + /// \param name Name of the variable as it will appear in Squirrel + /// \param getMethod Getter for the variable + /// \param setMethod Setter for the variable + /// + /// \tparam F1 Type of get function (usually doesnt need to be defined explicitly) + /// \tparam F2 Type of set function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// This method binds setter and getter functions in C++ to Squirrel as if they are a class variable. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Prop(const SQChar* name, F1 getMethod, F2 setMethod) { + ClassData* cd = ClassType::getClassData(vm); + + if(getMethod != NULL) { + // Add the getter + BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberOverloadedFunc(getMethod), cd->getTable); + } + + if(setMethod != NULL) { + // Add the setter + BindAccessor(name, &setMethod, sizeof(setMethod), SqMemberOverloadedFunc(setMethod), cd->setTable); + } + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a class property (using global functions instead of member functions) + /// + /// \param name Name of the variable as it will appear in Squirrel + /// \param getMethod Getter for the variable + /// \param setMethod Setter for the variable + /// + /// \tparam F1 Type of get function (usually doesnt need to be defined explicitly) + /// \tparam F2 Type of set function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// This method binds setter and getter functions in C++ to Squirrel as if they are a class variable. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& GlobalProp(const SQChar* name, F1 getMethod, F2 setMethod) { + ClassData* cd = ClassType::getClassData(vm); + + if(getMethod != NULL) { + // Add the getter + BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberGlobalOverloadedFunc(getMethod), cd->getTable); + } + + if(setMethod != NULL) { + // Add the setter + BindAccessor(name, &setMethod, sizeof(setMethod), SqMemberGlobalOverloadedFunc(setMethod), cd->setTable); + } + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a read-only class property + /// + /// \param name Name of the variable as it will appear in Squirrel + /// \param getMethod Getter for the variable + /// + /// \tparam F Type of get function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// This method binds a getter function in C++ to Squirrel as if it is a class variable. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Prop(const SQChar* name, F getMethod) { + // Add the getter + BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberOverloadedFunc(getMethod), ClassType::getClassData(vm)->getTable); + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a read-only class property (using a global function instead of a member function) + /// + /// \param name Name of the variable as it will appear in Squirrel + /// \param getMethod Getter for the variable + /// + /// \tparam F Type of get function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// This method binds a getter function in C++ to Squirrel as if it is a class variable. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& GlobalProp(const SQChar* name, F getMethod) { + // Add the getter + BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberGlobalOverloadedFunc(getMethod), ClassType::getClassData(vm)->getTable); + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a class function + /// + /// \param name Name of the function as it will appear in Squirrel + /// \param method Function to bind + /// + /// \tparam F Type of function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Func(const SQChar* name, F method) { + BindFunc(name, &method, sizeof(method), SqMemberFunc(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a class function with overloading enabled + /// + /// \param name Name of the function as it will appear in Squirrel + /// \param method Function to bind + /// + /// \tparam F Type of function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// Overloading in this context means to allow the function name to be used with functions + /// of a different number of arguments. This definition differs from others (e.g. C++'s). + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Overload(const SQChar* name, F method) { + BindOverload(name, &method, sizeof(method), SqMemberOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a global function as a class function + /// + /// \param name Name of the function as it will appear in Squirrel + /// \param method Function to bind + /// + /// \tparam F Type of function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& GlobalFunc(const SQChar* name, F method) { + BindFunc(name, &method, sizeof(method), SqMemberGlobalFunc(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a static class function + /// + /// \param name Name of the function as it will appear in Squirrel + /// \param method Function to bind + /// + /// \tparam F Type of function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& StaticFunc(const SQChar* name, F method) { + BindFunc(name, &method, sizeof(method), SqGlobalFunc(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a global function as a class function with overloading enabled + /// + /// \param name Name of the function as it will appear in Squirrel + /// \param method Function to bind + /// + /// \tparam F Type of function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// Overloading in this context means to allow the function name to be used with functions + /// of a different number of arguments. This definition differs from others (e.g. C++'s). + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& GlobalOverload(const SQChar* name, F method) { + BindOverload(name, &method, sizeof(method), SqMemberGlobalOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method) - 1); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a static class function with overloading enabled + /// + /// \param name Name of the function as it will appear in Squirrel + /// \param method Function to bind + /// + /// \tparam F Type of function (usually doesnt need to be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// Overloading in this context means to allow the function name to be used with functions + /// of a different number of arguments. This definition differs from others (e.g. C++'s). + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& StaticOverload(const SQChar* name, F method) { + BindOverload(name, &method, sizeof(method), SqGlobalOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a Squirrel function as defined by the Squirrel documentation as a class function + /// + /// \param name Name of the function as it will appear in Squirrel + /// \param func Function to bind + /// + /// \return The Class itself so the call can be chained + /// + /// \remarks + /// Inside of the function, the class instance the function was called with will be at index 1 on the + /// stack and all arguments will be after that index in the order they were given to the function. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Class& SquirrelFunc(const SQChar* name, SQFUNCTION func) { + sq_pushobject(vm, ClassType::getClassData(vm)->classObj); + sq_pushstring(vm, name, -1); + sq_newclosure(vm, func, 0); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); // pop table + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets a Function from a name in the Class + /// + /// \param name The name in the class that contains the Function + /// + /// \return Function found in the Class (null if failed) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function GetFunction(const SQChar* name) { + ClassData* cd = ClassType::getClassData(vm); + HSQOBJECT funcObj; + sq_pushobject(vm, cd->classObj); + sq_pushstring(vm, name, -1); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + return Function(); + } + SQObjectType value_type = sq_gettype(vm, -1); + if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) { + sq_pop(vm, 2); + return Function(); + } +#else + sq_get(vm, -2); +#endif + sq_getstackobj(vm, -1, &funcObj); + Function ret(vm, cd->classObj, funcObj); // must addref before the pop! + sq_pop(vm, 2); + return ret; + } + +protected: + +/// @cond DEV + + static SQInteger ClassWeakref(HSQUIRRELVM vm) { + sq_weakref(vm, -1); + return 1; + } + + static SQInteger ClassTypeof(HSQUIRRELVM vm) { + sq_pushstring(vm, ClassType::ClassName().c_str(), -1); + return 1; + } + + static SQInteger ClassCloned(HSQUIRRELVM vm) { + SQTRY() + Sqrat::Var other(vm, 2); + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); + return SQ_ERROR; + } +#if !defined (SCRAT_NO_ERROR_CHECKING) + return ClassType::CopyFunc()(vm, 1, other.value); +#else + ClassType::CopyFunc()(vm, 1, other.value); + return 0; +#endif + SQCATCH(vm) { +#if defined (SCRAT_USE_EXCEPTIONS) + SQUNUSED(e); // this is to avoid a warning in MSVC +#endif + return SQ_ERROR; + } + } + + // Initialize the required data structure for the class + void InitClass(ClassData* cd) { + cd->instances.Init(new typename unordered_map::type); + + // push the class + sq_pushobject(vm, cd->classObj); + + // set the typetag of the class + sq_settypetag(vm, -1, cd->staticData.Get()); + + // add the default constructor + sq_pushstring(vm, _SC("constructor"), -1); + sq_newclosure(vm, &A::New, 0); + sq_newslot(vm, -3, false); + + // add the set table (static) + HSQOBJECT& setTable = cd->setTable; + sq_resetobject(&setTable); + sq_pushstring(vm, _SC("__setTable"), -1); + sq_newtable(vm); + sq_getstackobj(vm, -1, &setTable); + sq_addref(vm, &setTable); + sq_newslot(vm, -3, true); + + // add the get table (static) + HSQOBJECT& getTable = cd->getTable; + sq_resetobject(&getTable); + sq_pushstring(vm, _SC("__getTable"), -1); + sq_newtable(vm); + sq_getstackobj(vm, -1, &getTable); + sq_addref(vm, &getTable); + sq_newslot(vm, -3, true); + + // override _set + sq_pushstring(vm, _SC("_set"), -1); + sq_pushobject(vm, setTable); // Push the set table as a free variable + sq_newclosure(vm, &sqVarSet, 1); + sq_newslot(vm, -3, false); + + // override _get + sq_pushstring(vm, _SC("_get"), -1); + sq_pushobject(vm, getTable); // Push the get table as a free variable + sq_newclosure(vm, &sqVarGet, 1); + sq_newslot(vm, -3, false); + + // add weakref (apparently not provided by default) + sq_pushstring(vm, _SC("weakref"), -1); + sq_newclosure(vm, &Class::ClassWeakref, 0); + sq_newslot(vm, -3, false); + + // add _typeof + sq_pushstring(vm, _SC("_typeof"), -1); + sq_newclosure(vm, &Class::ClassTypeof, 0); + sq_newslot(vm, -3, false); + + // add _cloned + sq_pushstring(vm, _SC("_cloned"), -1); + sq_newclosure(vm, &Class::ClassCloned, 0); + sq_newslot(vm, -3, false); + + // pop the class + sq_pop(vm, 1); + } + + // Helper function used to bind getters and setters + inline void BindAccessor(const SQChar* name, void* var, size_t varSize, SQFUNCTION func, HSQOBJECT table) { + // Push the get or set table + sq_pushobject(vm, table); + sq_pushstring(vm, name, -1); + + // Push the variable offset as a free variable + SQUserPointer varPtr = sq_newuserdata(vm, static_cast(varSize)); + memcpy(varPtr, var, varSize); + + // Create the accessor function + sq_newclosure(vm, func, 1); + + // Add the accessor to the table + sq_newslot(vm, -3, false); + + // Pop get/set table + sq_pop(vm, 1); + } + + // constructor binding + Class& BindConstructor(SQFUNCTION method, SQInteger nParams, const SQChar *name = 0) { + SQFUNCTION overload = SqOverloadFunc(method); + bool alternative_global = false; + if (name == 0) + name = _SC("constructor"); + else alternative_global = true; + string overloadName = SqOverloadName::Get(name, nParams); + + if (!alternative_global ) + { + // push the class + sq_pushobject(vm, ClassType::getClassData(vm)->classObj); + } + else + { + // the containing environment is the root table?? + sq_pushroottable(vm); + } + + // Bind overload handler + sq_pushstring(vm, name, -1); + sq_pushstring(vm, name, -1); // function name is passed as a free variable + sq_newclosure(vm, overload, 1); + sq_newslot(vm, -3, false); + + // Bind overloaded allocator function + sq_pushstring(vm, overloadName.c_str(), -1); + sq_newclosure(vm, method, 0); + sq_setparamscheck(vm,nParams + 1,NULL); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + return *this; + } + +/// @endcond + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with no arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::iNew, 0, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 1 argument (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 1, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 2 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 2, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 3 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// \tparam A3 Type of argument 3 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 3, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 4 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// \tparam A3 Type of argument 3 of the constructor (must be defined explicitly) + /// \tparam A4 Type of argument 4 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 4, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 5 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// \tparam A3 Type of argument 3 of the constructor (must be defined explicitly) + /// \tparam A4 Type of argument 4 of the constructor (must be defined explicitly) + /// \tparam A5 Type of argument 5 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 5, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 6 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// \tparam A3 Type of argument 3 of the constructor (must be defined explicitly) + /// \tparam A4 Type of argument 4 of the constructor (must be defined explicitly) + /// \tparam A5 Type of argument 5 of the constructor (must be defined explicitly) + /// \tparam A6 Type of argument 6 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 6, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 7 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// \tparam A3 Type of argument 3 of the constructor (must be defined explicitly) + /// \tparam A4 Type of argument 4 of the constructor (must be defined explicitly) + /// \tparam A5 Type of argument 5 of the constructor (must be defined explicitly) + /// \tparam A6 Type of argument 6 of the constructor (must be defined explicitly) + /// \tparam A7 Type of argument 7 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 7, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 8 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// \tparam A3 Type of argument 3 of the constructor (must be defined explicitly) + /// \tparam A4 Type of argument 4 of the constructor (must be defined explicitly) + /// \tparam A5 Type of argument 5 of the constructor (must be defined explicitly) + /// \tparam A6 Type of argument 6 of the constructor (must be defined explicitly) + /// \tparam A7 Type of argument 7 of the constructor (must be defined explicitly) + /// \tparam A8 Type of argument 8 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 8, name); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constructor with 9 arguments (there can only be one constructor of this many arguments for a given name) + /// + /// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor) + /// + /// \tparam A1 Type of argument 1 of the constructor (must be defined explicitly) + /// \tparam A2 Type of argument 2 of the constructor (must be defined explicitly) + /// \tparam A3 Type of argument 3 of the constructor (must be defined explicitly) + /// \tparam A4 Type of argument 4 of the constructor (must be defined explicitly) + /// \tparam A5 Type of argument 5 of the constructor (must be defined explicitly) + /// \tparam A6 Type of argument 6 of the constructor (must be defined explicitly) + /// \tparam A7 Type of argument 7 of the constructor (must be defined explicitly) + /// \tparam A8 Type of argument 8 of the constructor (must be defined explicitly) + /// \tparam A9 Type of argument 9 of the constructor (must be defined explicitly) + /// + /// \return The Class itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Class& Ctor(const SQChar *name = 0) { + return BindConstructor(A::template iNew, 9, name); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Facilitates exposing a C++ class with a base class to Squirrel +/// +/// \tparam C Class type to expose +/// \tparam B Base class type (must already be bound) +/// \tparam A An allocator to use when instantiating and destroying class instances of this type in Squirrel +/// +/// \remarks +/// Classes in Squirrel are single-inheritance only, and as such Sqrat only allows for single inheritance as well. +/// +/// \remarks +/// DefaultAllocator is used if no allocator is specified. This should be sufficent for most classes, +/// but if specific behavior is desired, it can be overridden. If the class should not be instantiated from +/// Squirrel the NoConstructor allocator may be used. See NoCopy and CopyOnly too. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template > +class DerivedClass : public Class +{ +private: + + static SQInteger cleanup_hook(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + ClassData** ud = reinterpret_cast**>(ptr); + delete *ud; + return 0; + } + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs the DerivedClass object + /// + /// A DerivedClass object doesnt do anything on its own. + /// It must be told what methods and variables it contains. + /// This is done using Class methods such as Class::Func and Class::Var. + /// Then the DerivedClass must be exposed to Squirrel. + /// This is usually done by calling TableBase::Bind on a RootTable with the DerivedClass. + /// + /// \param v Squirrel virtual machine to create the DerivedClass for + /// \param className A necessarily unique name for the class that can appear in error messages + /// + /// \remarks + /// You MUST bind the base class fully before constructing a derived class. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + DerivedClass(HSQUIRRELVM v, const string& className) : Class(v, string(), false) { + if (!ClassType::hasClassData(v)) { + sq_pushregistrytable(v); + sq_pushstring(v, "__classes", -1); + if (SQ_FAILED(sq_rawget(v, -2))) { + sq_newtable(v); + sq_pushstring(v, "__classes", -1); + sq_push(v, -2); + sq_rawset(v, -4); + } + sq_pushstring(v, className.c_str(), -1); + ClassData** ud = reinterpret_cast**>(sq_newuserdata(v, sizeof(ClassData*))); + *ud = new ClassData; + sq_setreleasehook(v, -1, &cleanup_hook); + sq_rawset(v, -3); + sq_pop(v, 2); + + ClassData* bd = ClassType::getClassData(v); + ClassData* cd = *ud; + + if (ClassType::getStaticClassData().Expired()) { + cd->staticData.Init(new StaticClassData); + cd->staticData->copyFunc = &A::Copy; + cd->staticData->className = string(className); + cd->staticData->baseClass = bd->staticData.Get(); + + ClassType::getStaticClassData() = cd->staticData; + } else { + cd->staticData = ClassType::getStaticClassData().Lock(); + } + + HSQOBJECT& classObj = cd->classObj; + sq_resetobject(&classObj); + + sq_pushobject(v, bd->classObj); + sq_newclass(v, true); + sq_getstackobj(v, -1, &classObj); + sq_addref(v, &classObj); // must addref before the pop! + sq_pop(v, 1); + InitDerivedClass(v, cd, bd); + } + } + +protected: + +/// @cond DEV + + void InitDerivedClass(HSQUIRRELVM vm, ClassData* cd, ClassData* bd) { + cd->instances.Init(new typename unordered_map::type); + + // push the class + sq_pushobject(vm, cd->classObj); + + // set the typetag of the class + sq_settypetag(vm, -1, cd->staticData.Get()); + + // add the default constructor + sq_pushstring(vm, _SC("constructor"), -1); + sq_newclosure(vm, &A::New, 0); + sq_newslot(vm, -3, false); + + // clone the base classes set table (static) + HSQOBJECT& setTable = cd->setTable; + sq_resetobject(&setTable); + sq_pushobject(vm, bd->setTable); + sq_pushstring(vm, _SC("__setTable"), -1); + sq_clone(vm, -2); + sq_remove(vm, -3); + sq_getstackobj(vm, -1, &setTable); + sq_addref(vm, &setTable); + sq_newslot(vm, -3, true); + + // clone the base classes get table (static) + HSQOBJECT& getTable = cd->getTable; + sq_resetobject(&getTable); + sq_pushobject(vm, bd->getTable); + sq_pushstring(vm, _SC("__getTable"), -1); + sq_clone(vm, -2); + sq_remove(vm, -3); + sq_getstackobj(vm, -1, &getTable); + sq_addref(vm, &getTable); + sq_newslot(vm, -3, true); + + // override _set + sq_pushstring(vm, _SC("_set"), -1); + sq_pushobject(vm, setTable); // Push the set table as a free variable + sq_newclosure(vm, sqVarSet, 1); + sq_newslot(vm, -3, false); + + // override _get + sq_pushstring(vm, _SC("_get"), -1); + sq_pushobject(vm, getTable); // Push the get table as a free variable + sq_newclosure(vm, sqVarGet, 1); + sq_newslot(vm, -3, false); + + // add weakref (apparently not provided by default) + sq_pushstring(vm, _SC("weakref"), -1); + sq_newclosure(vm, &Class::ClassWeakref, 0); + sq_newslot(vm, -3, false); + + // add _typeof + sq_pushstring(vm, _SC("_typeof"), -1); + sq_newclosure(vm, &Class::ClassTypeof, 0); + sq_newslot(vm, -3, false); + + // add _cloned + sq_pushstring(vm, _SC("_cloned"), -1); + sq_newclosure(vm, &Class::ClassCloned, 0); + sq_newslot(vm, -3, false); + + // pop the class + sq_pop(vm, 1); + } + +/// @endcond + +}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratClassType.h b/src/include/scripting/sqrat/sqratClassType.h new file mode 100644 index 0000000000..54a3ba1bc7 --- /dev/null +++ b/src/include/scripting/sqrat/sqratClassType.h @@ -0,0 +1,250 @@ +// +// SqratClassType: Type Translators +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_CLASSTYPE_H_) +#define _SCRAT_CLASSTYPE_H_ + +#include +#include + +#include "sqratUtil.h" + +namespace Sqrat +{ + +/// @cond DEV + +// The copy function for a class +typedef SQInteger (*COPYFUNC)(HSQUIRRELVM, SQInteger, const void*); + +// Every Squirrel class instance made by Sqrat has its type tag set to a AbstractStaticClassData object that is unique per C++ class +struct AbstractStaticClassData { + AbstractStaticClassData() {} + virtual ~AbstractStaticClassData() {} + virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) = 0; + AbstractStaticClassData* baseClass; + string className; + COPYFUNC copyFunc; +}; + +// StaticClassData keeps track of the nearest base class B and the class associated with itself C in order to cast C++ pointers to the right base class +template +struct StaticClassData : public AbstractStaticClassData { + virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) { + if (classType != this) { + ptr = baseClass->Cast(static_cast(static_cast(ptr)), classType); + } + return ptr; + } +}; + +// Every Squirrel class object created by Sqrat in every VM has its own unique ClassData object stored in the registry table of the VM +template +struct ClassData { + HSQOBJECT classObj; + HSQOBJECT getTable; + HSQOBJECT setTable; + SharedPtr::type> instances; + SharedPtr staticData; +}; + +// Lookup static class data by type_info rather than a template because C++ cannot export generic templates +class _ClassType_helper { +public: +#if defined(SCRAT_IMPORT) + static SQRAT_API WeakPtr& _getStaticClassData(const std::type_info* type); +#else + struct compare_type_info { + bool operator ()(const std::type_info* left, const std::type_info* right) const { + return left->before(*right) != 0; + } + }; + static SQRAT_API WeakPtr& _getStaticClassData(const std::type_info* type) { + static std::map, compare_type_info> data; + return data[type]; + } +#endif +}; + +// Internal helper class for managing classes +template +class ClassType { +public: + + static inline ClassData* getClassData(HSQUIRRELVM vm) { + sq_pushregistrytable(vm); + sq_pushstring(vm, "__classes", -1); +#ifndef NDEBUG + SQRESULT r = sq_rawget(vm, -2); + assert(SQ_SUCCEEDED(r)); // fails if getClassData is called when the data does not exist for the given VM yet (bind the class) +#else + sq_rawget(vm, -2); +#endif + sq_pushstring(vm, ClassName().c_str(), -1); +#ifndef NDEBUG + r = sq_rawget(vm, -2); + assert(SQ_SUCCEEDED(r)); // fails if getClassData is called when the data does not exist for the given VM yet (bind the class) +#else + sq_rawget(vm, -2); +#endif + ClassData** ud; + sq_getuserdata(vm, -1, (SQUserPointer*)&ud, NULL); + sq_pop(vm, 3); + return *ud; + } + + static WeakPtr& getStaticClassData() { + return _ClassType_helper::_getStaticClassData(&typeid(C)); + } + + static inline bool hasClassData(HSQUIRRELVM vm) { + if (!getStaticClassData().Expired()) { + sq_pushregistrytable(vm); + sq_pushstring(vm, "__classes", -1); + if (SQ_SUCCEEDED(sq_rawget(vm, -2))) { + sq_pushstring(vm, ClassName().c_str(), -1); + if (SQ_SUCCEEDED(sq_rawget(vm, -2))) { + sq_pop(vm, 3); + return true; + } + sq_pop(vm, 1); + } + sq_pop(vm, 1); + } + return false; + } + + static inline AbstractStaticClassData*& BaseClass() { + assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists + return getStaticClassData().Lock()->baseClass; + } + + static inline string& ClassName() { + assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists + return getStaticClassData().Lock()->className; + } + + static inline COPYFUNC& CopyFunc() { + assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists + return getStaticClassData().Lock()->copyFunc; + } + + static SQInteger DeleteInstance(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + std::pair::type> >* instance = reinterpret_cast::type> >*>(ptr); + instance->second->erase(instance->first); + delete instance; + return 0; + } + + static void PushInstance(HSQUIRRELVM vm, C* ptr) { + if (!ptr) { + sq_pushnull(vm); + return; + } + + ClassData* cd = getClassData(vm); + + typename unordered_map::type::iterator it = cd->instances->find(ptr); + if (it != cd->instances->end()) { + sq_pushobject(vm, it->second); + return; + } + + sq_pushobject(vm, cd->classObj); + sq_createinstance(vm, -1); + sq_remove(vm, -2); + sq_setinstanceup(vm, -1, new std::pair::type> >(ptr, cd->instances)); + sq_setreleasehook(vm, -1, &DeleteInstance); + sq_getstackobj(vm, -1, &((*cd->instances)[ptr])); + } + + static void PushInstanceCopy(HSQUIRRELVM vm, const C& value) { + sq_pushobject(vm, getClassData(vm)->classObj); + sq_createinstance(vm, -1); + sq_remove(vm, -2); +#ifndef NDEBUG + SQRESULT result = CopyFunc()(vm, -1, &value); + assert(SQ_SUCCEEDED(result)); // fails when trying to copy an object defined as non-copyable +#else + CopyFunc()(vm, -1, &value); +#endif + } + + static C* GetInstance(HSQUIRRELVM vm, SQInteger idx, bool nullAllowed = false) { + AbstractStaticClassData* classType = NULL; + std::pair::type> >* instance = NULL; + if (hasClassData(vm)) /* type checking only done if the value has type data else it may be enum */ + { + if (nullAllowed && sq_gettype(vm, idx) == OT_NULL) { + return NULL; + } + + classType = getStaticClassData().Lock().Get(); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, classType))) { + SQTHROW(vm, FormatTypeError(vm, idx, ClassName())); + return NULL; + } + + if (instance == NULL) { + SQTHROW(vm, _SC("got unconstructed native class (call base.constructor in the constructor of Squirrel classes that extend native classes)")); + return NULL; + } +#else + sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, 0); +#endif + } + else /* value is likely of integral type like enums, cannot return a pointer */ + { + SQTHROW(vm, FormatTypeError(vm, idx, _SC("unknown"))); + return NULL; + } + AbstractStaticClassData* actualType; + sq_gettypetag(vm, idx, (SQUserPointer*)&actualType); + if (actualType == NULL) { + SQInteger top = sq_gettop(vm); + sq_getclass(vm, idx); + while (actualType == NULL) { + sq_getbase(vm, -1); + sq_gettypetag(vm, -1, (SQUserPointer*)&actualType); + } + sq_settop(vm, top); + } + if (classType != actualType) { + return static_cast(actualType->Cast(instance->first, classType)); + } + return static_cast(instance->first); + } +}; + +/// @endcond + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratConst.h b/src/include/scripting/sqrat/sqratConst.h new file mode 100644 index 0000000000..e317d31ad1 --- /dev/null +++ b/src/include/scripting/sqrat/sqratConst.h @@ -0,0 +1,200 @@ +// +// SqratConst: Constant and Enumeration Binding +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_CONST_H_) +#define _SCRAT_CONST_H_ + +#include +#include + +#include "sqratObject.h" + +namespace Sqrat { + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Facilitates exposing a C++ enumeration to Squirrel +/// +/// \remarks +/// The Enumeration class only facilitates binding C++ enumerations that contain only integers, +/// floats, and strings because the Squirrel constant table can only contain these types of +/// values. Other types of enumerations can be bound using Class::SetStaticValue instead. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Enumeration : public Object { +public: + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs the Enumeration object + /// + /// An Enumeration object doesnt do anything on its own. + /// It must be told what constant values it contains. + /// This is done using Enumeration::Const. + /// Then the Enumeration must be exposed to Squirrel. + /// This is done by calling ConstTable::Enum with the Enumeration. + /// + /// \param v Squirrel virtual machine to create the Enumeration for + /// \param createTable Whether the underlying table that values are bound to is created by the constructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Enumeration(HSQUIRRELVM v = DefaultVM::Get(), bool createTable = true) : Object(v, false) { + if(createTable) { + sq_newtable(vm); + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(vm,1); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds an enumeration value + /// + /// \param name Name of the value as it will appear in Squirrel + /// \param val Value to bind + /// + /// \return The Enumeration itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual Enumeration& Const(const SQChar* name, const int val) { + BindValue(name, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds an enumeration value + /// + /// \param name Name of the value as it will appear in Squirrel + /// \param val Value to bind + /// + /// \return The Enumeration itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual Enumeration& Const(const SQChar* name, const float val) { + BindValue(name, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds an enumeration value + /// + /// \param name Name of the value as it will appear in Squirrel + /// \param val Value to bind + /// + /// \return The Enumeration itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual Enumeration& Const(const SQChar* name, const SQChar* val) { + BindValue(name, val, false); + return *this; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Facilitates exposing a C++ constant to Squirrel +/// +/// \remarks +/// The ConstTable class only facilitates binding C++ constants that are integers, +/// floats, and strings because the Squirrel constant table can only contain these types of +/// values. Other types of constants can be bound using Class::SetStaticValue instead. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class ConstTable : public Enumeration { +public: + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a ConstTable object to represent the given VM's const table + /// + /// \param v VM to get the ConstTable for + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ConstTable(HSQUIRRELVM v = DefaultVM::Get()) : Enumeration(v, false) { + sq_pushconsttable(vm); + sq_getstackobj(vm,-1, &obj); + sq_pop(v,1); // No addref needed, since the consttable is always around + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constant value + /// + /// \param name Name of the value as it will appear in Squirrel + /// \param val Value to bind + /// + /// \return The ConstTable itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual ConstTable& Const(const SQChar* name, const int val) { + Enumeration::Const(name, val); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constant value + /// + /// \param name Name of the value as it will appear in Squirrel + /// \param val Value to bind + /// + /// \return The ConstTable itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual ConstTable& Const(const SQChar* name, const float val) { + Enumeration::Const(name, val); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a constant value + /// + /// \param name Name of the value as it will appear in Squirrel + /// \param val Value to bind + /// + /// \return The ConstTable itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual ConstTable& Const(const SQChar* name, const SQChar* val) { + Enumeration::Const(name, val); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds an Enumeration to the ConstTable + /// + /// \param name Name of the enumeration as it will appear in Squirrel + /// \param en Enumeration to bind + /// + /// \return The ConstTable itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ConstTable& Enum(const SQChar* name, Enumeration& en) { + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); + sq_pushobject(vm, en.GetObject()); + sq_newslot(vm, -3, false); + sq_pop(vm,1); // pop table + return *this; + } +}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratFunction.h b/src/include/scripting/sqrat/sqratFunction.h new file mode 100644 index 0000000000..55385de4cd --- /dev/null +++ b/src/include/scripting/sqrat/sqratFunction.h @@ -0,0 +1,2673 @@ +// +// sqratFunction: Squirrel Function Wrapper +// + +// +// Copyright (c) 2009 Brandon Jones +// Copyirght 2011 Li-Cheng (Andy) Tai +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_SQFUNC_H_) +#define _SCRAT_SQFUNC_H_ + +#include +#include "sqratObject.h" + +namespace Sqrat { + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Represents a function in Squirrel +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Function { + + friend class TableBase; + friend class Table; + friend class ArrayBase; + friend struct Var; + +private: + + HSQUIRRELVM vm; + HSQOBJECT env, obj; + +public: + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor (null) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function() { + sq_resetobject(&env); + sq_resetobject(&obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param sf Function to copy + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function(const Function& sf) : vm(sf.vm), env(sf.env), obj(sf.obj) { + sq_addref(vm, &env); + sq_addref(vm, &obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a Function from a slot in an Object + /// + /// \param e Object that potentially contains a Squirrel function in a slot + /// \param slot Name of the slot to look for the Squirrel function in + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function(const Object& e, const SQChar* slot) : vm(e.GetVM()), env(e.GetObject()) { + sq_addref(vm, &env); + Object so = e.GetSlot(slot); + obj = so.GetObject(); + sq_addref(vm, &obj); +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQObjectType value_type = so.GetType(); + if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE && value_type != OT_CLASS) { + // Note that classes can also be considered functions in Squirrel + SQTHROW(vm, _SC("function not found in slot")); + } +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a Function from two Squirrel objects (one is the environment object and the other is the function object) + /// + /// \param v VM that the function will exist in + /// \param e Squirrel object that should represent the environment of the function + /// \param o Squirrel object that should already represent a Squirrel function + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function(HSQUIRRELVM v, HSQOBJECT e, HSQOBJECT o) : vm(v), env(e), obj(o) { + sq_addref(vm, &env); + sq_addref(vm, &obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~Function() { + Release(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assignment operator + /// + /// \param sf Function to copy + /// + /// \return The Function itself + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function& operator=(const Function& sf) { + Release(); + vm = sf.vm; + env = sf.env; + obj = sf.obj; + sq_addref(vm, &env); + sq_addref(vm, &obj); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Checks whether the Function is null + /// + /// \return True if the Function currently has a null value, otherwise false + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool IsNull() { + return sq_isnull(obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel environment object for this Function (copy) + /// + /// \return Squirrel object representing the Function environment + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQOBJECT GetEnv() const { + return env; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel environment object for this Function (reference) + /// + /// \return Squirrel object representing the Function environment + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQOBJECT& GetEnv() { + return env; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel function object for this Function (copy) + /// + /// \return Squirrel object representing the Function + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQOBJECT GetFunc() const { + return obj; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel function object for this Function (reference) + /// + /// \return Squirrel object representing the Function + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQOBJECT& GetFunc() { + return obj; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel VM for this Function (copy) + /// + /// \return Squirrel VM associated with the Function + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQUIRRELVM GetVM() const { + return vm; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel VM for this Function (reference) + /// + /// \return Squirrel VM associated with the Function + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQUIRRELVM& GetVM() { + return vm; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets the Function to null (removing its references to underlying Squirrel objects) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Release() { + if(!IsNull()) { + sq_release(vm, &env); + sq_release(vm, &obj); + sq_resetobject(&env); + sq_resetobject(&obj); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate() { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 1)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } + + SQRESULT result = sq_call(vm, 1, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 1, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 2)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 2, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 2, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 3)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 3, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 3, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 4)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 4, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 4, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 5)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 5, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 5, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 6)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 6, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 6, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 7)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 7, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 7, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 8)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 8, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 8, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 9)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 9, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 9, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 10)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 10, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 10, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 11)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 11, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 11, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 12)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 12, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 12, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 13)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + PushVar(vm, a12); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 13, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 13, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// \param a13 Argument 13 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A13 Type of argument 13 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 14)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + PushVar(vm, a12); + PushVar(vm, a13); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 14, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 14, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function and returns its value as a SharedPtr + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// \param a13 Argument 13 of the Function + /// \param a14 Argument 14 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A13 Type of argument 13 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A14 Type of argument 14 of the Function (usually doesnt need to be defined explicitly) + /// \tparam R Type of return value (fails if return value is not of this type) + /// + /// \return SharedPtr containing the return value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr Evaluate(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 15)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return SharedPtr(); + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + PushVar(vm, a12); + PushVar(vm, a13); + PushVar(vm, a14); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 15, true, ErrorHandling::IsEnabled()); + + //handle an error: pop the stack and throw the exception + if (SQ_FAILED(result)) { + sq_settop(vm, top); + SQTHROW(vm, LastErrorString(vm)); + return SharedPtr(); + } +#else + sq_call(vm, 15, true, ErrorHandling::IsEnabled()); +#endif + + SharedPtr ret = Var >(vm, -1).value; + sq_settop(vm, top); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Execute() { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 1)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } + + SQRESULT result = sq_call(vm, 1, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 1, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 2)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 2, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 2, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 3)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 3, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 3, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 4)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 4, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 4, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 5)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 5, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 5, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 6)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 6, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 6, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 7)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 7, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 7, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 8)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 8, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 8, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 9)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 9, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 9, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 10)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 10, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 10, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 11)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 11, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 11, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 12)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 12, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 12, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 13)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + PushVar(vm, a12); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 13, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 13, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// \param a13 Argument 13 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A13 Type of argument 13 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 14)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + PushVar(vm, a12); + PushVar(vm, a13); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 14, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 14, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// \param a13 Argument 13 of the Function + /// \param a14 Argument 14 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A13 Type of argument 13 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A14 Type of argument 14 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Execute(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14) { + SQInteger top = sq_gettop(vm); + + sq_pushobject(vm, obj); + sq_pushobject(vm, env); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQUnsignedInteger nparams; + SQUnsignedInteger nfreevars; + if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != 15)) { + sq_pop(vm, 2); + SQTHROW(vm, _SC("wrong number of parameters")); + return; + } +#endif + + PushVar(vm, a1); + PushVar(vm, a2); + PushVar(vm, a3); + PushVar(vm, a4); + PushVar(vm, a5); + PushVar(vm, a6); + PushVar(vm, a7); + PushVar(vm, a8); + PushVar(vm, a9); + PushVar(vm, a10); + PushVar(vm, a11); + PushVar(vm, a12); + PushVar(vm, a13); + PushVar(vm, a14); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 15, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); + + //handle an error: throw the exception + if (SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_call(vm, 15, false, ErrorHandling::IsEnabled()); + sq_settop(vm, top); +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void operator()() { + Execute(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1) { + Execute(a1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2) { + Execute(a1, a2); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3) { + Execute(a1, a2, a3); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4) { + Execute(a1, a2, a3, a4); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + Execute(a1, a2, a3, a4, a5); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { + Execute(a1, a2, a3, a4, a5, a6); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { + Execute(a1, a2, a3, a4, a5, a6, a7); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { + Execute(a1, a2, a3, a4, a5, a6, a7, a8); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { + Execute(a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { + Execute(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { + Execute(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { + Execute(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// \param a13 Argument 13 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A13 Type of argument 13 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { + Execute(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the Function + /// + /// \param a1 Argument 1 of the Function + /// \param a2 Argument 2 of the Function + /// \param a3 Argument 3 of the Function + /// \param a4 Argument 4 of the Function + /// \param a5 Argument 5 of the Function + /// \param a6 Argument 6 of the Function + /// \param a7 Argument 7 of the Function + /// \param a8 Argument 8 of the Function + /// \param a9 Argument 9 of the Function + /// \param a10 Argument 10 of the Function + /// \param a11 Argument 11 of the Function + /// \param a12 Argument 12 of the Function + /// \param a13 Argument 13 of the Function + /// \param a14 Argument 14 of the Function + /// + /// \tparam A1 Type of argument 1 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A2 Type of argument 2 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A3 Type of argument 3 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A4 Type of argument 4 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A5 Type of argument 5 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A6 Type of argument 6 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A7 Type of argument 7 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A8 Type of argument 8 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A9 Type of argument 9 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A10 Type of argument 10 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A11 Type of argument 11 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A12 Type of argument 12 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A13 Type of argument 13 of the Function (usually doesnt need to be defined explicitly) + /// \tparam A14 Type of argument 14 of the Function (usually doesnt need to be defined explicitly) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, A14 a14) { + Execute(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Function instances to and from the stack as references (functions are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + Function value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a Function + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// Assumes the Function environment is at index 1. + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + HSQOBJECT sqEnv; + HSQOBJECT sqValue; + sq_getstackobj(vm, 1, &sqEnv); + sq_getstackobj(vm, idx, &sqValue); + value = Function(vm, sqEnv, sqValue); +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQObjectType value_type = sq_gettype(vm, idx); + if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) { + SQTHROW(vm, FormatTypeError(vm, idx, _SC("closure"))); + } +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a Function on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const Function& value) { + sq_pushobject(vm, value.GetFunc()); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Function instances to and from the stack as references (functions are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var {Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {}}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Function instances to and from the stack as references (functions are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var {Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {}}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratGlobalMethods.h b/src/include/scripting/sqrat/sqratGlobalMethods.h new file mode 100644 index 0000000000..41b5dc665c --- /dev/null +++ b/src/include/scripting/sqrat/sqratGlobalMethods.h @@ -0,0 +1,2382 @@ +// +// SqratGlobalMethods: Global Methods +// + +// +// Copyright (c) 2009 Brandon Jones +// Copyirght 2011 Li-Cheng (Andy) Tai +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_GLOBAL_METHODS_H_) +#define _SCRAT_GLOBAL_METHODS_H_ + +#include +#include "sqratTypes.h" + +namespace Sqrat { + +/// @cond DEV + +// +// Squirrel Global Functions +// +template +class SqGlobal { +public: + + // Arg Count 0 + template + static SQInteger Func0(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + R ret = (*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 1 + template + static SQInteger Func1(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 1) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 2 + template + static SQInteger Func2(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 3 + template + static SQInteger Func3(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 4 + template + static SQInteger Func4(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 5 + template + static SQInteger Func5(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 6 + template + static SQInteger Func6(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 7 + template + static SQInteger Func7(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 8 + template + static SQInteger Func8(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7, A8); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 9 + template + static SQInteger Func9(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 10 + template + static SQInteger Func10(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 11 + template + static SQInteger Func11(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 12 + template + static SQInteger Func12(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 13 + template + static SQInteger Func13(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + Var a13(vm, startIdx + 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 14 + template + static SQInteger Func14(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + Var a13(vm, startIdx + 12); + Var a14(vm, startIdx + 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } +}; + + +// +// reference return specialization +// + +template +class SqGlobal { +public: + + // Arg Count 0 + template + static SQInteger Func0(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + R& ret = (*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 1 + template + static SQInteger Func1(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 1) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 2 + template + static SQInteger Func2(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 3 + template + static SQInteger Func3(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 4 + template + static SQInteger Func4(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 5 + template + static SQInteger Func5(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 6 + template + static SQInteger Func6(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 7 + template + static SQInteger Func7(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 8 + template + static SQInteger Func8(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7, A8); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 9 + template + static SQInteger Func9(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 10 + template + static SQInteger Func10(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 11 + template + static SQInteger Func11(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 12 + template + static SQInteger Func12(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 13 + template + static SQInteger Func13(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + Var a13(vm, startIdx + 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 14 + template + static SQInteger Func14(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R& (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + Var a13(vm, startIdx + 12); + Var a14(vm, startIdx + 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } +}; + + +// +// void return specialization +// + +template <> +class SqGlobal { +public: + + // Arg Count 0 + template + static SQInteger Func0(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + (*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 1 + template + static SQInteger Func1(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 1) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 2 + template + static SQInteger Func2(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 3 + template + static SQInteger Func3(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 4 + template + static SQInteger Func4(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 5 + template + static SQInteger Func5(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 6 + template + static SQInteger Func6(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 7 + template + static SQInteger Func7(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 8 + template + static SQInteger Func8(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7, A8); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 9 + template + static SQInteger Func9(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 10 + template + static SQInteger Func10(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 11 + template + static SQInteger Func11(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 12 + template + static SQInteger Func12(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 13 + template + static SQInteger Func13(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + Var a13(vm, startIdx + 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 14 + template + static SQInteger Func14(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != startIdx + 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef void (*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14); + M* method; + sq_getuserdata(vm, -1, (SQUserPointer*)&method, NULL); + + SQTRY() + Var a1(vm, startIdx); + Var a2(vm, startIdx + 1); + Var a3(vm, startIdx + 2); + Var a4(vm, startIdx + 3); + Var a5(vm, startIdx + 4); + Var a6(vm, startIdx + 5); + Var a7(vm, startIdx + 6); + Var a8(vm, startIdx + 7); + Var a9(vm, startIdx + 8); + Var a10(vm, startIdx + 9); + Var a11(vm, startIdx + 10); + Var a12(vm, startIdx + 11); + Var a13(vm, startIdx + 12); + Var a14(vm, startIdx + 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } +}; + + +// +// Global Function Resolvers +// + +// Arg Count 0 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)()) { + return &SqGlobal::template Func0; +} + +// Arg Count 0 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)()) { + return &SqGlobal::template Func0; +} + +// Arg Count 1 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +// Arg Count 1 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +// Arg Count 2 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +// Arg Count 2 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +// Arg Count 3 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +// Arg Count 3 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +// Arg Count 4 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +// Arg Count 4 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +// Arg Count 5 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +// Arg Count 5 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +// Arg Count 6 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +// Arg Count 6 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +// Arg Count 7 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +// Arg Count 7 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +// Arg Count 8 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +// Arg Count 8 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +// Arg Count 9 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +// Arg Count 9 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +// Arg Count 10 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +// Arg Count 10 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +// Arg Count 11 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +// Arg Count 11 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +// Arg Count 12 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +// Arg Count 12 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +// Arg Count 13 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +// Arg Count 13 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +// Arg Count 14 +template +SQFUNCTION SqGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} + +// Arg Count 14 +template +SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} + + +// +// Member Global Function Resolvers +// + +// Arg Count 1 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +// Arg Count 1 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +// Arg Count 2 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +// Arg Count 2 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +// Arg Count 3 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +// Arg Count 3 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +// Arg Count 4 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +// Arg Count 4 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +// Arg Count 5 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +// Arg Count 5 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +// Arg Count 6 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +// Arg Count 6 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +// Arg Count 7 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +// Arg Count 7 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +// Arg Count 8 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +// Arg Count 8 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +// Arg Count 9 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +// Arg Count 9 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +// Arg Count 10 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +// Arg Count 10 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +// Arg Count 11 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +// Arg Count 11 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +// Arg Count 12 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +// Arg Count 12 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +// Arg Count 13 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +// Arg Count 13 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +// Arg Count 14 +template +SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} + +// Arg Count 14 +template +SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} + +/// @endcond + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratMemberMethods.h b/src/include/scripting/sqrat/sqratMemberMethods.h new file mode 100644 index 0000000000..503401040c --- /dev/null +++ b/src/include/scripting/sqrat/sqratMemberMethods.h @@ -0,0 +1,5597 @@ +// +// SqratMemberMethods: Member Methods +// + +// +// Copyright (c) 2009 Brandon Jones +// Copyright 2011 Li-Cheng (Andy) Tai +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_MEMBER_METHODS_H_) +#define _SCRAT_MEMBER_METHODS_H_ + +#include +#include "sqratTypes.h" + +namespace Sqrat { + +/// @cond DEV + +// +// Squirrel Global Functions +// + +template +class SqMember { +public: + + // Arg Count 0 + template + static SQInteger Func0(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + + typedef R (C::*M)(); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + R ret = (ptr->*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func0C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)() const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + R ret = (ptr->*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 1 + template + static SQInteger Func1(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func1C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 2 + template + static SQInteger Func2(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func2C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 3 + template + static SQInteger Func3(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func3C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 4 + template + static SQInteger Func4(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func4C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 5 + template + static SQInteger Func5(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func5C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 6 + template + static SQInteger Func6(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func6C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 7 + template + static SQInteger Func7(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func7C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 8 + template + static SQInteger Func8(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func8C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 9 + template + static SQInteger Func9(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func9C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + + // Arg Count 10 + template + static SQInteger Func10(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func10C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + + // Arg Count 11 + template + static SQInteger Func11(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func11C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + + // Arg Count 12 + template + static SQInteger Func12(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func12C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 13 + template + static SQInteger Func13(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 15) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func13C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 15) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 14 + template + static SQInteger Func14(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 16) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + Var a14(vm, 15); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func14C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 16) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + Var a14(vm, 15); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVar(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } +}; + + +// +// reference return specialization +// + +template +class SqMember { +public: + + // Arg Count 0 + template + static SQInteger Func0(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + R& ret = (ptr->*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func0C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)() const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + R& ret = (ptr->*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 1 + template + static SQInteger Func1(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func1C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 2 + template + static SQInteger Func2(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func2C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 3 + template + static SQInteger Func3(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func3C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 4 + template + static SQInteger Func4(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func4C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 5 + template + static SQInteger Func5(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func5C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 6 + template + static SQInteger Func6(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func6C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 7 + template + static SQInteger Func7(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func7C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 8 + template + static SQInteger Func8(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func8C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 9 + template + static SQInteger Func9(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func9C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + + // Arg Count 10 + template + static SQInteger Func10(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func10C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + + // Arg Count 11 + template + static SQInteger Func11(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func11C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + + // Arg Count 12 + template + static SQInteger Func12(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func12C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 13 + template + static SQInteger Func13(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 15) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R&(C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func13C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 15) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + // Arg Count 14 + template + static SQInteger Func14(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 16) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + Var a14(vm, 15); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + + template + static SQInteger Func14C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 16) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef R& (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + Var a14(vm, 15); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + R& ret = (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + PushVarR(vm, ret); + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 1; + } + +}; + + +// +// void return specialization +// + +template +class SqMember { +public: + + // Arg Count 0 + template + static SQInteger Func0(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + (ptr->*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func0C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 2) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)() const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + (ptr->*method)(); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 1 + template + static SQInteger Func1(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func1C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 3) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 2 + template + static SQInteger Func2(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func2C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 4) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 3 + template + static SQInteger Func3(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func3C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 5) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 4 + template + static SQInteger Func4(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func4C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 6) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 5 + template + static SQInteger Func5(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func5C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 7) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 6 + template + static SQInteger Func6(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func6C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 8) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 7 + template + static SQInteger Func7(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func7C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 9) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 8 + template + static SQInteger Func8(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func8C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 10) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 9 + template + static SQInteger Func9(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func9C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 11) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 10 + template + static SQInteger Func10(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func10C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 12) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 11 + template + static SQInteger Func11(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func11C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 13) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 12 + template + static SQInteger Func12(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func12C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 14) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 13 + template + static SQInteger Func13(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 15) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func13C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 15) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + // Arg Count 14 + template + static SQInteger Func14(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 16) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14); + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + Var a14(vm, 15); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + + template + static SQInteger Func14C(HSQUIRRELVM vm) { + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (!SQRAT_CONST_CONDITION(overloaded) && sq_gettop(vm) != 16) { + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#endif + typedef void (C::*M)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const; + M* methodPtr; + sq_getuserdata(vm, -1, (SQUserPointer*)&methodPtr, NULL); + M method = *methodPtr; + + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + assert(0); // may fail because C is not a type bound in the VM + return sq_throwerror(vm, SQWHAT(vm)); + } + + SQTRY() + Var a1(vm, 2); + Var a2(vm, 3); + Var a3(vm, 4); + Var a4(vm, 5); + Var a5(vm, 6); + Var a6(vm, 7); + Var a7(vm, 8); + Var a8(vm, 9); + Var a9(vm, 10); + Var a10(vm, 11); + Var a11(vm, 12); + Var a12(vm, 13); + Var a13(vm, 14); + Var a14(vm, 15); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + (ptr->*method)( + a1.value, + a2.value, + a3.value, + a4.value, + a5.value, + a6.value, + a7.value, + a8.value, + a9.value, + a10.value, + a11.value, + a12.value, + a13.value, + a14.value + ); + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + return 0; + } + +}; + + +// +// Member Function Resolvers +// + +// Arg Count 0 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)()) { + return &SqMember::template Func0; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)() const) { + return &SqMember::template Func0C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)()) { + return &SqMember::template Func0; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)() const) { + return &SqMember::template Func0C; +} + +// Arg Count 1 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1)) { + return &SqMember::template Func1; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1) const) { + return &SqMember::template Func1C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1)) { + return &SqMember::template Func1; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1) const) { + return &SqMember::template Func1C; +} + +// Arg Count 2 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2)) { + return &SqMember::template Func2; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2) const) { + return &SqMember::template Func2C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2)) { + return &SqMember::template Func2; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2) const) { + return &SqMember::template Func2C; +} + +// Arg Count 3 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3)) { + return &SqMember::template Func3; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3) const) { + return &SqMember::template Func3C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3)) { + return &SqMember::template Func3; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3) const) { + return &SqMember::template Func3C; +} + +// Arg Count 4 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4)) { + return &SqMember::template Func4; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4) const) { + return &SqMember::template Func4C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4)) { + return &SqMember::template Func4; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4) const) { + return &SqMember::template Func4C; +} + +// Arg Count 5 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqMember::template Func5; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5) const) { + return &SqMember::template Func5C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqMember::template Func5; +} + +template +inline SQFUNCTION SqMemberFunc(R&(C::* /*method*/)(A1, A2, A3, A4, A5) const) { + return &SqMember::template Func5C; +} + +// Arg Count 6 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqMember::template Func6; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6) const) { + return &SqMember::template Func6C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqMember::template Func6; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6) const) { + return &SqMember::template Func6C; +} + +// Arg Count 7 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqMember::template Func7; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7) const) { + return &SqMember::template Func7C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqMember::template Func7; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7) const) { + return &SqMember::template Func7C; +} + +// Arg Count 8 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqMember::template Func8; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8) const) { + return &SqMember::template Func8C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqMember::template Func8; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8) const) { + return &SqMember::template Func8C; +} + +// Arg Count 9 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqMember::template Func9; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { + return &SqMember::template Func9C; +} + +template +inline SQFUNCTION SqMemberFunc(R&(C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqMember::template Func9; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { + return &SqMember::template Func9C; +} + +// Arg Count 10 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqMember::template Func10; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { + return &SqMember::template Func10C; +} +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqMember::template Func10; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { + return &SqMember::template Func10C; +} + +// Arg Count 11 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqMember::template Func11; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const) { + return &SqMember::template Func11C; +} +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqMember::template Func11; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const) { + return &SqMember::template Func11C; +} + +// Arg Count 12 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqMember::template Func12; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const) { + return &SqMember::template Func12C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqMember::template Func12; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const) { + return &SqMember::template Func12C; +} + +// Arg Count 13 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqMember::template Func13; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const) { + return &SqMember::template Func13C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqMember::template Func13; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const) { + return &SqMember::template Func13C; +} + +// Arg Count 14 +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqMember::template Func14; +} + +template +inline SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const) { + return &SqMember::template Func14C; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqMember::template Func14; +} + +template +inline SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const) { + return &SqMember::template Func14C; +} + + +// +// Variable Get +// + +template +inline SQInteger sqDefaultGet(HSQUIRRELVM vm) { + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + + typedef V C::*M; + M* memberPtr = NULL; + sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, NULL); // Get Member... + M member = *memberPtr; + + PushVarR(vm, ptr->*member); + + return 1; +} + +template +inline SQInteger sqStaticGet(HSQUIRRELVM vm) { + typedef V *M; + M* memberPtr = NULL; + sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, NULL); // Get Member... + M member = *memberPtr; + + PushVarR(vm, *member); + + return 1; +} + +inline SQInteger sqVarGet(HSQUIRRELVM vm) { + // Find the get method in the get table + sq_push(vm, 2); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_rawget(vm, -2))) { +#if (SQUIRREL_VERSION_NUMBER>= 200) && (SQUIRREL_VERSION_NUMBER < 300) // Squirrel 2.x + return sq_throwerror(vm, _SC("member variable not found")); +#else // Squirrel 3.x + sq_pushnull(vm); + return sq_throwobject(vm); +#endif + } +#else + sq_rawget(vm, -2); +#endif + + // push 'this' + sq_push(vm, 1); + + // Call the getter +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 1, true, ErrorHandling::IsEnabled()); + if (SQ_FAILED(result)) { + return sq_throwerror(vm, LastErrorString(vm).c_str()); + } +#else + sq_call(vm, 1, true, ErrorHandling::IsEnabled()); +#endif + + return 1; +} + + +// +// Variable Set +// + +template +inline SQInteger sqDefaultSet(HSQUIRRELVM vm) { + C* ptr; + SQTRY() + ptr = Var(vm, 1).value; + SQCATCH_NOEXCEPT(vm) { + SQCLEAR(vm); // clear the previous error + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + + typedef V C::*M; + M* memberPtr = NULL; + sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, NULL); // Get Member... + M member = *memberPtr; + + SQTRY() + if (is_pointer::value || is_reference::value) { + ptr->*member = Var(vm, 2).value; + } else { + ptr->*member = Var(vm, 2).value; + } + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + + return 0; +} + +template +inline SQInteger sqStaticSet(HSQUIRRELVM vm) { + typedef V *M; + M* memberPtr = NULL; + sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, NULL); // Get Member... + M member = *memberPtr; + + SQTRY() + if (is_pointer::value || is_reference::value) { + *member = Var(vm, 2).value; + } else { + *member = Var(vm, 2).value; + } + SQCATCH_NOEXCEPT(vm) { + return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); + } + SQCATCH(vm) { + return sq_throwerror(vm, SQWHAT(vm)); + } + + return 0; +} + +inline SQInteger sqVarSet(HSQUIRRELVM vm) { + // Find the set method in the set table + sq_push(vm, 2); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_rawget(vm, -2))) { +#if (SQUIRREL_VERSION_NUMBER>= 200) && (SQUIRREL_VERSION_NUMBER < 300) // Squirrel 2.x + return sq_throwerror(vm, _SC("member variable not found")); +#else // Squirrel 3.x + sq_pushnull(vm); + return sq_throwobject(vm); +#endif + } +#else + sq_rawget(vm, -2); +#endif + + // push 'this' + sq_push(vm, 1); + sq_push(vm, 3); + + // Call the setter +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, 2, false, ErrorHandling::IsEnabled()); + if (SQ_FAILED(result)) { + return sq_throwerror(vm, LastErrorString(vm).c_str()); + } +#else + sq_call(vm, 2, false, ErrorHandling::IsEnabled()); +#endif + + return 0; +} + +/// @endcond + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratObject.h b/src/include/scripting/sqrat/sqratObject.h new file mode 100644 index 0000000000..b8e6d2c239 --- /dev/null +++ b/src/include/scripting/sqrat/sqratObject.h @@ -0,0 +1,557 @@ +// +// SqratObject: Referenced Squirrel Object Wrapper +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_OBJECT_H_) +#define _SCRAT_OBJECT_H_ + +#include +#include + +#include "sqratAllocator.h" +#include "sqratTypes.h" +#include "sqratOverloadMethods.h" +#include "sqratUtil.h" + +namespace Sqrat { + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// The base class for classes that represent Squirrel objects +/// +/// \remarks +/// All Object and derived classes MUST be destroyed before calling sq_close or your application will crash when exiting. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Object { +protected: + +/// @cond DEV + HSQUIRRELVM vm; + HSQOBJECT obj; + bool release; + + Object(HSQUIRRELVM v, bool releaseOnDestroy = true) : vm(v), release(releaseOnDestroy) { + sq_resetobject(&obj); + } +/// @endcond + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor (null) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Object() : vm(0), release(true) { + sq_resetobject(&obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param so Object to copy + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Object(const Object& so) : vm(so.vm), obj(so.obj), release(so.release) { + sq_addref(vm, &obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs an Object from a Squirrel object + /// + /// \param o Squirrel object + /// \param v VM that the object will exist in + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Object(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : vm(v), obj(o), release(true) { + sq_addref(vm, &obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs an Object from a C++ instance + /// + /// \param instance Pointer to a C++ class instance that has been bound already + /// \param v VM that the object will exist in + /// + /// \tparam T Type of instance + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + Object(T* instance, HSQUIRRELVM v = DefaultVM::Get()) : vm(v), release(true) { + ClassType::PushInstance(vm, instance); + sq_getstackobj(vm, -1, &obj); + sq_addref(vm, &obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual ~Object() { + if(release) { + Release(); + release = false; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assignment operator + /// + /// \param so Object to copy + /// + /// \return The Object itself + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Object& operator=(const Object& so) { + if(release) { + Release(); + } + vm = so.vm; + obj = so.obj; + release = so.release; + sq_addref(vm, &GetObject()); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel VM for this Object (reference) + /// + /// \return Squirrel VM associated with the Object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQUIRRELVM& GetVM() { + return vm; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel VM for this Object (copy) + /// + /// \return Squirrel VM associated with the Object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQUIRRELVM GetVM() const { + return vm; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the type of the Object as defined by the Squirrel API + /// + /// \return SQObjectType for the Object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SQObjectType GetType() const { + return GetObject()._type; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Checks whether the Object is null + /// + /// \return True if the Object currently has a null value, otherwise false + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool IsNull() const { + return sq_isnull(GetObject()); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel object for this Object (copy) + /// + /// \return Squirrel object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual HSQOBJECT GetObject() const { + return obj; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel object for this Object (reference) + /// + /// \return Squirrel object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual HSQOBJECT& GetObject() { + return obj; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Allows the Object to be inputted directly into places that expect a HSQOBJECT + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + operator HSQOBJECT&() { + return GetObject(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets the Object to null (removing its references to underlying Squirrel objects) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Release() { + sq_release(vm, &obj); + sq_resetobject(&obj); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value of a slot from the object + /// + /// \param slot Name of the slot + /// + /// \return An Object representing the value of the slot (can be a null object if nothing was found) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Object GetSlot(const SQChar* slot) const { + HSQOBJECT slotObj; + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, slot, -1); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + return Object(vm); // Return a NULL object + } else { + sq_getstackobj(vm, -1, &slotObj); + Object ret(slotObj, vm); // must addref before the pop! + sq_pop(vm, 2); + return ret; + } +#else + sq_get(vm, -2); + sq_getstackobj(vm, -1, &slotObj); + Object ret(slotObj, vm); // must addref before the pop! + sq_pop(vm, 2); + return ret; +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value of an index from the object + /// + /// \param index Index of the slot + /// + /// \return An Object representing the value of the slot (can be a null object if nothing was found) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Object GetSlot(SQInteger index) const { + HSQOBJECT slotObj; + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + return Object(vm); // Return a NULL object + } else { + sq_getstackobj(vm, -1, &slotObj); + Object ret(slotObj, vm); // must addref before the pop! + sq_pop(vm, 2); + return ret; + } +#else + sq_get(vm, -2); + sq_getstackobj(vm, -1, &slotObj); + Object ret(slotObj, vm); // must addref before the pop! + sq_pop(vm, 2); + return ret; +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Casts the object to a certain C++ type + /// + /// \tparam T Type to cast to + /// + /// \return A copy of the value of the Object with the given type + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + T Cast() const { + sq_pushobject(vm, GetObject()); + T ret = Var(vm, -1).value; + sq_pop(vm, 1); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Allows Object to be used like C++ arrays with the [] operator + /// + /// \param slot The slot key + /// + /// \tparam T Type of the slot key (usually doesnt need to be defined explicitly) + /// + /// \return An Object representing the value of the slot (can be a null object if nothing was found) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + inline Object operator[](T slot) + { + return GetSlot(slot); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns the size of the Object + /// + /// \return Size of Object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SQInteger GetSize() const { + sq_pushobject(vm, GetObject()); + SQInteger ret = sq_getsize(vm, -1); + sq_pop(vm, 1); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Iterator for going over the slots in the object using Object::Next + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + struct iterator + { + /// @cond DEV + friend class Object; + /// @endcond + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor (null) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + iterator() + { + Index = 0; + sq_resetobject(&Key); + sq_resetobject(&Value); + Key._type = OT_NULL; + Value._type = OT_NULL; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns the string value of the key the iterator is on if possible + /// + /// \return String or NULL + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const SQChar* getName() { return sq_objtostring(&Key); } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel object for the key the iterator is on + /// + /// \return HSQOBJECT representing a key + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQOBJECT getKey() { return Key; } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the Squirrel object for the value the iterator is on + /// + /// \return HSQOBJECT representing a value + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQOBJECT getValue() { return Value; } + private: + + HSQOBJECT Key; + HSQOBJECT Value; + SQInteger Index; + }; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Used to go through all the slots in an Object (same limitations as sq_next) + /// + /// \param iter An iterator being used for going through the slots + /// + /// \return Whether there is a next slot + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Next(iterator& iter) const + { + sq_pushobject(vm,obj); + sq_pushinteger(vm,iter.Index); + if(SQ_SUCCEEDED(sq_next(vm,-2))) + { + sq_getstackobj(vm,-1,&iter.Value); + sq_getstackobj(vm,-2,&iter.Key); + sq_getinteger(vm,-3,&iter.Index); + sq_pop(vm,4); + return true; + } + else + { + sq_pop(vm,2); + return false; + } + } + +protected: +/// @cond DEV + + // Bind a function and it's associated Squirrel closure to the object + inline void BindFunc(const SQChar* name, void* method, size_t methodSize, SQFUNCTION func, bool staticVar = false) { + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); + + SQUserPointer methodPtr = sq_newuserdata(vm, static_cast(methodSize)); + memcpy(methodPtr, method, methodSize); + + sq_newclosure(vm, func, 1); + sq_newslot(vm, -3, staticVar); + sq_pop(vm,1); // pop table + } + + inline void BindFunc(const SQInteger index, void* method, size_t methodSize, SQFUNCTION func, bool staticVar = false) { + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); + + SQUserPointer methodPtr = sq_newuserdata(vm, static_cast(methodSize)); + memcpy(methodPtr, method, methodSize); + + sq_newclosure(vm, func, 1); + sq_newslot(vm, -3, staticVar); + sq_pop(vm,1); // pop table + } + + + // Bind a function and it's associated Squirrel closure to the object + inline void BindOverload(const SQChar* name, void* method, size_t methodSize, SQFUNCTION func, SQFUNCTION overload, int argCount, bool staticVar = false) { + string overloadName = SqOverloadName::Get(name, argCount); + + sq_pushobject(vm, GetObject()); + + // Bind overload handler + sq_pushstring(vm, name, -1); + sq_pushstring(vm, name, -1); // function name is passed as a free variable + sq_newclosure(vm, overload, 1); + sq_newslot(vm, -3, staticVar); + + // Bind overloaded function + sq_pushstring(vm, overloadName.c_str(), -1); + SQUserPointer methodPtr = sq_newuserdata(vm, static_cast(methodSize)); + memcpy(methodPtr, method, methodSize); + sq_newclosure(vm, func, 1); + sq_newslot(vm, -3, staticVar); + + sq_pop(vm,1); // pop table + } + + // Set the value of a variable on the object. Changes to values set this way are not reciprocated + template + inline void BindValue(const SQChar* name, const V& val, bool staticVar = false) { + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); + PushVar(vm, val); + sq_newslot(vm, -3, staticVar); + sq_pop(vm,1); // pop table + } + template + inline void BindValue(const SQInteger index, const V& val, bool staticVar = false) { + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); + PushVar(vm, val); + sq_newslot(vm, -3, staticVar); + sq_pop(vm,1); // pop table + } + + // Set the value of an instance on the object. Changes to values set this way are reciprocated back to the source instance + template + inline void BindInstance(const SQChar* name, V* val, bool staticVar = false) { + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); + PushVar(vm, val); + sq_newslot(vm, -3, staticVar); + sq_pop(vm,1); // pop table + } + template + inline void BindInstance(const SQInteger index, V* val, bool staticVar = false) { + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); + PushVar(vm, val); + sq_newslot(vm, -3, staticVar); + sq_pop(vm,1); // pop table + } + +/// @endcond +}; + +/// @cond DEV +template<> +inline void Object::BindValue(const SQChar* name, const int & val, bool staticVar /* = false */) { + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); + PushVar(vm, val); + sq_newslot(vm, -3, staticVar); + sq_pop(vm,1); // pop table +} +/// @endcond + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Object instances to and from the stack as references (Object is always a reference) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + Object value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as an Object + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + HSQOBJECT sqValue; + sq_getstackobj(vm, idx, &sqValue); + value = Object(sqValue, vm); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put an Object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const Object& value) { + sq_pushobject(vm, value.GetObject()); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Object instances to and from the stack as references (Object is always a reference) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var {Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {}}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Object instances to and from the stack as references (Object is always a reference) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var {Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {}}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratOverloadMethods.h b/src/include/scripting/sqrat/sqratOverloadMethods.h new file mode 100644 index 0000000000..1733082a82 --- /dev/null +++ b/src/include/scripting/sqrat/sqratOverloadMethods.h @@ -0,0 +1,1175 @@ +// +// SqratOverloadMethods: Overload Methods +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SQRAT_OVERLOAD_METHODS_H_) +#define _SQRAT_OVERLOAD_METHODS_H_ + +#include +#include +#include +#include "sqratTypes.h" +#include "sqratUtil.h" +#include "sqratGlobalMethods.h" +#include "sqratMemberMethods.h" + +namespace Sqrat { + +/// @cond DEV + +// +// Overload name generator +// + +class SqOverloadName { +public: + + static string Get(const SQChar* name, int args) { + std::basic_stringstream overloadName; + overloadName << _SC("__overload_") << name << args; + + return overloadName.str(); + } +}; + + +// +// Squirrel Overload Functions +// + +template +class SqOverload { +public: + + static SQInteger Func(HSQUIRRELVM vm) { + // Get the arg count + int argCount = sq_gettop(vm) - 2; + + const SQChar* funcName; + sq_getstring(vm, -1, &funcName); // get the function name (free variable) + + string overloadName = SqOverloadName::Get(funcName, argCount); + + sq_pushstring(vm, overloadName.c_str(), -1); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_get(vm, 1))) { // Lookup the proper overload + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#else + sq_get(vm, 1); +#endif + + // Push the args again + for (int i = 1; i <= argCount + 1; ++i) { + sq_push(vm, i); + } + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, argCount + 1, true, ErrorHandling::IsEnabled()); + if (SQ_FAILED(result)) { + return sq_throwerror(vm, LastErrorString(vm).c_str()); + } +#else + sq_call(vm, argCount + 1, true, ErrorHandling::IsEnabled()); +#endif + + return 1; + } +}; + + +// +// void return specialization +// + +template <> +class SqOverload { +public: + + static SQInteger Func(HSQUIRRELVM vm) { + // Get the arg count + int argCount = sq_gettop(vm) - 2; + + const SQChar* funcName; + sq_getstring(vm, -1, &funcName); // get the function name (free variable) + + string overloadName = SqOverloadName::Get(funcName, argCount); + + sq_pushstring(vm, overloadName.c_str(), -1); + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_get(vm, 1))) { // Lookup the proper overload + return sq_throwerror(vm, _SC("wrong number of parameters")); + } +#else + sq_get(vm, 1); +#endif + + // Push the args again + for (int i = 1; i <= argCount + 1; ++i) { + sq_push(vm, i); + } + +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQRESULT result = sq_call(vm, argCount + 1, false, ErrorHandling::IsEnabled()); + if (SQ_FAILED(result)) { + return sq_throwerror(vm, LastErrorString(vm).c_str()); + } +#else + sq_call(vm, argCount + 1, false, ErrorHandling::IsEnabled()); +#endif + + return 0; + } +}; + + +// +// Global Overloaded Function Resolvers +// + +// Arg Count 0 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)()) { + return &SqGlobal::template Func0; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)()) { + return &SqGlobal::template Func0; +} + +// Arg Count 1 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +// Arg Count 2 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +// Arg Count 3 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +// Arg Count 4 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +// Arg Count 5 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +// Arg Count 6 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +// Arg Count 7 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +// Arg Count 8 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +// Arg Count 9 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +// Arg Count 10 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +// Arg Count 11 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +// Arg Count 12 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +// Arg Count 13 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +// Arg Count 14 +template +SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} +template +SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} + + +// +// Member Global Overloaded Function Resolvers +// + +// Arg Count 1 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1)) { + return &SqGlobal::template Func1; +} + +// Arg Count 2 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2)) { + return &SqGlobal::template Func2; +} + +// Arg Count 3 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3)) { + return &SqGlobal::template Func3; +} + +// Arg Count 4 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4)) { + return &SqGlobal::template Func4; +} + +// Arg Count 5 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqGlobal::template Func5; +} + +// Arg Count 6 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqGlobal::template Func6; +} + +// Arg Count 7 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqGlobal::template Func7; +} + +// Arg Count 8 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqGlobal::template Func8; +} + +// Arg Count 9 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqGlobal::template Func9; +} + +// Arg Count 10 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqGlobal::template Func10; +} + +// Arg Count 11 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqGlobal::template Func11; +} + +// Arg Count 12 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqGlobal::template Func12; +} + +// Arg Count 13 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqGlobal::template Func13; +} + +// Arg Count 14 +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} + +template +SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqGlobal::template Func14; +} + + +// +// Member Overloaded Function Resolvers +// + +// Arg Count 0 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)()) { + return &SqMember::template Func0; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)() const) { + return &SqMember::template Func0C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)()) { + return &SqMember::template Func0; +} +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)() const) { + return &SqMember::template Func0C; +} + +// Arg Count 1 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1)) { + return &SqMember::template Func1; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1) const) { + return &SqMember::template Func1C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1)) { + return &SqMember::template Func1; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1) const) { + return &SqMember::template Func1C; +} + +// Arg Count 2 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2)) { + return &SqMember::template Func2; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2) const) { + return &SqMember::template Func2C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2)) { + return &SqMember::template Func2; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2) const) { + return &SqMember::template Func2C; +} + +// Arg Count 3 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3)) { + return &SqMember::template Func3; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3) const) { + return &SqMember::template Func3C; +} +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3)) { + return &SqMember::template Func3; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3) const) { + return &SqMember::template Func3C; +} + +// Arg Count 4 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4)) { + return &SqMember::template Func4; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4) const) { + return &SqMember::template Func4C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4)) { + return &SqMember::template Func4; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4) const) { + return &SqMember::template Func4C; +} + +// Arg Count 5 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqMember::template Func5; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5) const) { + return &SqMember::template Func5C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5)) { + return &SqMember::template Func5; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5) const) { + return &SqMember::template Func5C; +} + +// Arg Count 6 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqMember::template Func6; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6) const) { + return &SqMember::template Func6C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return &SqMember::template Func6; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6) const) { + return &SqMember::template Func6C; +} + +// Arg Count 7 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqMember::template Func7; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7) const) { + return &SqMember::template Func7C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return &SqMember::template Func7; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7) const) { + return &SqMember::template Func7C; +} + +// Arg Count 8 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqMember::template Func8; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8) const) { + return &SqMember::template Func8C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return &SqMember::template Func8; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8) const) { + return &SqMember::template Func8C; +} + +// Arg Count 9 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqMember::template Func9; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { + return &SqMember::template Func9C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return &SqMember::template Func9; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { + return &SqMember::template Func9C; +} + +// Arg Count 10 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqMember::template Func10; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { + return &SqMember::template Func10C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return &SqMember::template Func10; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { + return &SqMember::template Func10C; +} + +// Arg Count 11 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqMember::template Func11; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const) { + return &SqMember::template Func11C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return &SqMember::template Func11; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const) { + return &SqMember::template Func11C; +} + +// Arg Count 12 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqMember::template Func12; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const) { + return &SqMember::template Func12C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return &SqMember::template Func12; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const) { + return &SqMember::template Func12C; +} + +// Arg Count 13 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqMember::template Func13; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const) { + return &SqMember::template Func13C; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return &SqMember::template Func13; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const) { + return &SqMember::template Func13C; +} + + +// Arg Count 14 +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqMember::template Func14; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const) { + return &SqMember::template Func14C; +} +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return &SqMember::template Func14; +} + +template +inline SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const) { + return &SqMember::template Func14C; +} + + +// +// Overload handler resolver +// + +template +inline SQFUNCTION SqOverloadFunc(R (* /*method*/)) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)() const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const ) { + return &SqOverload::Func; +} + +template +inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const ) { + return &SqOverload::Func; +} + + +// +// Query argument count +// + +// Arg Count 0 +template +inline int SqGetArgCount(R (* /*method*/)()) { + return 0; +} + +// Arg Count 1 +template +inline int SqGetArgCount(R (* /*method*/)(A1)) { + return 1; +} + +// Arg Count 2 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2)) { + return 2; +} + +// Arg Count 3 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3)) { + return 3; +} + +// Arg Count 4 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4)) { + return 4; +} + +// Arg Count 5 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5)) { + return 5; +} + +// Arg Count 6 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return 6; +} + +// Arg Count 7 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return 7; +} + +// Arg Count 8 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return 8; +} + +// Arg Count 9 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return 9; +} + +// Arg Count 10 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return 10; +} + +// Arg Count 11 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return 11; +} + +// Arg Count 12 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return 12; +} + +// Arg Count 13 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return 13; +} + +// Arg Count 14 +template +inline int SqGetArgCount(R (* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return 14; +} + + +// +// Query member function argument count +// + +// Arg Count 0 +template +inline int SqGetArgCount(R (C::* /*method*/)()) { + return 0; +} + +// Arg Count 1 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1)) { + return 1; +} + +// Arg Count 2 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2)) { + return 2; +} + +// Arg Count 3 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3)) { + return 3; +} + +// Arg Count 4 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4)) { + return 4; +} + +// Arg Count 5 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5)) { + return 5; +} + +// Arg Count 6 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6)) { + return 6; +} + +// Arg Count 7 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7)) { + return 7; +} + +// Arg Count 8 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8)) { + return 8; +} + +// Arg Count 9 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9)) { + return 9; +} + +// Arg Count 10 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)) { + return 10; +} + +// Arg Count 11 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) { + return 11; +} + +// Arg Count 12 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)) { + return 12; +} + +// Arg Count 13 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)) { + return 13; +} + +// Arg Count 14 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)) { + return 14; +} + + +// +// Query const member function argument count +// + +// Arg Count 0 +template +inline int SqGetArgCount(R (C::* /*method*/)() const) { + return 0; +} + +// Arg Count 1 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1) const) { + return 1; +} + +// Arg Count 2 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2) const) { + return 2; +} + +// Arg Count 3 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3) const) { + return 3; +} + +// Arg Count 4 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4) const) { + return 4; +} + +// Arg Count 5 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5) const) { + return 5; +} + +// Arg Count 6 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6) const) { + return 6; +} + +// Arg Count 7 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7) const) { + return 7; +} + +// Arg Count 8 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8) const) { + return 8; +} + +// Arg Count 9 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const) { + return 9; +} + +// Arg Count 10 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const) { + return 10; +} + +// Arg Count 11 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) const) { + return 11; +} + +// Arg Count 12 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) const) { + return 12; +} + +// Arg Count 13 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) const) { + return 13; +} + +// Arg Count 14 +template +inline int SqGetArgCount(R (C::* /*method*/)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) const) { + return 14; +} + +/// @endcond + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratScript.h b/src/include/scripting/sqrat/sqratScript.h new file mode 100644 index 0000000000..d0ab06a6ac --- /dev/null +++ b/src/include/scripting/sqrat/sqratScript.h @@ -0,0 +1,243 @@ +// +// SqratScript: Script Compilation and Execution +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_SCRIPT_H_) +#define _SCRAT_SCRIPT_H_ + +#include +#include +#include + +#include "sqratObject.h" + +namespace Sqrat { + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Helper class for managing Squirrel scripts +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Script : public Object { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor + /// + /// \param v VM that the Script will be associated with + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Script(HSQUIRRELVM v = DefaultVM::Get()) : Object(v, true) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets up the Script using a string containing a Squirrel script + /// + /// \param script String containing a file path to a Squirrel script + /// \param name Optional string containing the script's name (for errors) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void CompileString(const string& script, const string& name = _SC("")) { + if(!sq_isnull(obj)) { + sq_release(vm, &obj); + sq_resetobject(&obj); + } + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_compilebuffer(vm, script.c_str(), static_cast(script.size() /** sizeof(SQChar)*/), name.c_str(), true))) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sq_compilebuffer(vm, script.c_str(), static_cast(script.size() /** sizeof(SQChar)*/), name.c_str(), true); +#endif + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(vm, 1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets up the Script using a string containing a Squirrel script + /// + /// \param script String containing a file path to a Squirrel script + /// \param errMsg String that is filled with any errors that may occur + /// \param name Optional string containing the script's name (for errors) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool CompileString(const string& script, string& errMsg, const string& name = _SC("")) { + if(!sq_isnull(obj)) { + sq_release(vm, &obj); + sq_resetobject(&obj); + } + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_compilebuffer(vm, script.c_str(), static_cast(script.size() /** sizeof(SQChar)*/), name.c_str(), true))) { + errMsg = LastErrorString(vm); + return false; + } +#else + sq_compilebuffer(vm, script.c_str(), static_cast(script.size() /** sizeof(SQChar)*/), name.c_str(), true); +#endif + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(vm, 1); + return true; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets up the Script using a file containing a Squirrel script + /// + /// \param path File path containing a Squirrel script + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void CompileFile(const string& path) { + if(!sq_isnull(obj)) { + sq_release(vm, &obj); + sq_resetobject(&obj); + } + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sqstd_loadfile(vm, path.c_str(), true))) { + SQTHROW(vm, LastErrorString(vm)); + return; + } +#else + sqstd_loadfile(vm, path.c_str(), true); +#endif + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(vm, 1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets up the Script using a file containing a Squirrel script + /// + /// \param path File path containing a Squirrel script + /// \param errMsg String that is filled with any errors that may occur + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool CompileFile(const string& path, string& errMsg) { + if(!sq_isnull(obj)) { + sq_release(vm, &obj); + sq_resetobject(&obj); + } + +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sqstd_loadfile(vm, path.c_str(), true))) { + errMsg = LastErrorString(vm); + return false; + } +#else + sqstd_loadfile(vm, path.c_str(), true); +#endif + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(vm, 1); + return true; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the script + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Run() { +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(!sq_isnull(obj)) { + SQRESULT result; + SQInteger top = sq_gettop(vm); + sq_pushobject(vm, obj); + sq_pushroottable(vm); + result = sq_call(vm, 1, false, true); + sq_settop(vm, top); + if(SQ_FAILED(result)) { + SQTHROW(vm, LastErrorString(vm)); + return; + } + } +#else + SQInteger top = sq_gettop(vm); + sq_pushobject(vm, obj); + sq_pushroottable(vm); + sq_call(vm, 1, false, true); + sq_settop(vm, top); +#endif + } + +#if !defined (SCRAT_NO_ERROR_CHECKING) + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs the script + /// + /// \param errMsg String that is filled with any errors that may occur + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Run(string& errMsg) { + if(!sq_isnull(obj)) { + SQRESULT result; + SQInteger top = sq_gettop(vm); + sq_pushobject(vm, obj); + sq_pushroottable(vm); + result = sq_call(vm, 1, false, true); + sq_settop(vm, top); + if(SQ_FAILED(result)) { + errMsg = LastErrorString(vm); + return false; + } + return true; + } + return false; + } +#endif + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Writes the byte code of the Script to a file + /// + /// \param path File path to write to + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void WriteCompiledFile(const string& path) { +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(!sq_isnull(obj)) { + sq_pushobject(vm, obj); + sqstd_writeclosuretofile(vm, path.c_str()); + } +#else + sq_pushobject(vm, obj); + sqstd_writeclosuretofile(vm, path.c_str()); +#endif + sq_pop(vm, 1); // needed? + } +}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratTable.h b/src/include/scripting/sqrat/sqratTable.h new file mode 100644 index 0000000000..5294ecbbd3 --- /dev/null +++ b/src/include/scripting/sqrat/sqratTable.h @@ -0,0 +1,541 @@ +// +// SqratTable: Table Binding +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_TABLE_H_) +#define _SCRAT_TABLE_H_ + +#include +#include + +#include "sqratObject.h" +#include "sqratFunction.h" +#include "sqratGlobalMethods.h" + +namespace Sqrat { + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// The base class for Table that implements almost all of its functionality +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class TableBase : public Object { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor (null) + /// + /// \param v VM that the table will exist in + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TableBase(HSQUIRRELVM v = DefaultVM::Get()) : Object(v, true) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the TableBase from an Object that already exists + /// + /// \param obj An Object that should already represent a Squirrel table + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TableBase(const Object& obj) : Object(obj) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the TableBase from a HSQOBJECT and HSQUIRRELVM that already exist + /// + /// \param o Squirrel object that should already represent a Squirrel table + /// \param v Squirrel VM that contains the Squirrel object given + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TableBase(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : Object(o, v) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a Table or Class to the Table (can be used to facilitate namespaces) + /// + /// \param name The key in the table being assigned a Table or Class + /// \param obj Table or Class that is being placed in the table + /// + /// \remarks + /// Bind cannot be called "inline" like other functions because it introduces order-of-initialization bugs. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Bind(const SQChar* name, Object& obj) { + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); + sq_pushobject(vm, obj.GetObject()); + sq_newslot(vm, -3, false); + sq_pop(vm,1); // pop table + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Binds a raw Squirrel closure to the Table + /// + /// \param name The key in the table being assigned a function + /// \param func Squirrel function that is being placed in the Table + /// + /// \return The Table itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TableBase& SquirrelFunc(const SQChar* name, SQFUNCTION func) { + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); + sq_newclosure(vm, func, 0); + sq_newslot(vm, -3, false); + sq_pop(vm,1); // pop table + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets a key in the Table to a specific value + /// + /// \param name The key in the table being assigned a value + /// \param val Value that is being placed in the Table + /// + /// \tparam V Type of value (usually doesnt need to be defined explicitly) + /// + /// \return The Table itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + TableBase& SetValue(const SQChar* name, const V& val) { + BindValue(name, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets an index in the Table to a specific value + /// + /// \param index The index in the table being assigned a value + /// \param val Value that is being placed in the Table + /// + /// \tparam V Type of value (usually doesnt need to be defined explicitly) + /// + /// \return The Table itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + TableBase& SetValue(const SQInteger index, const V& val) { + BindValue(index, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets a key in the Table to a specific instance (like a reference) + /// + /// \param name The key in the table being assigned a value + /// \param val Pointer to the instance that is being placed in the Table + /// + /// \tparam V Type of instance (usually doesnt need to be defined explicitly) + /// + /// \return The Table itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + TableBase& SetInstance(const SQChar* name, V* val) { + BindInstance(name, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets an index in the Table to a specific instance (like a reference) + /// + /// \param index The index in the table being assigned a value + /// \param val Pointer to the instance that is being placed in the Table + /// + /// \tparam V Type of instance (usually doesnt need to be defined explicitly) + /// + /// \return The Table itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + TableBase& SetInstance(const SQInteger index, V* val) { + BindInstance(index, val, false); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets a key in the Table to a specific function + /// + /// \param name The key in the table being assigned a value + /// \param method Function that is being placed in the Table + /// + /// \tparam F Type of function (only define this if you need to choose a certain template specialization or overload) + /// + /// \return The Table itself so the call can be chained + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + TableBase& Func(const SQChar* name, F method) { + BindFunc(name, &method, sizeof(method), SqGlobalFunc(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets a key in the Table to a specific function and allows the key to be overloaded with functions of a different amount of arguments + /// + /// \param name The key in the table being assigned a value + /// \param method Function that is being placed in the Table + /// + /// \tparam F Type of function (only define this if you need to choose a certain template specialization or overload) + /// + /// \return The Table itself so the call can be chained + /// + /// \remarks + /// Overloading in Sqrat does not work for functions with the same amount of arguments (just like in Squirrel). + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + TableBase& Overload(const SQChar* name, F method) { + BindOverload(name, &method, sizeof(method), SqGlobalOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method)); + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Checks if the given key exists in the table + /// + /// \param name Key to check + /// + /// \return True on success, otherwise false + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool HasKey(const SQChar* name) + { + sq_pushobject(vm, obj); + sq_pushstring(vm, name, -1); + if (SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + return false; + } + sq_pop(vm, 2); + return true; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns the value at a given key + /// + /// \param name Key of the element + /// + /// \tparam T Type of value (fails if value is not of this type) + /// + /// \return SharedPtr containing the value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr GetValue(const SQChar* name) + { + sq_pushobject(vm, obj); + sq_pushstring(vm, name, -1); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + SQTHROW(vm, _SC("illegal index")); + return SharedPtr(); + } +#else + sq_get(vm, -2); +#endif + SQTRY() + Var > entry(vm, -1); + SQCATCH_NOEXCEPT(vm) { + sq_pop(vm, 2); + return SharedPtr(); + } + sq_pop(vm, 2); + return entry.value; + SQCATCH(vm) { +#if defined (SCRAT_USE_EXCEPTIONS) + SQUNUSED(e); // avoid "unreferenced local variable" warning +#endif + sq_pop(vm, 2); + SQRETHROW(vm); + } + return SharedPtr(); // avoid "not all control paths return a value" warning + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns the value at a given index + /// + /// \param index Index of the element + /// + /// \tparam T Type of value (fails if value is not of this type) + /// + /// \return SharedPtr containing the value (or null if failed) + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr GetValue(int index) + { + sq_pushobject(vm, obj); + sq_pushinteger(vm, index); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if (SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + SQTHROW(vm, _SC("illegal index")); + return SharedPtr(); + } +#else + sq_get(vm, -2); +#endif + SQTRY() + Var > entry(vm, -1); + SQCATCH_NOEXCEPT(vm) { + sq_pop(vm, 2); + return SharedPtr(); + } + sq_pop(vm, 2); + return entry.value; + SQCATCH(vm) { +#if defined (SCRAT_USE_EXCEPTIONS) + SQUNUSED(e); // avoid "unreferenced local variable" warning +#endif + sq_pop(vm, 2); + SQRETHROW(vm); + } + return SharedPtr(); // avoid "not all control paths return a value" warning + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets a Function from a key in the Table + /// + /// \param name The key in the table that contains the Function + /// + /// \return Function found in the Table (null if failed) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function GetFunction(const SQChar* name) { + HSQOBJECT funcObj; + sq_pushobject(vm, GetObject()); + sq_pushstring(vm, name, -1); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + return Function(); + } + SQObjectType value_type = sq_gettype(vm, -1); + if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) { + sq_pop(vm, 2); + return Function(); + } +#else + sq_get(vm, -2); +#endif + sq_getstackobj(vm, -1, &funcObj); + Function ret(vm, GetObject(), funcObj); // must addref before the pop! + sq_pop(vm, 2); + return ret; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets a Function from an index in the Table + /// + /// \param index The index in the table that contains the Function + /// + /// \return Function found in the Table (null if failed) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Function GetFunction(const SQInteger index) { + HSQOBJECT funcObj; + sq_pushobject(vm, GetObject()); + sq_pushinteger(vm, index); +#if !defined (SCRAT_NO_ERROR_CHECKING) + if(SQ_FAILED(sq_get(vm, -2))) { + sq_pop(vm, 1); + return Function(); + } + SQObjectType value_type = sq_gettype(vm, -1); + if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) { + sq_pop(vm, 2); + return Function(); + } +#else + sq_get(vm, -2); +#endif + sq_getstackobj(vm, -1, &funcObj); + Function ret(vm, GetObject(), funcObj); // must addref before the pop! + sq_pop(vm, 2); + return ret; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Represents a table in Squirrel +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Table : public TableBase { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor (null) + /// + /// \remarks + /// The Table is invalid until it is given a VM to exist in. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Table() { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a Table + /// + /// \param v VM to create the Table in + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Table(HSQUIRRELVM v) : TableBase(v) { + sq_newtable(vm); + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(vm,1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the Table from an Object that already exists + /// + /// \param obj An Object that should already represent a Squirrel table + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Table(const Object& obj) : TableBase(obj) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Construct the Table from a HSQOBJECT and HSQUIRRELVM that already exist + /// + /// \param o Squirrel object that should already represent a Squirrel table + /// \param v Squirrel VM that contains the Squirrel object given + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Table(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : TableBase(o, v) { + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Table that is a reference to the Squirrel root table for a given VM +/// The Squirrel root table is usually where all globals are stored by the Squirrel language. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class RootTable : public TableBase { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a RootTable object to represent the given VM's root table + /// + /// \param v VM to get the RootTable for + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + RootTable(HSQUIRRELVM v = DefaultVM::Get()) : TableBase(v) { + sq_pushroottable(vm); + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(v,1); // pop root table + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Table that is a reference to the Squirrel registry table for a given VM +/// The Squirrel registry table is where non-Squirrel code can store Squirrel objects without worrying about Squirrel code messing with them. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class RegistryTable : public TableBase { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a RegistryTable object to represent the given VM's registry table + /// + /// \param v VM to get the RegistryTable for + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + RegistryTable(HSQUIRRELVM v = DefaultVM::Get()) : TableBase(v) { + sq_pushregistrytable(v); + sq_getstackobj(vm,-1,&obj); + sq_addref(vm, &obj); + sq_pop(v,1); // pop the registry table + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Table instances to and from the stack as references (tables are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + Table value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a Table + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + HSQOBJECT obj; + sq_resetobject(&obj); + sq_getstackobj(vm,idx,&obj); + value = Table(obj, vm); +#if !defined (SCRAT_NO_ERROR_CHECKING) + SQObjectType value_type = sq_gettype(vm, idx); + if (value_type != OT_TABLE) { + SQTHROW(vm, FormatTypeError(vm, idx, _SC("table"))); + } +#endif + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put an Table reference on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const Table& value) { + HSQOBJECT obj; + sq_resetobject(&obj); + obj = value.GetObject(); + sq_pushobject(vm,obj); + } +}; + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Table instances to and from the stack as references (tables are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var
{Var(HSQUIRRELVM vm, SQInteger idx) : Var
(vm, idx) {}}; + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push Table instances to and from the stack as references (tables are always references in Squirrel) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var : Var
{Var(HSQUIRRELVM vm, SQInteger idx) : Var
(vm, idx) {}}; + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratTypes.h b/src/include/scripting/sqrat/sqratTypes.h new file mode 100644 index 0000000000..f363d65c1a --- /dev/null +++ b/src/include/scripting/sqrat/sqratTypes.h @@ -0,0 +1,1121 @@ +// +// SqratTypes: Type Translators +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_TYPES_H_) +#define _SCRAT_TYPES_H_ + +#ifdef SQUNICODE +#include +#include +#endif + +#include +#include + +#include "sqratClassType.h" +#include "sqratUtil.h" + +namespace Sqrat { + +/// @cond DEV + +// copied from http://www.experts-exchange.com/Programming/Languages/CPP/A_223-Determing-if-a-C-type-is-convertable-to-another-at-compile-time.html +template +struct is_convertible +{ +private: + struct True_ { char x[2]; }; + struct False_ { }; + + static True_ helper(T2 const &); + static False_ helper(...); + + static T1* dummy; + +public: + static bool const YES = ( + sizeof(True_) == sizeof(is_convertible::helper(*dummy)) + ); +}; + +template +struct popAsInt +{ + T value; + popAsInt(HSQUIRRELVM vm, SQInteger idx) + { + SQObjectType value_type = sq_gettype(vm, idx); + switch(value_type) { + case OT_BOOL: + SQBool sqValueb; + sq_getbool(vm, idx, &sqValueb); + value = static_cast(sqValueb); + break; + case OT_INTEGER: + SQInteger sqValue; + sq_getinteger(vm, idx, &sqValue); + value = static_cast(sqValue); + break; + case OT_FLOAT: + SQFloat sqValuef; + sq_getfloat(vm, idx, &sqValuef); + value = static_cast(static_cast(sqValuef)); + break; + default: + SQTHROW(vm, FormatTypeError(vm, idx, _SC("integer"))); + value = static_cast(0); + break; + } + } +}; + +template +struct popAsInt +{ + T value; // cannot be initialized because unknown constructor parameters + popAsInt(HSQUIRRELVM /*vm*/, SQInteger /*idx*/) + { + // keep the current error message already set previously, do not touch that here + } +}; + +template +struct popAsFloat +{ + T value; + popAsFloat(HSQUIRRELVM vm, SQInteger idx) + { + SQObjectType value_type = sq_gettype(vm, idx); + switch(value_type) { + case OT_BOOL: + SQBool sqValueb; + sq_getbool(vm, idx, &sqValueb); + value = static_cast(sqValueb); + break; + case OT_INTEGER: + SQInteger sqValue; \ + sq_getinteger(vm, idx, &sqValue); + value = static_cast(sqValue); + break; + case OT_FLOAT: + SQFloat sqValuef; + sq_getfloat(vm, idx, &sqValuef); + value = static_cast(sqValuef); + break; + default: + SQTHROW(vm, FormatTypeError(vm, idx, _SC("float"))); + value = 0; + break; + } + } +}; + +/// @endcond + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push class instances to and from the stack as copies +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +/// \remarks +/// This specialization requires T to have a default constructor. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct Var { + + T value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + SQTRY() + T* ptr = ClassType::GetInstance(vm, idx); + if (ptr != NULL) { + value = *ptr; +#if !defined (SCRAT_NO_ERROR_CHECKING) + } else if (is_convertible::YES) { /* value is likely of integral type like enums */ + SQCLEAR(vm); // clear the previous error + value = popAsInt::YES>(vm, idx).value; +#endif + } else { + // initialize value to avoid warnings + value = popAsInt::YES>(vm, idx).value; + } + SQCATCH(vm) { +#if defined (SCRAT_USE_EXCEPTIONS) + SQUNUSED(e); // avoid "unreferenced local variable" warning +#endif + if (is_convertible::YES) { /* value is likely of integral type like enums */ + value = popAsInt::YES>(vm, idx).value; + } else { + SQRETHROW(vm); + } + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const T& value) { + if (ClassType::hasClassData(vm)) + ClassType::PushInstanceCopy(vm, value); + else /* try integral type */ + pushAsInt::YES>().push(vm, value); + } + +private: + + template + struct pushAsInt { + void push(HSQUIRRELVM vm, const T2& /*value*/) { + assert(false); // fails because called before a Sqrat::Class for T exists and T is not convertible to SQInteger + sq_pushnull(vm); + } + }; + + template + struct pushAsInt { + void push(HSQUIRRELVM vm, const T2& value) { + sq_pushinteger(vm, static_cast(value)); + } + }; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push class instances to and from the stack as references +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct Var { + + T& value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) : value(*ClassType::GetInstance(vm, idx)) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVarR to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, T& value) { + if (ClassType::hasClassData(vm)) + ClassType::PushInstance(vm, &value); + else /* try integral type */ + pushAsInt::YES>().push(vm, value); + } + +private: + + template + struct pushAsInt { + void push(HSQUIRRELVM vm, const T2& /*value*/) { + assert(false); // fails because called before a Sqrat::Class for T exists and T is not convertible to SQInteger + sq_pushnull(vm); + } + }; + + template + struct pushAsInt { + void push(HSQUIRRELVM vm, const T2& value) { + sq_pushinteger(vm, static_cast(value)); + } + }; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push class instances to and from the stack as pointers +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct Var { + + T* value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) : value(ClassType::GetInstance(vm, idx, true)) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, T* value) { + ClassType::PushInstance(vm, value); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push class instances to and from the stack as pointers to const data +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct Var { + + T* const value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) : value(ClassType::GetInstance(vm, idx, true)) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, T* const value) { + ClassType::PushInstance(vm, value); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push class instances to and from the stack as const references +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct Var { + + const T& value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) : value(*ClassType::GetInstance(vm, idx)) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const T& value) { + ClassType::PushInstanceCopy(vm, value); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push class instances to and from the stack as const pointers +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct Var { + + const T* value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) : value(ClassType::GetInstance(vm, idx, true)) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const T* value) { + ClassType::PushInstance(vm, const_cast(value)); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push class instances to and from the stack as const pointers to const data +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +struct Var { + + const T* const value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) : value(ClassType::GetInstance(vm, idx, true)) { + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const T* const value) { + ClassType::PushInstance(vm, const_cast(value)); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get (as copies) and push (as references) class instances to and from the stack as a SharedPtr +/// +/// \tparam T Type of instance (usually doesnt need to be defined explicitly) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template void PushVarR(HSQUIRRELVM vm, T& value); +template +struct Var > { + + SharedPtr value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as the given type + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + if (sq_gettype(vm, idx) != OT_NULL) { + Var instance(vm, idx); + SQCATCH_NOEXCEPT(vm) { + return; + } + value.Init(new T(instance.value)); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a class object on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const SharedPtr& value) { + PushVarR(vm, *value); + } +}; + +// Integer types +#define SCRAT_INTEGER( type ) \ + template<> \ + struct Var { \ + type value; \ + Var(HSQUIRRELVM vm, SQInteger idx) { \ + value = popAsInt(vm, idx).value; \ + } \ + static void push(HSQUIRRELVM vm, const type& value) { \ + sq_pushinteger(vm, static_cast(value)); \ + } \ + };\ + \ + template<> \ + struct Var { \ + type value; \ + Var(HSQUIRRELVM vm, SQInteger idx) { \ + value = popAsInt(vm, idx).value; \ + } \ + static void push(HSQUIRRELVM vm, const type& value) { \ + sq_pushinteger(vm, static_cast(value)); \ + } \ + }; + +SCRAT_INTEGER(unsigned int) +SCRAT_INTEGER(signed int) +SCRAT_INTEGER(unsigned long) +SCRAT_INTEGER(signed long) +SCRAT_INTEGER(unsigned short) +SCRAT_INTEGER(signed short) +SCRAT_INTEGER(unsigned char) +SCRAT_INTEGER(signed char) +SCRAT_INTEGER(unsigned long long) +SCRAT_INTEGER(signed long long) + +#ifdef _MSC_VER +#if defined(__int64) +SCRAT_INTEGER(unsigned __int64) +SCRAT_INTEGER(signed __int64) +#endif +#endif + +// Float types +#define SCRAT_FLOAT( type ) \ + template<> \ + struct Var { \ + type value; \ + Var(HSQUIRRELVM vm, SQInteger idx) { \ + value = popAsFloat(vm, idx).value; \ + } \ + static void push(HSQUIRRELVM vm, const type& value) { \ + sq_pushfloat(vm, static_cast(value)); \ + } \ + }; \ + \ + template<> \ + struct Var { \ + type value; \ + Var(HSQUIRRELVM vm, SQInteger idx) { \ + value = popAsFloat(vm, idx).value; \ + } \ + static void push(HSQUIRRELVM vm, const type& value) { \ + sq_pushfloat(vm, static_cast(value)); \ + } \ + }; + +SCRAT_FLOAT(float) +SCRAT_FLOAT(double) + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push bools to and from the stack +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + bool value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a bool + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + SQBool sqValue; + sq_tobool(vm, idx, &sqValue); + value = (sqValue != 0); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a bool on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const bool& value) { + sq_pushbool(vm, static_cast(value)); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push const bool references to and from the stack +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + bool value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a bool + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + SQBool sqValue; + sq_tobool(vm, idx, &sqValue); + value = (sqValue != 0); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a bool on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const bool& value) { + sq_pushbool(vm, static_cast(value)); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push SQChar arrays to and from the stack (usually is a char array) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { +private: + + HSQOBJECT obj; /* hold a reference to the object holding value during the Var struct lifetime*/ + HSQUIRRELVM v; + +public: + + SQChar* value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a character array + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + sq_tostring(vm, idx); + sq_getstackobj(vm, -1, &obj); + sq_getstring(vm, -1, (const SQChar**)&value); + sq_addref(vm, &obj); + sq_pop(vm,1); + v = vm; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~Var() + { + if(v && !sq_isnull(obj)) { + sq_release(v, &obj); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a character array on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// \param len Length of the string (defaults to finding the length by searching for a terminating null-character) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const SQChar* value, SQInteger len = -1) { + sq_pushstring(vm, value, len); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push const SQChar arrays to and from the stack (usually is a const char array) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { +private: + + HSQOBJECT obj; /* hold a reference to the object holding value during the Var struct lifetime*/ + HSQUIRRELVM v; + +public: + + const SQChar* value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a character array + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + sq_tostring(vm, idx); + sq_getstackobj(vm, -1, &obj); + sq_getstring(vm, -1, &value); + sq_addref(vm, &obj); + sq_pop(vm,1); + v = vm; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~Var() + { + if(v && !sq_isnull(obj)) { + sq_release(v, &obj); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a character array on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// \param len Length of the string (defaults to finding the length by searching for a terminating null-character) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const SQChar* value, SQInteger len = -1) { + sq_pushstring(vm, value, len); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push strings to and from the stack (string is usually std::string) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + string value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a string + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + const SQChar* ret; + sq_tostring(vm, idx); + sq_getstring(vm, -1, &ret); + value = string(ret, sq_getsize(vm, -1)); + sq_pop(vm,1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a string on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const string& value) { + sq_pushstring(vm, value.c_str(), value.size()); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push const string references to and from the stack as copies (strings are always copied) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + string value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a string + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + const SQChar* ret; + sq_tostring(vm, idx); + sq_getstring(vm, -1, &ret); + value = string(ret, sq_getsize(vm, -1)); + sq_pop(vm,1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a string on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const string& value) { + sq_pushstring(vm, value.c_str(), value.size()); + } +}; + +#ifdef SQUNICODE +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push std::string to and from the stack when SQChar is not char (must define SQUNICODE) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + std::string value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a string + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + const SQChar* ret; + sq_tostring(vm, idx); + sq_getstring(vm, -1, &ret); + value = wstring_to_string(string(ret, sq_getsize(vm, -1))); + sq_pop(vm,1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a string on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const std::string& value) { + std::wstring s = string_to_wstring(value); + sq_pushstring(vm, s.c_str(), s.size()); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push const std::string references to and from the stack when SQChar is not char (must define SQUNICODE) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { + + std::string value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a string + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + const SQChar* ret; + sq_tostring(vm, idx); + sq_getstring(vm, -1, &ret); + value = wstring_to_string(string(ret, sq_getsize(vm, -1))); + sq_pop(vm,1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a string on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const std::string& value) { + std::wstring s = string_to_wstring(value); + sq_pushstring(vm, s.c_str(), s.size()); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push SQChar arrays to and from the stack when SQChar is not char (must define SQUNICODE) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { +private: + + HSQOBJECT obj;/* hold a reference to the object holding value during the Var struct lifetime*/ + HSQUIRRELVM v; + +public: + + char* value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a character array + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + std::string holder; + const SQChar *sv; + sq_tostring(vm, idx); + sq_getstackobj(vm, -1, &obj); + sq_getstring(vm, -1, &sv); + sq_addref(vm, &obj); + sq_pop(vm,1); + v = vm; + holder = wstring_to_string(string(sv)); + value = strdup(holder.c_str()); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~Var() + { + if(v && !sq_isnull(obj)) { + sq_release(v, &obj); + free(value); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a character array on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// \param len Length of the string (defaults to finding the length by searching for a terminating null-character) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const char* value, SQInteger len = -1) { + sq_pushstring(vm, string_to_wstring(std::string(value)).c_str(), len); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Used to get and push const SQChar arrays to and from the stack when SQChar is not char (must define SQUNICODE) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<> +struct Var { +private: + + HSQOBJECT obj; /* hold a reference to the object holding value during the Var struct lifetime*/ + HSQUIRRELVM v; + +public: + + char* value; ///< The actual value of get operations + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as a character array + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx) { + std::string holder; + const SQChar *sv; + sq_tostring(vm, idx); + sq_getstackobj(vm, -1, &obj); + sq_getstring(vm, -1, &sv); + sq_addref(vm, &obj); + sq_pop(vm,1); + v = vm; + holder = wstring_to_string(string(sv)); + value = strdup(holder.c_str()); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~Var() + { + if(v && !sq_isnull(obj)) { + sq_release(v, &obj); + free(value); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Called by Sqrat::PushVar to put a character array on the stack + /// + /// \param vm Target VM + /// \param value Value to push on to the VM's stack + /// \param len Length of the string (defaults to finding the length by searching for a terminating null-character) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void push(HSQUIRRELVM vm, const char* value, SQInteger len = -1) { + sq_pushstring(vm, string_to_wstring(std::string(value)).c_str(), len); + } +}; +#endif + + +// Non-referencable type definitions +template struct is_referencable {static const bool value = true;}; + +#define SCRAT_MAKE_NONREFERENCABLE( type ) \ + template<> struct is_referencable {static const bool value = false;}; + +SCRAT_MAKE_NONREFERENCABLE(unsigned int) +SCRAT_MAKE_NONREFERENCABLE(signed int) +SCRAT_MAKE_NONREFERENCABLE(unsigned long) +SCRAT_MAKE_NONREFERENCABLE(signed long) +SCRAT_MAKE_NONREFERENCABLE(unsigned short) +SCRAT_MAKE_NONREFERENCABLE(signed short) +SCRAT_MAKE_NONREFERENCABLE(unsigned char) +SCRAT_MAKE_NONREFERENCABLE(signed char) +SCRAT_MAKE_NONREFERENCABLE(unsigned long long) +SCRAT_MAKE_NONREFERENCABLE(signed long long) +SCRAT_MAKE_NONREFERENCABLE(float) +SCRAT_MAKE_NONREFERENCABLE(double) +SCRAT_MAKE_NONREFERENCABLE(bool) +SCRAT_MAKE_NONREFERENCABLE(string) + +#ifdef _MSC_VER +#if defined(__int64) +SCRAT_MAKE_NONREFERENCABLE(unsigned __int64) +SCRAT_MAKE_NONREFERENCABLE(signed __int64) +#endif +#endif + +#ifdef SQUNICODE +SCRAT_MAKE_NONREFERENCABLE(std::string) +#endif + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Pushes a value on to a given VM's stack +/// +/// \param vm VM that the variable will be pushed on to the stack of +/// \param value The actual value being pushed +/// +/// \tparam T Type of value (usually doesnt need to be defined explicitly) +/// +/// \remarks +/// What this function does is defined by Sqrat::Var template specializations, +/// and thus you can create custom functionality for it by making new template specializations. +/// When making a custom type that is not referencable, you must use SCRAT_MAKE_NONREFERENCABLE( type ) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +inline void PushVar(HSQUIRRELVM vm, T* value) { + Var::push(vm, value); +} + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Pushes a value on to a given VM's stack +/// +/// \param vm VM that the variable will be pushed on to the stack of +/// \param value The actual value being pushed +/// +/// \tparam T Type of value (usually doesnt need to be defined explicitly) +/// +/// \remarks +/// What this function does is defined by Sqrat::Var template specializations, +/// and thus you can create custom functionality for it by making new template specializations. +/// When making a custom type that is not referencable, you must use SCRAT_MAKE_NONREFERENCABLE( type ) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +inline void PushVar(HSQUIRRELVM vm, const T& value) { + Var::push(vm, value); +} + + +/// @cond DEV +template +struct PushVarR_helper { + inline static void push(HSQUIRRELVM vm, T value) { + PushVar(vm, value); + } +}; +template +struct PushVarR_helper { + inline static void push(HSQUIRRELVM vm, const T& value) { + PushVar(vm, value); + } +}; +/// @endcond + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Pushes a reference on to a given VM's stack (some types cannot be referenced and will be copied instead) +/// +/// \param vm VM that the reference will be pushed on to the stack of +/// \param value The actual referenced value being pushed +/// +/// \tparam T Type of value (usually doesnt need to be defined explicitly) +/// +/// \remarks +/// What this function does is defined by Sqrat::Var template specializations, +/// and thus you can create custom functionality for it by making new template specializations. +/// When making a custom type that is not referencable, you must use SCRAT_MAKE_NONREFERENCABLE( type ) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +inline void PushVarR(HSQUIRRELVM vm, T& value) { + if (!is_pointer::value && is_referencable::type>::value) { + Var::push(vm, value); + } else { + PushVarR_helper::value>::push(vm, value); + } +} + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratUtil.h b/src/include/scripting/sqrat/sqratUtil.h new file mode 100644 index 0000000000..c076d70c89 --- /dev/null +++ b/src/include/scripting/sqrat/sqratUtil.h @@ -0,0 +1,1197 @@ +// +// SqratUtil: Squirrel Utilities +// + +// +// Copyright (c) 2009 Brandon Jones +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_UTIL_H_) +#define _SCRAT_UTIL_H_ + +#include +#include +#include +#include + +#if defined(SCRAT_USE_CXX11_OPTIMIZATIONS) +#include +#endif + +namespace Sqrat { + +/// @cond DEV + +#if defined(SCRAT_USE_CXX11_OPTIMIZATIONS) + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Define an unordered map for Sqrat to use based on whether SCRAT_USE_CXX11_OPTIMIZATIONS is defined or not + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + struct unordered_map { + typedef std::unordered_map type; + }; +#else + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Define an unordered map for Sqrat to use based on whether SCRAT_USE_CXX11_OPTIMIZATIONS is defined or not + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + struct unordered_map { + typedef std::map type; + }; +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Define an inline function to avoid MSVC's "conditional expression is constant" warning +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef _MSC_VER + template + inline T _c_def(T value) { return value; } + #define SQRAT_CONST_CONDITION(value) _c_def(value) +#else + #define SQRAT_CONST_CONDITION(value) value +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Define helpers to create portable import / export macros +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(SCRAT_EXPORT) + #if defined(_WIN32) + // Windows compilers need a specific keyword for export + #define SQRAT_API __declspec(dllexport) + #else + #if __GNUC__ >= 4 + // GCC 4 has special keywords for showing/hiding symbols, + // the same keyword is used for both importing and exporting + #define SQRAT_API __attribute__ ((__visibility__ ("default"))) + #else + // GCC < 4 has no mechanism to explicitly hide symbols, everything's exported + #define SQRAT_API + + #endif + #endif +#elif defined(SCRAT_IMPORT) + #if defined(_WIN32) + // Windows compilers need a specific keyword for import + #define SQRAT_API __declspec(dllimport) + #else + #if __GNUC__ >= 4 + // GCC 4 has special keywords for showing/hiding symbols, + // the same keyword is used for both importing and exporting + #define SQRAT_API __attribute__ ((__visibility__ ("default"))) + #else + // GCC < 4 has no mechanism to explicitly hide symbols, everything's exported + #define SQRAT_API + #endif + #endif +#else + #define SQRAT_API +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Define macros for internal error handling +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined (SCRAT_NO_ERROR_CHECKING) + #define SQCATCH(vm) if (SQRAT_CONST_CONDITION(false)) + #define SQCATCH_NOEXCEPT(vm) if (SQRAT_CONST_CONDITION(false)) + #define SQCLEAR(vm) + #define SQRETHROW(vm) + #define SQTHROW(vm, err) + #define SQTRY() + #define SQWHAT(vm) _SC("") + #define SQWHAT_NOEXCEPT(vm) _SC("") +#elif defined (SCRAT_USE_EXCEPTIONS) + #define SQCATCH(vm) } catch (const Sqrat::Exception& e) + #define SQCATCH_NOEXCEPT(vm) if (SQRAT_CONST_CONDITION(false)) + #define SQCLEAR(vm) + #ifdef _MSC_VER // avoid MSVC's "unreachable code" warning + #define SQRETHROW(vm) if (SQRAT_CONST_CONDITION(true)) throw + #define SQTHROW(vm, err) if (SQRAT_CONST_CONDITION(true)) throw Sqrat::Exception(err) + #else + #define SQRETHROW(vm) throw + #define SQTHROW(vm, err) throw Sqrat::Exception(err) + #endif + #define SQTRY() try { + #define SQWHAT(vm) e.Message().c_str() + #define SQWHAT_NOEXCEPT(vm) _SC("") +#else + #define SQCATCH(vm) if (SQRAT_CONST_CONDITION(false)) + #define SQCATCH_NOEXCEPT(vm) if (Error::Occurred(vm)) + #define SQCLEAR(vm) Error::Clear(vm) + #define SQRETHROW(vm) + #define SQTHROW(vm, err) Error::Throw(vm, err) + #define SQTRY() + #define SQWHAT(vm) _SC("") + #define SQWHAT_NOEXCEPT(vm) Error::Message(vm).c_str() +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Removes unused variable warnings in a way that Doxygen can understand +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +void SQUNUSED(const T&) { +} + +/// @endcond + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Defines a string that is definitely compatible with the version of Squirrel being used (normally this is std::string) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef std::basic_string string; + +/// @cond DEV +#ifdef SQUNICODE +/* from http://stackoverflow.com/questions/15333259/c-stdwstring-to-stdstring-quick-and-dirty-conversion-for-use-as-key-in, + only works for ASCII chars */ +/** +* Convert a std::string into a std::wstring +*/ +static std::wstring string_to_wstring(const std::string& str) +{ + return std::wstring(str.begin(), str.end()); +} + +/** +* Convert a std::wstring into a std::string +*/ +static std::string wstring_to_string(const std::wstring& wstr) +{ + return std::string(wstr.begin(), wstr.end()); +} + +#endif // SQUNICODE + +template +class SharedPtr; + +template +class WeakPtr; + +/// @endcond + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Helper class that defines a VM that can be used as a fallback VM in case no other one is given to a piece of code +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class DefaultVM { +private: + + static HSQUIRRELVM& staticVm() { + static HSQUIRRELVM vm; + return vm; + } + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the default VM + /// + /// \return Default VM + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static HSQUIRRELVM Get() { + return staticVm(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets the default VM to a given VM + /// + /// \param vm New default VM + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void Set(HSQUIRRELVM vm) { + staticVm() = vm; + } +}; + +#if !defined (SCRAT_NO_ERROR_CHECKING) && !defined (SCRAT_USE_EXCEPTIONS) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// The class that must be used to deal with errors that Sqrat has +/// +/// \remarks +/// When documentation in Sqrat says, "This function MUST have its error handled if it occurred," that +/// means that after the function has been run, you must call Error::Occurred to see if the function +/// ran successfully. If the function did not run successfully, then you MUST either call Error::Clear +/// or Error::Message to clear the error buffer so new ones may occur and Sqrat does not get confused. +/// +/// \remarks +/// Any error thrown inside of a bound C++ function will be thrown in the given Squirrel VM and +/// automatically handled. +/// +/// \remarks +/// If compiling with SCRAT_USE_EXCEPTIONS defined, Sqrat will throw exceptions instead of using this +/// class to handle errors. This means that functions must be enclosed in try blocks that catch +/// Sqrat::Exception instead of checking for errors with Error::Occurred. +/// +/// \remarks +/// If compiling with SCRAT_NO_ERROR_CHECKING defined, Sqrat will run significantly faster, +/// but it will no longer check for errors and the Error class itself will not be defined. +/// In this mode, a Squirrel script may crash the C++ application if errors occur in it. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Error { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Clears the error associated with a given VM + /// + /// \param vm Target VM + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void Clear(HSQUIRRELVM vm) { + sq_pushregistrytable(vm); + sq_pushstring(vm, "__error", -1); + sq_rawdeleteslot(vm, -2, false); + sq_pop(vm, 1); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Clears the error associated with a given VM and returns the associated error message + /// + /// \param vm Target VM + /// + /// \return String containing a nice error message + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static string Message(HSQUIRRELVM vm) { + sq_pushregistrytable(vm); + sq_pushstring(vm, "__error", -1); + if (SQ_SUCCEEDED(sq_rawget(vm, -2))) { + string** ud; + sq_getuserdata(vm, -1, (SQUserPointer*)&ud, NULL); + sq_pop(vm, 1); + string err = **ud; + sq_pushstring(vm, "__error", -1); + sq_rawdeleteslot(vm, -2, false); + sq_pop(vm, 1); + return err; + } + sq_pushstring(vm, "__error", -1); + sq_rawdeleteslot(vm, -2, false); + sq_pop(vm, 1); + return string(_SC("an unknown error has occurred")); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns whether a Sqrat error has occurred with a given VM + /// + /// \param vm Target VM + /// + /// \return True if an error has occurred, otherwise false + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static bool Occurred(HSQUIRRELVM vm) { + sq_pushregistrytable(vm); + sq_pushstring(vm, "__error", -1); + if (SQ_SUCCEEDED(sq_rawget(vm, -2))) { + sq_pop(vm, 2); + return true; + } + sq_pop(vm, 1); + return false; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Raises an error in a given VM with a given error message + /// + /// \param vm Target VM + /// \param err A nice error message + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void Throw(HSQUIRRELVM vm, const string& err) { + sq_pushregistrytable(vm); + sq_pushstring(vm, "__error", -1); + if (SQ_FAILED(sq_rawget(vm, -2))) { + sq_pushstring(vm, "__error", -1); + string** ud = reinterpret_cast(sq_newuserdata(vm, sizeof(string*))); + *ud = new string(err); + sq_setreleasehook(vm, -1, &error_cleanup_hook); + sq_rawset(vm, -3); + sq_pop(vm, 1); + return; + } + sq_pop(vm, 2); + } + +private: + + Error() {} + + static SQInteger error_cleanup_hook(SQUserPointer ptr, SQInteger size) { + SQUNUSED(size); + string** ud = reinterpret_cast(ptr); + delete *ud; + return 0; + } +}; +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Tells Sqrat whether Squirrel error handling should be used +/// +/// \remarks +/// If true, if a runtime error occurs during the execution of a call, the VM will invoke its error handler. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class ErrorHandling { +private: + + static bool& errorHandling() { + static bool eh = true; + return eh; + } + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns whether Squirrel error handling is enabled + /// + /// \return True if error handling is enabled, otherwise false + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static bool IsEnabled() { + return errorHandling(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Enables or disables Squirrel error handling + /// + /// \param enable True to enable, false to disable + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void Enable(bool enable) { + errorHandling() = enable; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Sqrat exception class +/// +/// \remarks +/// Used only when SCRAT_USE_EXCEPTIONS is defined (see Sqrat::Error) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Exception { +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs an exception + /// + /// \param msg A nice error message + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Exception(const string& msg) : message(msg) {} + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param ex Exception to copy + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Exception(const Exception& ex) : message(ex.message) {} + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Returns a string identifying the exception + /// + /// \return A nice error message + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const string& Message() const { + return message; + } + +private: + + string message; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Returns a string that has been formatted to give a nice type error message (for usage with Class::SquirrelFunc) +/// +/// \param vm VM the error occurred with +/// \param idx Index on the stack of the argument that had a type error +/// \param expectedType The name of the type that the argument should have been +/// +/// \return String containing a nice type error message +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline string FormatTypeError(HSQUIRRELVM vm, SQInteger idx, const string& expectedType) { + string err = _SC("wrong type (") + expectedType + _SC(" expected"); +#if (SQUIRREL_VERSION_NUMBER>= 200) && (SQUIRREL_VERSION_NUMBER < 300) // Squirrel 2.x + err = err + _SC(")"); +#else // Squirrel 3.x + if (SQ_SUCCEEDED(sq_typeof(vm, idx))) { + const SQChar* actualType; + sq_tostring(vm, -1); + sq_getstring(vm, -1, &actualType); + sq_pop(vm, 2); + err = err + _SC(", got ") + actualType + _SC(")"); + } else { + err = err + _SC(", got unknown)"); + } +#endif + return err; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Returns the last error that occurred with a Squirrel VM (not associated with Sqrat errors) +/// +/// \param vm Target VM +/// +/// \return String containing a nice error message +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline string LastErrorString(HSQUIRRELVM vm) { + const SQChar* sqErr; + sq_getlasterror(vm); + if (sq_gettype(vm, -1) == OT_NULL) { + sq_pop(vm, 1); + return string(); + } + sq_tostring(vm, -1); + sq_getstring(vm, -1, &sqErr); + sq_pop(vm, 2); + return string(sqErr); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// A smart pointer that retains shared ownership of an object through a pointer (see std::shared_ptr) +/// +/// \tparam T Type of pointer +/// +/// \remarks +/// SharedPtr exists to automatically delete an object when all references to it are destroyed. +/// +/// \remarks +/// std::shared_ptr was not used because it is a C++11 feature. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class SharedPtr +{ + template + friend class SharedPtr; + + template + friend class WeakPtr; + +private: + + T* m_Ptr; + unsigned int* m_RefCount; + unsigned int* m_RefCountRefCount; + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a new SharedPtr + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SharedPtr() : + m_Ptr (NULL), + m_RefCount (NULL), + m_RefCountRefCount(NULL) + { + + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a new SharedPtr from an object allocated with the new operator + /// + /// \param ptr Should be the return value from a call to the new operator + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SharedPtr(T* ptr) : + m_Ptr (NULL), + m_RefCount (NULL), + m_RefCountRefCount(NULL) + { + Init(ptr); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a new SharedPtr from an object allocated with the new operator + /// + /// \param ptr Should be the return value from a call to the new operator + /// + /// \tparam U Type of pointer (usually doesnt need to be defined explicitly) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr(U* ptr) : + m_Ptr (NULL), + m_RefCount (NULL), + m_RefCountRefCount(NULL) + { + Init(ptr); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param copy SharedPtr to copy + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SharedPtr(const SharedPtr& copy) + { + if (copy.Get() != NULL) + { + m_Ptr = copy.Get(); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCount += 1; + *m_RefCountRefCount += 1; + } + else + { + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param copy SharedPtr to copy + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr(const SharedPtr& copy) + { + if (copy.Get() != NULL) + { + m_Ptr = static_cast(copy.Get()); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCount += 1; + *m_RefCountRefCount += 1; + } + else + { + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param copy WeakPtr to copy + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr(const WeakPtr& copy) + { + if (copy.m_Ptr != NULL) + { + m_Ptr = static_cast(copy.m_Ptr); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCount += 1; + *m_RefCountRefCount += 1; + } + else + { + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructs the owned object if no more SharedPtr link to it + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~SharedPtr() + { + Reset(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assigns the SharedPtr + /// + /// \param copy SharedPtr to copy + /// + /// \return The SharedPtr itself + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SharedPtr& operator=(const SharedPtr& copy) + { + if (this != ©) + { + Reset(); + + if (copy.Get() != NULL) + { + m_Ptr = copy.Get(); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCount += 1; + *m_RefCountRefCount += 1; + } + } + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assigns the SharedPtr + /// + /// \param copy SharedPtr to copy + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + /// \return The SharedPtr itself + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + SharedPtr& operator=(const SharedPtr& copy) + { + Reset(); + + if (copy.Get() != NULL) + { + m_Ptr = static_cast(copy.Get()); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCount += 1; + *m_RefCountRefCount += 1; + } + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets up a new object to be managed by the SharedPtr + /// + /// \param ptr Should be the return value from a call to the new operator + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Init(T* ptr) + { + Reset(); + + m_Ptr = ptr; + + m_RefCount = new unsigned int; + *m_RefCount = 1; + + m_RefCountRefCount = new unsigned int; + *m_RefCountRefCount = 1; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets up a new object to be managed by the SharedPtr + /// + /// \param ptr Should be the return value from a call to the new operator + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + void Init(U* ptr) + { + Reset(); + + m_Ptr = static_cast(ptr); + + m_RefCount = new unsigned int; + *m_RefCount = 1; + + m_RefCountRefCount = new unsigned int; + *m_RefCountRefCount = 1; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Clears the owned object for this SharedPtr and deletes it if no more SharedPtr link to it + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Reset() + { + if (m_Ptr != NULL) + { + *m_RefCount -= 1; + *m_RefCountRefCount -= 1; + + if (*m_RefCount == 0) + { + delete m_Ptr; + } + + if (*m_RefCountRefCount == 0) + { + delete m_RefCount; + delete m_RefCountRefCount; + } + + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Checks if there is NOT an associated managed object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool operator!() const + { + return m_Ptr == NULL; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another SharedPtr + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + bool operator ==(const SharedPtr& right) const + { + return m_Ptr == right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another SharedPtr + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool operator ==(const SharedPtr& right) const + { + return m_Ptr == right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + bool friend operator ==(const SharedPtr& left, const U* right) + { + return left.m_Ptr == right; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool friend operator ==(const SharedPtr& left, const T* right) + { + return left.m_Ptr == right; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + bool friend operator ==(const U* left, const SharedPtr& right) + { + return left == right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool friend operator ==(const T* left, const SharedPtr& right) + { + return left == right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another SharedPtr + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + bool operator !=(const SharedPtr& right) const + { + return m_Ptr != right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another SharedPtr + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool operator !=(const SharedPtr& right) const + { + return m_Ptr != right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + bool friend operator !=(const SharedPtr& left, const U* right) + { + return left.m_Ptr != right; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool friend operator !=(const SharedPtr& left, const T* right) + { + return left.m_Ptr != right; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + bool friend operator !=(const U* left, const SharedPtr& right) + { + return left != right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Compares with another pointer + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool friend operator !=(const T* left, const SharedPtr& right) + { + return left != right.m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Dereferences pointer to the managed object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + T& operator*() const + { + assert(m_Ptr != NULL); // fails when dereferencing a null SharedPtr + return *m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Dereferences pointer to the managed object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + T* operator->() const + { + assert(m_Ptr != NULL); // fails when dereferencing a null SharedPtr + return m_Ptr; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the underlying pointer + /// + /// \return Pointer to the managed object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + T* Get() const + { + return m_Ptr; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// A smart pointer that retains a non-owning ("weak") reference to an object that is managed by SharedPtr (see std::weak_ptr) +/// +/// \tparam T Type of pointer +/// +/// \remarks +/// WeakPtr exists for when an object that may be deleted at any time needs to be accessed if it exists. +/// +/// \remarks +/// std::weak_ptr was not used because it is a C++11 feature. +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template +class WeakPtr +{ + template + friend class SharedPtr; + +private: + + T* m_Ptr; + unsigned int* m_RefCount; + unsigned int* m_RefCountRefCount; + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructs a new WeakPtr + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + WeakPtr() : + m_Ptr (NULL), + m_RefCount (NULL), + m_RefCountRefCount(NULL) + { + + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param copy WeakPtr to copy + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + WeakPtr(const WeakPtr& copy) + { + if (copy.m_Ptr != NULL) + { + m_Ptr = copy.m_Ptr; + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCountRefCount += 1; + } + else + { + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param copy WeakPtr to copy + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + WeakPtr(const WeakPtr& copy) + { + if (copy.m_Ptr != NULL) + { + m_Ptr = static_cast(copy.m_Ptr); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCountRefCount += 1; + } + else + { + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Copy constructor + /// + /// \param copy SharedPtr to copy + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + WeakPtr(const SharedPtr& copy) + { + if (copy.Get() != NULL) + { + m_Ptr = static_cast(copy.Get()); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCountRefCount += 1; + } + else + { + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructs the WeakPtr but has no influence on the object that was managed + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~WeakPtr() + { + Reset(); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assigns the WeakPtr + /// + /// \param copy WeakPtr to copy + /// + /// \return The WeakPtr itself + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + WeakPtr& operator=(const WeakPtr& copy) + { + if (this != ©) + { + Reset(); + + if (copy.m_Ptr != NULL) + { + m_Ptr = copy.m_Ptr; + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCountRefCount += 1; + } + } + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assigns the WeakPtr + /// + /// \param copy WeakPtr to copy + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + /// \return The WeakPtr itself + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + WeakPtr& operator=(const WeakPtr& copy) + { + Reset(); + + if (copy.m_Ptr != NULL) + { + m_Ptr = static_cast(copy.m_Ptr); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCountRefCount += 1; + } + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Assigns the WeakPtr + /// + /// \param copy SharedPtr to copy + /// + /// \tparam U Type of copy (usually doesnt need to be defined explicitly) + /// + /// \return The WeakPtr itself + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + WeakPtr& operator=(const SharedPtr& copy) + { + Reset(); + + if (copy.Get() != NULL) + { + m_Ptr = static_cast(copy.Get()); + m_RefCount = copy.m_RefCount; + m_RefCountRefCount = copy.m_RefCountRefCount; + + *m_RefCountRefCount += 1; + } + + return *this; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Checks whether the managed object exists + /// + /// \return True if the managed object does not exist, false otherwise + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Expired() const + { + return (m_Ptr == NULL || *m_RefCount == 0); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Creates a new SharedPtr that shares ownership of the managed object + /// + /// \return A SharedPtr which shares ownership of the managed object + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SharedPtr Lock() const + { + SharedPtr other; + if (m_Ptr != NULL) + { + other.m_Ptr = m_Ptr; + other.m_RefCount = m_RefCount; + other.m_RefCountRefCount = m_RefCountRefCount; + + *m_RefCount += 1; + *m_RefCountRefCount += 1; + } + return other; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Clears the associated object for this WeakPtr + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Reset() + { + if (m_Ptr != NULL) + { + *m_RefCountRefCount -= 1; + + if (*m_RefCountRefCount == 0) + { + delete m_RefCount; + delete m_RefCountRefCount; + } + + m_Ptr = NULL; + m_RefCount = NULL; + m_RefCountRefCount = NULL; + } + } +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @cond DEV +/// Used internally to get and manipulate the underlying type of variables - retrieved from cppreference.com +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template struct remove_const {typedef T type;}; +template struct remove_const {typedef T type;}; +template struct remove_volatile {typedef T type;}; +template struct remove_volatile {typedef T type;}; +template struct remove_cv {typedef typename remove_volatile::type>::type type;}; +template struct is_pointer_helper {static const bool value = false;}; +template struct is_pointer_helper {static const bool value = true;}; +template struct is_pointer_helper > {static const bool value = true;}; +template struct is_pointer_helper > {static const bool value = true;}; +template struct is_pointer : is_pointer_helper::type> {}; +template struct is_reference {static const bool value = false;}; +template struct is_reference {static const bool value = true;}; +/// @endcond + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratVM.h b/src/include/scripting/sqrat/sqratVM.h new file mode 100644 index 0000000000..4bacc24d47 --- /dev/null +++ b/src/include/scripting/sqrat/sqratVM.h @@ -0,0 +1,348 @@ +// +// wrapper for the Squirrel VM under Sqrat +// + +// +// Copyright (c) 2011 Alston Chen +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#if !defined(_SCRAT_VM_H_) +#define _SCRAT_VM_H_ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace Sqrat +{ + +#ifdef SQUNICODE +#define scvprintf vwprintf +#else +#define scvprintf vprintf +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Helper class that wraps a Squirrel virtual machine in a C++ API +/// +/// \remarks +/// This class is not currently thread-safe for the case of different VMs running in different threads (all others are) +/// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class SqratVM +{ +private: + + HSQUIRRELVM m_vm; + Sqrat::RootTable* m_rootTable; + Sqrat::Script* m_script; + Sqrat::string m_lastErrorMsg; + + static void s_addVM(HSQUIRRELVM vm, SqratVM* sqratvm) + { + // TODO for user: use mutex to lock ms_sqratVMs if necessary for your uses + ms_sqratVMs().insert(std::make_pair(vm, sqratvm)); + } + + static void s_deleteVM(HSQUIRRELVM vm) + { + // TODO for user: use mutex to lock ms_sqratVMs if necessary for your uses + ms_sqratVMs().erase(vm); + } + + static SqratVM* s_getVM(HSQUIRRELVM vm) + { + // TODO for user: use mutex to lock ms_sqratVMs if necessary for your uses + return ms_sqratVMs()[vm]; + } + +private: + + static SQRAT_API unordered_map::type& ms_sqratVMs(); + + static void printFunc(HSQUIRRELVM /*v*/, const SQChar *s, ...) + { + va_list vl; + va_start(vl, s); + scvprintf(s, vl); + va_end(vl); + } + + static SQInteger runtimeErrorHandler(HSQUIRRELVM v) + { + const SQChar *sErr = 0; + if(sq_gettop(v) >= 1) + { + Sqrat::string& errStr = s_getVM(v)->m_lastErrorMsg; + if(SQ_SUCCEEDED(sq_getstring(v, 2, &sErr))) + { + errStr = sErr; + } + else + { + errStr = _SC("an unknown runtime error has occured"); + } + } + return 0; + } + + static void compilerErrorHandler(HSQUIRRELVM v, + const SQChar* desc, + const SQChar* source, + SQInteger line, + SQInteger column) + { + SQChar buf[512]; + scsprintf(buf, _SC("%s:%d:%d: %s"), source, (int) line, (int) column, desc); + buf[sizeof(buf) - 1] = 0; + s_getVM(v)->m_lastErrorMsg = buf; + } + +public: + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Enumeration representing the different types of errors that may occur within a SqratVM + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + enum ERROR_STATE + { + SQRAT_NO_ERROR, ///< For when no error has occurred + SQRAT_COMPILE_ERROR, ///< For when a script compiling error has occurred + SQRAT_RUNTIME_ERROR ///< For when a script running error has occurred + }; + + static const unsigned char LIB_IO = 0x01; ///< Input/Output library + static const unsigned char LIB_BLOB = 0x02; ///< Blob library + static const unsigned char LIB_MATH = 0x04; ///< Math library + static const unsigned char LIB_SYST = 0x08; ///< System library + static const unsigned char LIB_STR = 0x10; ///< String library + static const unsigned char LIB_ALL = LIB_IO | LIB_BLOB | LIB_MATH | LIB_SYST | LIB_STR; ///< All libraries + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Default constructor + /// + /// \param initialStackSize Initial size of the execution stack (if the stack is too small it will automatically grow) + /// \param libsToLoad Specifies what standard Squirrel libraries should be loaded + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SqratVM(int initialStackSize = 1024, unsigned char libsToLoad = LIB_ALL): m_vm(sq_open(initialStackSize)) + , m_rootTable(new Sqrat::RootTable(m_vm)) + , m_script(new Sqrat::Script(m_vm)) + , m_lastErrorMsg() + { + s_addVM(m_vm, this); + //register std libs + sq_pushroottable(m_vm); + if (libsToLoad & LIB_IO) + sqstd_register_iolib(m_vm); + if (libsToLoad & LIB_BLOB) + sqstd_register_bloblib(m_vm); + if (libsToLoad & LIB_MATH) + sqstd_register_mathlib(m_vm); + if (libsToLoad & LIB_SYST) + sqstd_register_systemlib(m_vm); + if (libsToLoad & LIB_STR) + sqstd_register_stringlib(m_vm); + sq_pop(m_vm, 1); + SetPrintFunc(printFunc, printFunc); + SetErrorHandler(runtimeErrorHandler, compilerErrorHandler); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Destructor + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~SqratVM() + { + s_deleteVM(m_vm); + delete m_script; + delete m_rootTable; + sq_close(m_vm); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the underlying Squirrel VM + /// + /// \return Underlying Squirrel VM + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + HSQUIRRELVM GetVM() + { + return m_vm; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the root table for this VM + /// + /// \return RootTable for the VM + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Sqrat::RootTable& GetRootTable() + { + return *m_rootTable; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the associated Script for this VM + /// + /// \return Script for the VM + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Sqrat::Script& GetScript() + { + return *m_script; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Gets the error message for the most recent Squirrel error with the VM + /// + /// \return String containing a nice error message + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Sqrat::string GetLastErrorMsg() + { + return m_lastErrorMsg; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Overwrites the most recent Squirrel error for this VM + /// + /// \param str A nice error message + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetLastErrorMsg(const Sqrat::string& str) + { + m_lastErrorMsg = str; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets the print function of the virtual machine (a default one is set in the constructor) + /// + /// \param printFunc A pointer to the print func or NULL to disable the output + /// \param errFunc A pointer to the error func or NULL to disable the output + /// + /// \remarks + /// The print function is used by the built-in Squirrel print function to output text. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPrintFunc(SQPRINTFUNCTION printFunc, SQPRINTFUNCTION errFunc) + { + sq_setprintfunc(m_vm, printFunc, errFunc); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Sets the Squirrel error handlers (both are set to defaults in the constructor) + /// + /// \param runErr A pointer to the runtime error handler func + /// \param comErr A pointer to the compile error handler func + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetErrorHandler(SQFUNCTION runErr, SQCOMPILERERROR comErr) + { + sq_newclosure(m_vm, runErr, 0); + sq_seterrorhandler(m_vm); + sq_setcompilererrorhandler(m_vm, comErr); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs a string containing a Squirrel script + /// + /// \param str String containing a Squirrel script + /// + /// \return An ERROR_STATE representing what happened + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ERROR_STATE DoString(const Sqrat::string& str) + { + Sqrat::string msg; + m_lastErrorMsg.clear(); + if(!m_script->CompileString(str, msg)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SQRAT_COMPILE_ERROR; + } + if(!m_script->Run(msg)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SQRAT_RUNTIME_ERROR; + } + return SQRAT_NO_ERROR; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Runs a file containing a Squirrel script + /// + /// \param file File path containing a Squirrel script + /// + /// \return An ERROR_STATE representing what happened + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ERROR_STATE DoFile(const Sqrat::string& file) + { + Sqrat::string msg; + m_lastErrorMsg.clear(); + if(!m_script->CompileFile(file, msg)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SQRAT_COMPILE_ERROR; + } + if(!m_script->Run(msg)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SQRAT_RUNTIME_ERROR; + } + return SQRAT_NO_ERROR; + } + +}; + +#if !defined(SCRAT_IMPORT) +inline unordered_map::type& SqratVM::ms_sqratVMs() { + static unordered_map::type ms; + return ms; +} +#endif + +} + +#endif diff --git a/src/include/scripting/sqrat/sqratext_Ref.h b/src/include/scripting/sqrat/sqratext_Ref.h new file mode 100644 index 0000000000..4809bb2226 --- /dev/null +++ b/src/include/scripting/sqrat/sqratext_Ref.h @@ -0,0 +1,47 @@ + + +#ifndef __SQRATEXT_REF_H +#define __SQRATEXT_REF_H + + +namespace Sqrat { + template + class Ref { + T* _ptr; + T instance; + public: + Ref() { _ptr = &instance; }//new T; } + + T *operator ->() { return _ptr; } + const T *operator ->() const { return _ptr; } + operator T*() { return _ptr; } + + //Copies override "our" instance for another + Ref &operator =(Ref *rhs) { _ptr = rhs->_ptr; return *this; } + Ref &operator =(T *rhs) { _ptr = rhs; return *this; } + }; + + template + struct Var > { + T *value; + Var(HSQUIRRELVM vm, SQInteger idx) { + value = ClassType::GetInstance(vm, idx); + } + static void push(HSQUIRRELVM vm, Ref &value) { + ClassType::PushInstance(vm, &(*value)); + } + }; + + template + struct Var&> { + T *value; + Var(HSQUIRRELVM vm, SQInteger idx) { + value = ClassType::GetInstance(vm, idx); + } + static void push(HSQUIRRELVM vm, Ref& value) { + ClassType::PushInstance(vm, &(*value)); + } + }; +}; + +#endif //__SQRATEXT_REF_H \ No newline at end of file From 63d2f5dfda9d1bce673f065e8d674b047d5826df Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 16:34:17 +0200 Subject: [PATCH 04/16] [NOT COMPILE] Add a c++ wrapper around the squirrel c-api vm to make it possible to compile files and catch errors from sqrat and squirrel. There is also a api for sand boxing a vm for temporary handling. --- .../scripting/bindings/sc_binding_util.h | 43 ++ src/include/scripting/bindings/sc_cb_vm.h | 423 ++++++++++++ src/sdk/scripting/bindings/sc_cb_vm.cpp | 621 ++++++++++++++++++ 3 files changed, 1087 insertions(+) create mode 100644 src/include/scripting/bindings/sc_binding_util.h create mode 100644 src/include/scripting/bindings/sc_cb_vm.h create mode 100644 src/sdk/scripting/bindings/sc_cb_vm.cpp diff --git a/src/include/scripting/bindings/sc_binding_util.h b/src/include/scripting/bindings/sc_binding_util.h new file mode 100644 index 0000000000..d328b7787e --- /dev/null +++ b/src/include/scripting/bindings/sc_binding_util.h @@ -0,0 +1,43 @@ +#ifndef SC_BINDING_UTIL_H +#define SC_BINDING_UTIL_H + + +// helper macros to bind constants +#define BIND_INT_CONSTANT(a) Sqrat::ConstTable(vm).Const(_SC(#a), a) +#define BIND_INT_CONSTANT_NAMED(a,n) Sqrat::ConstTable(vm).Const(_SC(n), a) +// NOTE (bluehazzard#1#): This can break the API, but the old API was wrong, because constants should be constants and don't get modified... +#define BIND_WXSTR_CONSTANT_NAMED(a,n) Sqrat::ConstTable(vm).Const(_SC(n),a.ToUTF8()) + +#define SC_RETURN_FAILED -1 +#define SC_RETURN_OK -0 +#define SC_RETURN_VALUE 1 +#include + +namespace ScriptBindings +{ + + +template int GetValueFromTable(Sqrat::Table table,const SQChar* name,U& output,bool exc = false) +{ + if(!table.HasKey(name)) + return -1; + + Sqrat::SharedPtr ptr = table.GetValue(name); + if(ptr == nullptr) + { + if(exc) + { + CBScriptException ex(wxString::Format(_("Could not Find Value with name: %s"),name) + wxString(_(" from table "))); //+ wxString::FromUTF8(table.getName())) + throw ex; + } + + return -2; + } + + + output = *ptr.Get(); + return 0; +} + +} +#endif // SC_BINDING_UTIL_H diff --git a/src/include/scripting/bindings/sc_cb_vm.h b/src/include/scripting/bindings/sc_cb_vm.h new file mode 100644 index 0000000000..abd07f31ad --- /dev/null +++ b/src/include/scripting/bindings/sc_cb_vm.h @@ -0,0 +1,423 @@ + +#ifndef SC_CB_VM_H +#define SC_CB_VM_H + +#include +#include +#include "manager.h" +#include +#include + +namespace ScriptBindings +{ + +class CBsquirrelVMManager; +class CBSquirrelThread; + + +/** \brief A helper class to manage Exceptions thrown from the script environment + */ +class CBScriptException //: public Sqrat::Exception +{ +public: + + /** \brief Public constructor to use it with wxWidgets Strings + * + * \param msg wxString The Message + * + */ + CBScriptException(wxString msg); + ~CBScriptException(); + + /** \brief Get the message as a wxString + * + * \return wxString The error message transported with this exception + * + */ + wxString Message(); + +private: + wxString m_message; +}; + +/** \brief Flags for standard libraries to load. + * + * This flags can be used with \ref CBsquirrelVM::CBsquirrelVM, \ref CBsquirrelVM::LoadLibrary and \ref CBsquirrelVM::GetLoadedLibraries + * \defgroup vm_library_flags VM Library Flags + * \relates CBsquirrelVM + */ + /** \addtogroup vm_library_flags + @{ + */ +const uint32_t VM_LIB_ALL = 0xFFFFFFFF; /**< Load all std libraries */ +const uint32_t VM_LIB_IO = 0x00000001; /**< Load the file I/O library */ +const uint32_t VM_LIB_BLOB = 0x00000002; /**< Load the blob library*/ +const uint32_t VM_LIB_MATH = 0x00000004; /**< Load the Math library (sin, cos, etc...) */ +const uint32_t VM_LIB_SYST = 0x00000008; /**< Load the system library (clock(), date(), etc...) */ +const uint32_t VM_LIB_STR = 0x00000010; /**< Load the string library */ +/**@}*/ + + + +/** \brief Returns the success/fail of the run/compile + * + * This are the return values from \ref doString and \ref doFile +*/ + enum SC_ERROR_STATE + { + SC_NO_ERROR, /**< No error occurred */ + SC_COMPILE_ERROR, /**< A compilation error occurred. Call \ref getLastErrorMsg() to get a detailed description of the error: file and line */ + SC_RUNTIME_ERROR /**< A runtime error occurred. Call \ref getLastErrorMsg() to get a detailed description of the error */ + }; + +/** \brief A class to manage the squirrel VM. + * + * Based on SqratVM + */ +class CBsquirrelVM +{ + +private: + static void compilerErrorHandler(HSQUIRRELVM v,const SQChar* desc,const SQChar* source,SQInteger line,SQInteger column); + static SQInteger runtimeErrorHandler(HSQUIRRELVM v); + + +public: + + + + /** \brief Initialize a squirrel VM and load the specified standard libraries. + * + * This VM catches compile-time and run-time errors. They can be retrieved with GetLastError() + * \param[in] int initialStackSize = 1024 + * The size of the initial stack + * \param[in] const uint32_t library_to_load = VM_LIB_ALL + * The libraries to be loaded. + * + * Libraries can be combined with | operator. Example: + * \code CBsquirrelVM(1024,VM_LIB_SYST|VM_LIB_MATH); \endcode \n + * For a list with flags see \ref vm_library_flags + */ + CBsquirrelVM(int initialStackSize = 1024,const uint32_t library_to_load = VM_LIB_ALL); + CBsquirrelVM(HSQUIRRELVM vm, bool close = true); + ~CBsquirrelVM(); + + /** \brief Shuts down the vm + * + * Removes the vm from the internal list and closes it in squirrel. + * \return void + * + */ + void Shutdown(); + + CBSquirrelThread* CreateThread(); + + /** \brief Loads additional std libraries + * \param[in] library_to_load const uint32_t + * Libraries to load. Combined with | \n For a list with flags see \ref vm_library_flags + */ + void LoadLibrary(const uint32_t library_to_load); + + /** \brief Returns all loaded libraries as Flags. + * For a list with flags see \ref vm_library_flags + * \return uint32_t Loaded libraries + */ + uint32_t GetLoadedLibraries() {return m_lib_loaded;}; + + /** \brief Set the compiler and runtime error handler functions for this vm + * \param[in] runErr SQFUNCTION The runtime error handler Function with the signature: SQInteger (*SQFUNCTION)(HSQUIRRELVM); + * \param[in] comErr SQCOMPILERERROR The compile error handler Function with the signature: typedef void (*SQCOMPILERERROR)(HSQUIRRELVM v,const SQChar * desc,const SQChar *source,SQInteger line,SQInteger column); + */ + void SetErrorHandler(SQFUNCTION runErr, SQCOMPILERERROR comErr); + + /** \brief Set the compiler and runtime error handler functions for this vm + * \param[in] printFunc SQPRINTFUNCTION The print() handler Function with the prototype: printfunc(HSQUIRRELVM v,const SQChar *s,...) + * \param[in] errFunc SQPRINTFUNCTION The error() handler Function with the prototype: printfunc(HSQUIRRELVM v,const SQChar *s,...) + */ + void SetPrintFunc(SQPRINTFUNCTION printFunc, SQPRINTFUNCTION errFunc); + + /** \brief Get the compiler and runtime error handler functions for this vm + * \param[out] printFunc SQPRINTFUNCTION The print() handler Function with the prototype: printfunc(HSQUIRRELVM v,const SQChar *s,...) + * \param[out] errFunc SQPRINTFUNCTION The error() handler Function with the prototype: printfunc(HSQUIRRELVM v,const SQChar *s,...) + */ + void GetPrintFunc(SQPRINTFUNCTION& printFunc, SQPRINTFUNCTION& errFunc); + + /** \brief Returns the HSQUIRRELVM object managed by this CBsquirrelVM + * \return HSQUIRRELVM The vm Object + */ + HSQUIRRELVM GetSqVM() { return m_vm; }; + + /** \brief Gets the root table + * \return Sqrat::RootTable& Reference to the rootTable from this vm. + */ + Sqrat::RootTable& GetRootTable() { return *m_rootTable; }; + + /** \brief Gets the current running script + * \return Sqrat::Script& Reference to the compiled/running script + */ + Sqrat::Script& GetScript() { return *m_script; }; + + /** \brief Gets the last error + * + * The error is returned in an readable format. It is not differenced between compiler or tuntime error + * \return wxString The error string + */ + wxString getLastErrorMsg(); + + /** \brief Reports if a error occurred on this vm + * + * The detailed error can be retrieved with getLastErrorMsg() + * \return bool true if a error occurred + */ + bool HasError(); + + /** \brief Sets the last error + * \param str const Sqrat::string& The error message + */ + void setLastErrorMsg(const Sqrat::string& str) { m_lastErrorMsg = str; }; + + /** \name Compiles and runs an string + */ + /** @{ */ + /** + * \param[in] str Sqrat::string& A sqrat string to compile and run + * \return See \ref ERROR_STATE for the return values + */ + SC_ERROR_STATE doString(const Sqrat::string& str,const Sqrat::string& name); + /** + * \param[in] str wxString A wxWidgets string to compile and run + * \return See \ref ERROR_STATE for the return values + */ + SC_ERROR_STATE doString(const wxString str,const wxString name); + /** @} */ + + /** \brief Compiles and runs a file + * \param file const Sqrat::string& Path to a file that has to be compiled and run + * \return ERROR_STATE See \ref ERROR_STATE for the return values + */ + SC_ERROR_STATE doFile(const Sqrat::string& file); + SC_ERROR_STATE doFile(const wxString& file); + + /** \brief Set this vm as the default vm used with sqrat + * + * Warning the old vm is lost. + */ + void SetMeDefault(); + +private: + HSQUIRRELVM m_vm; + Sqrat::RootTable* m_rootTable; + Sqrat::Script* m_script; + Sqrat::string m_lastErrorMsg; + uint32_t m_lib_loaded; + bool m_shutdwon; + bool m_close; +}; + +/** \brief A hash map to save the different vms (not for public use) + */ + +WX_DECLARE_HASH_MAP(HSQUIRRELVM, + CBsquirrelVM*, + wxPointerHash, + wxPointerEqual, + VMHashMap); + + + +class CBSquirrelThread +{ +public: + CBSquirrelThread(HSQUIRRELVM parent); + ~CBSquirrelThread(); + + + SC_ERROR_STATE doString(const wxString script,const wxString name); + + CBsquirrelVM* GetVM() {return m_vm;}; + + +private: + + bool create_thread(); + bool destroy_thread(); + + CBsquirrelVM* m_vm; + + HSQUIRRELVM m_parent_vm; + //HSQUIRRELVM m_thread; + HSQOBJECT m_thread_obj; + +}; + +/** \brief A helper class to Manage different squirrel VMs + * + * This is almost only needed for the Error handler and will eventually removed... + */ +class CBsquirrelVMManager : public Mgr +{ + friend class Mgr; + wxCriticalSection cs; + public: + + /** \brief Add a vm to Manage + * \param[in] vm CBsquirrelVM* The vm which has to be managed + */ + void AddVM(CBsquirrelVM* vm); + + /** \brief Get the CBsquirrelVM from a HSQUIRRELVM object + * \param[in] vm HSQUIRRELVM The vm from which the CBsquirrelVM is needed + * \return CBsquirrelVM* A pointer to the CBsquirrelVM object. nullptr if not found + */ + CBsquirrelVM* GetVM(HSQUIRRELVM vm); + + + /** \name Remove a VM from the list + */ + /** @{ */ + /** + * \param[in] vm CBsquirrelVM* A pointer to a CBsquirrelVM that will be removed + */ + void RemoveVM(CBsquirrelVM* vm); + /** + * \param[in] vm HSQUIRRELVM A pointer to a Squirrelvm that will be removed + */ + void RemoveVM(HSQUIRRELVM vm); + /** @} */ + + protected: + + + private: + CBsquirrelVMManager(); + ~CBsquirrelVMManager(); + CBsquirrelVMManager(cb_unused const CBsquirrelVMManager& rhs); // prevent copy construction + VMHashMap m_map; + +}; + + + + +/** \brief A class to manage the VM stack easily + */ +class StackHandler +{ +public: + /** \brief Initialize the StackHandler with a SquirrelVM + * \param vm HSQUIRRELVM Squirrel VM from which the Stack get handled + */ + StackHandler(HSQUIRRELVM vm); + ~StackHandler(); + + /** \brief Get the parameter count from the stack + * \return int Returns the Number of parameters on the stack + */ + int GetParamCount(); + + /** \brief Get the variable type from stack on position pos + * \param pos int + * \return SQObjectType The type of the object + */ + SQObjectType GetType(int pos); + + /** \brief Get the object from stack + * \param pos int + * \return template RETURN_VALUE + */ + template RETURN_VALUE GetValue(int pos) + { + // Clear all old errors + Sqrat::Error::Clear(m_vm); + + Sqrat::Var val(m_vm,pos); + if(Sqrat::Error::Occurred(m_vm)) + throw CBScriptException(_("Script Error: GetValue<> failed\n")); + return val.value; + } + + /** \brief Get an instance of an object from stack + * \param pos int + * \return INSTANCE_TYPE* + */ + template INSTANCE_TYPE* GetInstance(int pos) + { + // Clear all old errors + Sqrat::Error::Clear(m_vm); + INSTANCE_TYPE* ret = Sqrat::ClassType::GetInstance(m_vm, pos); + if(Sqrat::Error::Occurred(m_vm)) + throw CBScriptException(_("Script Error: GetInstance<> failed\n")); + return ret; + } + + /** \brief Push a value to the stack + * + * \param value VALUE_TYPE The Value + * \return template void + * + * For example + * \code + * sa.PushValue(55); + * \endcode + */ + template void PushValue(VALUE_TYPE value) + { + Sqrat::Var::push(m_vm, value); + } + + template void PushInstanceCopy(VALUE_TYPE value) + { + Sqrat::ClassType::PushInstanceCopy(m_vm, value); + } + + template void PushInstance(VALUE_TYPE* value) + { + Sqrat::ClassType::PushInstance(m_vm, value); + } + + /** \brief Throws an squirrel error + * \param error SQChar a error description + * \return SQInteger + */ + SQInteger ThrowError(const SQChar* error); + + /** \brief Throws an squirrel error + * \param error SQChar a error description + * \return SQInteger + */ + SQInteger ThrowError(const wxString error); + + /** \brief Returns the error message of the last occurred error or an empty string + * + * \param del bool + * + * This function deletes the error from the Sqrat::Error queue if del is true. other vise it will be kept in the queue + * \return wxString Error message of the string or an empty string if no error occurred + */ + wxString GetError(bool del = true); + + /** \brief Returns true if a error occurred + * + * \return bool True if a error occurred + */ + bool HasError(); + + /** \brief Returns a backtrace of the current call stack + * + * \return wxString + * + */ + wxString CreateStackInfo(); + wxString CreateFunctionLocalInfo(int stack_lvl); + + HSQUIRRELVM GetVM() {return m_vm;}; + +protected: +private: + HSQUIRRELVM m_vm; + +}; + +} + +#endif // SC_CB_VM_H diff --git a/src/sdk/scripting/bindings/sc_cb_vm.cpp b/src/sdk/scripting/bindings/sc_cb_vm.cpp new file mode 100644 index 0000000000..b044206e1c --- /dev/null +++ b/src/sdk/scripting/bindings/sc_cb_vm.cpp @@ -0,0 +1,621 @@ + +#include +#include +#include +#include +#include + + +#include + +#include +#include +#include +#include +#include + + + +namespace ScriptBindings +{ + +CBScriptException::CBScriptException(wxString msg) : m_message(msg) +{ + +} + +CBScriptException::~CBScriptException() +{ + +} + +wxString CBScriptException::Message() +{ + return m_message; +} + + +template<> CBsquirrelVMManager* Mgr::instance = nullptr; +template<> bool Mgr::isShutdown = false; + +CBsquirrelVMManager::CBsquirrelVMManager() +{ + +} + +CBsquirrelVMManager::~CBsquirrelVMManager() +{ + +} + +void CBsquirrelVMManager::AddVM(CBsquirrelVM* vm) +{ + wxCriticalSectionLocker locker(cs); + m_map[vm->GetSqVM()] = vm; +} + +CBsquirrelVM* CBsquirrelVMManager::GetVM(HSQUIRRELVM vm) +{ + wxCriticalSectionLocker locker(cs); + if(m_map.find(vm) == m_map.end()) + { + // VM not found... + // Should we throw an exception? + return nullptr; + } + return m_map[vm]; +} + +void CBsquirrelVMManager::RemoveVM(CBsquirrelVM* vm) +{ + wxCriticalSectionLocker locker(cs); + VMHashMap::iterator itr = m_map.begin(); + for(;itr != m_map.end();itr++) + { + if(itr->second == vm) + { + m_map.erase(itr); + } + } +} + +void CBsquirrelVMManager::RemoveVM(HSQUIRRELVM vm) +{ + wxCriticalSectionLocker locker(cs); + m_map.erase(vm); +} + +CBsquirrelVM::CBsquirrelVM(HSQUIRRELVM vm,bool close) : m_vm(vm) + , m_rootTable(new Sqrat::RootTable(m_vm)) + , m_script(new Sqrat::Script(m_vm)) + , m_lastErrorMsg() + , m_shutdwon(false) + , m_close(close) +{ + CBsquirrelVMManager::Get()->AddVM(this); + m_lib_loaded = 0; + + sq_enabledebuginfo(m_vm,true); + + SetErrorHandler(runtimeErrorHandler,compilerErrorHandler); + + m_lastErrorMsg.clear(); +} + +CBsquirrelVM::CBsquirrelVM(int initialStackSize,const uint32_t library_to_load) : m_vm(sq_open(initialStackSize)) + , m_rootTable(new Sqrat::RootTable(m_vm)) + , m_script(new Sqrat::Script(m_vm)) + , m_lastErrorMsg() + , m_shutdwon(false) +{ + //Register VM in the Manager + CBsquirrelVMManager::Get()->AddVM(this); + + //Register std libs + sq_pushroottable(m_vm); // The register functions aspects a Table on the stack + + if(library_to_load & VM_LIB_IO) + sqstd_register_iolib(m_vm); + if(library_to_load & VM_LIB_BLOB) + sqstd_register_bloblib(m_vm); + if(library_to_load & VM_LIB_MATH) + sqstd_register_mathlib(m_vm); + if(library_to_load & VM_LIB_SYST) + sqstd_register_systemlib(m_vm); + if(library_to_load & VM_LIB_STR) + sqstd_register_stringlib(m_vm); + sq_pop(m_vm, 1); // Pop the root table + + m_lib_loaded = library_to_load; + + sq_enabledebuginfo(m_vm,true); + + SetErrorHandler(runtimeErrorHandler,compilerErrorHandler); + + m_lastErrorMsg.clear(); + + // FIXME (bluehazzard#1#): temporary set me as default vm, if CB supports multi vm this should be removed!!!! + Sqrat::DefaultVM::Set(m_vm); +} + +CBsquirrelVM::~CBsquirrelVM() +{ + if(!m_shutdwon) + Shutdown(); +} + +void CBsquirrelVM::Shutdown() +{ + CBsquirrelVMManager::Get()->RemoveVM(m_vm); // Remove this vm from the managed list + delete m_script; + delete m_rootTable; + if(m_close) + sq_close(m_vm); + + m_shutdwon = true; +} + +CBSquirrelThread* CBsquirrelVM::CreateThread() +{ + try + { + CBSquirrelThread* ret = new CBSquirrelThread(this->GetSqVM()); + return ret; + } catch(CBScriptException &e) + { + Manager::Get()->GetLogManager()->LogError(_("CBsquirrelVM::CreateThread(): ")+ e.Message()); + return nullptr; + } + return nullptr; +} + +void CBsquirrelVM::LoadLibrary(const uint32_t library_to_load) +{ + sq_pushroottable(m_vm); // The register functions aspects a Table on the stack + if(library_to_load & VM_LIB_IO) + sqstd_register_iolib(m_vm); + if(library_to_load & VM_LIB_BLOB) + sqstd_register_bloblib(m_vm); + if(library_to_load & VM_LIB_MATH) + sqstd_register_mathlib(m_vm); + if(library_to_load & VM_LIB_SYST) + sqstd_register_systemlib(m_vm); + if(library_to_load & VM_LIB_STR) + sqstd_register_stringlib(m_vm); + sq_pop(m_vm, 1); // Pop the root table + + m_lib_loaded |= library_to_load; +} + +SQInteger CBsquirrelVM::runtimeErrorHandler(HSQUIRRELVM v) +{ + CBsquirrelVM* sq_vm = CBsquirrelVMManager::Get()->GetVM(v); + StackHandler sa(v); + if(sq_vm == NULL) + { + // Something funny happened. + Manager::Get()->GetLogManager()->LogError(_T("Could not find squirrel VM in runtimeErrorHandler! This is a Program Error. Please report it to the developers!")); + return SQ_ERROR; + } + const SQChar *sErr = 0; + wxString ErrorMessage(_T("Squirrel Runtime Error:\n")); + ErrorMessage.Append(sa.CreateStackInfo()); + ErrorMessage.Append(_T("\nError:\n")); + if(sq_gettop(v) >= 1) + { + if(SQ_SUCCEEDED(sq_getstring(v, 2, &sErr))) + { + ErrorMessage.Append(wxString::FromUTF8(sErr)); + } + else + { + ErrorMessage.Append(_T("An Unknown RuntimeError Occurred.")); + } + } + // Append local variables of the last function + ErrorMessage.Append(_T("\n\nLocal Variables:\n")); + ErrorMessage.Append(sa.CreateFunctionLocalInfo(1)); + + sq_vm->m_lastErrorMsg = ErrorMessage.ToUTF8(); + return SQ_ERROR; +} + +// Default Error Handler +void CBsquirrelVM::compilerErrorHandler(HSQUIRRELVM v, + const SQChar* desc, + const SQChar* source, + SQInteger line, + SQInteger column) +{ + int buffer_size = 128; + SQChar *tmp_buffer; + for(;;buffer_size*=2) + { + tmp_buffer = new SQChar [buffer_size]; + int retvalue = snprintf(tmp_buffer,buffer_size, _SC("\nSource: %s\nline: %d\ncolumn:%d\n%s"), source, (int) line, (int) column, desc); + if(retvalue < buffer_size) + { + // Buffersize was large enough + CBsquirrelVM* sq_vm = CBsquirrelVMManager::Get()->GetVM(v); + if(sq_vm == NULL) + { + // Something funny happened. + // In reality this shouldn't happen never... + Manager::Get()->GetLogManager()->LogError(_("Could not find squirrel VM in compilerErrorHandler! This is a Program Error. Please report it to the developers!")); + return; + } + sq_vm->m_lastErrorMsg = tmp_buffer; + + delete[] tmp_buffer; + break; + } + // Buffer size was not enough + delete[] tmp_buffer; + } +} + +void CBsquirrelVM::SetPrintFunc(SQPRINTFUNCTION printFunc, SQPRINTFUNCTION errFunc) +{ + sq_setprintfunc(m_vm, printFunc, errFunc); +} + +void CBsquirrelVM::GetPrintFunc(SQPRINTFUNCTION& printFunc, SQPRINTFUNCTION& errFunc) +{ + printFunc = sq_getprintfunc(m_vm); + errFunc = sq_geterrorfunc(m_vm); +} + +void CBsquirrelVM::SetErrorHandler(SQFUNCTION runErr, SQCOMPILERERROR comErr) +{ + sq_newclosure(m_vm, runErr, 0); + sq_seterrorhandler(m_vm); + sq_setcompilererrorhandler(m_vm, comErr); +} + +SC_ERROR_STATE CBsquirrelVM::doString(const Sqrat::string& str,const Sqrat::string& name) +{ + Sqrat::string msg; + m_lastErrorMsg.clear(); + if(!m_script->CompileString(str, msg,name)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SC_COMPILE_ERROR; + } + if(!m_script->Run(msg)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SC_RUNTIME_ERROR; + } + return SC_NO_ERROR; +} + +SC_ERROR_STATE CBsquirrelVM::doFile(const wxString& file) +{ + return doFile(Sqrat::string(file.mb_str())); +} + +SC_ERROR_STATE CBsquirrelVM::doFile(const Sqrat::string& file) +{ + Sqrat::string msg; + m_lastErrorMsg.clear(); + if(!m_script->CompileFile(file, msg)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SC_COMPILE_ERROR; + } + if(!m_script->Run(msg)) + { + if(m_lastErrorMsg.empty()) + { + m_lastErrorMsg = msg; + } + return SC_RUNTIME_ERROR; + } + return SC_NO_ERROR; +} + + +SC_ERROR_STATE CBsquirrelVM::doString(const wxString str, const wxString name) +{ + return doString(Sqrat::string(str.ToUTF8()),Sqrat::string(name.ToUTF8())); +} + +void CBsquirrelVM::SetMeDefault() +{ + if(m_vm == nullptr) + cbThrow(_("Cant set nullptr as default vm")); + Sqrat::DefaultVM::Set(m_vm); +} + +wxString CBsquirrelVM::getLastErrorMsg() +{ + wxString ErrorMessage; + ErrorMessage.Append(wxString(m_lastErrorMsg.c_str(),wxConvUTF8)); + m_lastErrorMsg.clear(); + + if(Sqrat::Error::Occurred(m_vm)) + { + ErrorMessage.Append(_("\nSqrat Error:\n")); + ErrorMessage.Append(wxString::FromUTF8(Sqrat::Error::Message(m_vm).c_str())); + Sqrat::Error::Clear(m_vm); + } + return ErrorMessage; +}; + +bool CBsquirrelVM::HasError() +{ + if(!m_lastErrorMsg.empty() || Sqrat::Error::Occurred(m_vm)) + return true; + else + return false; +} + + +/******************************************************************/ +/* CBSquirrelThread */ +/******************************************************************/ + +CBSquirrelThread::CBSquirrelThread(HSQUIRRELVM vm) : m_parent_vm(vm) +{ + create_thread(); +} + +CBSquirrelThread::~CBSquirrelThread() +{ + destroy_thread(); +} + +bool CBSquirrelThread::create_thread() +{ + if(m_parent_vm == nullptr) + { + throw CBScriptException(_("CBSquirrelThread::create_thread(): m_parent_vm == nullptr")); + } + + HSQUIRRELVM thread = sq_newthread(m_parent_vm,1024); + + if(thread == nullptr) + return false; + + sq_resetobject(&m_thread_obj); + if(SQ_FAILED(sq_getstackobj(m_parent_vm,-1,&m_thread_obj))) + { + throw CBScriptException(_("CBSquirrelThread::create_thread(): SQ_FAILED(sq_getstackobj(m_parent_vm,-1,&thread))")); + } + else + { + sq_addref(m_parent_vm,&m_thread_obj); + sq_pop(m_parent_vm,1); + } + + // Create a isolated vm, with its own environment + HSQOBJECT environment; + sq_resetobject(&environment); + sq_newtable(thread); + + // store the table in environment object + if(sq_getstackobj(thread, -1, &environment) < 0) + { + throw CBScriptException(_("CBSquirrelThread::create_thread(): if(sq_getstackobj(thread, -1, &environment)<0)")); + } + + //increment the ref counter of the object + sq_addref(thread, &environment); + sq_pop(thread, 1); + + // set old roottable as delegate of environment + sq_pushobject(thread, environment); + sq_pushroottable(thread); + sq_setdelegate(thread, -2); + sq_pop(thread, 1); + + // set environment as new roottable + // if we want to isolate the enviroment even more, we should overwrite the _set metamethod + sq_pushobject(thread, environment); + sq_setroottable(thread); + + sq_release(thread, &environment); + + m_vm = new CBsquirrelVM(thread,false); + + return true; +} + +bool CBSquirrelThread::destroy_thread() +{ + if(m_vm) + { + m_vm->Shutdown(); + delete m_vm; + m_vm = nullptr; + } + + // We close the VM in m_vm->Shutdown(), so also this object should get released... + sq_release(m_parent_vm,&m_thread_obj); + return true; +} + +SC_ERROR_STATE CBSquirrelThread::doString(const wxString script,const wxString name) +{ + return m_vm->doString(script,name); +} + + +/******************************************************************/ +/* Stack Handler */ +/******************************************************************/ + + +StackHandler::StackHandler(HSQUIRRELVM vm) : m_vm(vm) +{ + +} + +StackHandler::~StackHandler() +{ + +} + +int StackHandler::GetParamCount() +{ + return sq_gettop(m_vm); +} + +SQObjectType StackHandler::GetType(int pos) +{ + return sq_gettype(m_vm,pos); +} + +SQInteger StackHandler::ThrowError(const SQChar* error) +{ + return sq_throwerror(m_vm,error); +} + + +SQInteger StackHandler::ThrowError(const wxString error) +{ + + wxString tmp = _("Stack Handler: ") + error + _("\n")+ CreateStackInfo() + _("\n Local variables:\n") + CreateFunctionLocalInfo(1); + + return sq_throwerror(m_vm,tmp.ToUTF8().data()); +} + +wxString StackHandler::CreateStackInfo() +{ + SQStackInfos si; + int stack = 1; // lvl 0 is the sq_stackinfos itself + wxString stack_string(_("Call Stack: \n")); + while(SQ_SUCCEEDED(sq_stackinfos(m_vm,stack,&si))) + { + stack_string << wxString::Format(_("[%02i] "),stack) << wxString(si.funcname,wxConvUTF8) + << _T("\t(") << wxString(si.source,wxConvUTF8) << _(":") << si.line << _T(")\n"); + stack++; + } + return stack_string; +} + +wxString StackHandler::CreateFunctionLocalInfo(int stack_lvl) +{ + SQStackInfos si; + wxString stack_string; + int seq=0; + const SQChar *name=0; + const SQChar *s=0; + SQInteger i; + SQFloat f; + SQBool b; + + if(SQ_SUCCEEDED(sq_stackinfos(m_vm,stack_lvl,&si))) + { + stack_string << _T("FUNCTION: ") << wxString(si.funcname,wxConvUTF8) + <<_(" (") << wxString(si.source,wxConvUTF8) << _(":") << si.line << _T(")\n"); + } + + while((name = sq_getlocal(m_vm,stack_lvl,seq))) + { + seq++; + stack_string << _("\t") << wxString(name,wxConvUTF8) << _("\t"); + switch(sq_gettype(m_vm,-1)) + { + case OT_NULL: + stack_string << _(":(NULL)\n"); + break; + case OT_INTEGER: + sq_getinteger(m_vm,-1,&i); + stack_string << _(":(int)\t= ") << i << _("\n"); + break; + case OT_FLOAT: + sq_getfloat(m_vm,-1,&f); + stack_string << _(":(float)\t= ") << f << _("\n"); + break; + case OT_USERPOINTER: + stack_string << _(":(userpointer)\n"); + break; + case OT_STRING: + sq_getstring(m_vm,-1,&s); + stack_string << _(":(string)\t= ") << wxString(s,wxConvUTF8) << _("\n"); + break; + case OT_TABLE: + stack_string << _(":(table)\n"); + break; + case OT_ARRAY: + stack_string << _(":(array)\n"); + break; + case OT_CLOSURE: + stack_string << _(":(closure)\n"); + break; + case OT_NATIVECLOSURE: + stack_string << _(":(native closure)\n"); + break; + case OT_GENERATOR: + stack_string << _(":(generator)\n"); + break; + case OT_USERDATA: + stack_string << _(":(user data)\n"); + break; + case OT_THREAD: + stack_string << _(":(thread)\n"); + break; + case OT_CLASS: + stack_string << _(":(class)\n"); + break; + case OT_INSTANCE: + stack_string << _(":(instance)\n"); + break; + case OT_WEAKREF: + stack_string << _(":(weak ref)\n"); + break; + case OT_BOOL: + sq_getbool(m_vm,-1,&b); + stack_string << _(":(bool)\t= ") << (b?_("true"):_("false")) << _("\n"); + break; + default: + stack_string << _("\t") << _T("Stack error at lvl: ") << seq << _("\n"); + break; + } + sq_pop(m_vm,1); + } + return stack_string; +} + +wxString StackHandler::GetError(bool del) +{ + if(!Sqrat::Error::Occurred(m_vm)) + return wxEmptyString; + + wxString stack_string = CreateStackInfo(); + stack_string += _("\nSqrat Error\n"); + stack_string += wxString::FromUTF8(Sqrat::Error::Message(m_vm).c_str()); + + if(del) + Sqrat::Error::Clear(m_vm); + + return stack_string; +} + +bool StackHandler::HasError() +{ + return Sqrat::Error::Occurred(m_vm); +} + +} // namespace ScriptBindings + + + + + + + + + + + From c26cb4e3186932421ea7875b5201cd92e818c1b8 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 16:53:42 +0200 Subject: [PATCH 05/16] [NOT COMPILE] Change cb internals squirrel binding from sqplus to sqrat (1/3) - remove all wx related stuff from cb squirrel files + Add ClearPlugins() function to clean up all registered Plugins * All register functions expect a vm parameter to make it possible to * register to different vms --- src/include/scripting/bindings/sc_plugin.h | 2 + src/sdk/scripting/bindings/sc_consts.cpp | 91 +++--- src/sdk/scripting/bindings/sc_dialog.cpp | 47 ++- src/sdk/scripting/bindings/sc_globals.cpp | 197 +++++++------ src/sdk/scripting/bindings/sc_io.cpp | 46 +-- src/sdk/scripting/bindings/sc_plugin.cpp | 192 ++++++------ src/sdk/scripting/bindings/sc_progress.cpp | 48 ++- .../scripting/bindings/sc_util_dialogs.cpp | 275 ++++++++++-------- 8 files changed, 484 insertions(+), 414 deletions(-) diff --git a/src/include/scripting/bindings/sc_plugin.h b/src/include/scripting/bindings/sc_plugin.h index 74e6695da1..8f01ca6d0f 100644 --- a/src/include/scripting/bindings/sc_plugin.h +++ b/src/include/scripting/bindings/sc_plugin.h @@ -16,6 +16,8 @@ namespace ScriptBindings { namespace ScriptPluginWrapper { + void ClearPlugins(); + wxArrayInt CreateMenu(wxMenuBar* mbar); wxArrayInt CreateModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data); diff --git a/src/sdk/scripting/bindings/sc_consts.cpp b/src/sdk/scripting/bindings/sc_consts.cpp index 3b6e35f03b..d2b7506e89 100644 --- a/src/sdk/scripting/bindings/sc_consts.cpp +++ b/src/sdk/scripting/bindings/sc_consts.cpp @@ -9,24 +9,34 @@ #include #ifndef CB_PRECOMP + #include + #include + + #include + #include + #include + #include + #include #include + #include #include + #include #endif #include -#include "sc_base_types.h" +#include +#include "scripting/bindings/sc_binding_util.h" +#include "scripting/bindings/sc_plugin.h" + -// helper macros to bind constants -#define BIND_INT_CONSTANT(a) SqPlus::BindConstant(a, #a); -#define BIND_INT_CONSTANT_NAMED(a,n) SqPlus::BindConstant(a, n); -#define BIND_WXSTR_CONSTANT_NAMED(a,n) BindVariable(const_cast(&a), n, SqPlus::VAR_ACCESS_CONSTANT); namespace ScriptBindings { - wxString s_PathSep = wxFILE_SEP_PATH; + //wxString s_PathSep = wxFILE_SEP_PATH; + - void Register_Constants() + void Register_Constants(HSQUIRRELVM vm) { // platform constants BIND_INT_CONSTANT_NAMED(0, "PLATFORM_MSW"); @@ -54,45 +64,10 @@ namespace ScriptBindings BIND_INT_CONSTANT_NAMED(PLUGIN_SDK_VERSION_MINOR, "PLUGIN_SDK_VERSION_MINOR"); BIND_INT_CONSTANT_NAMED(PLUGIN_SDK_VERSION_RELEASE, "PLUGIN_SDK_VERSION_RELEASE"); - // path separator for filenames - BIND_WXSTR_CONSTANT_NAMED(s_PathSep, "wxFILE_SEP_PATH"); + BIND_INT_CONSTANT_NAMED(SCRIPT_BINDING_VERSION_MAJOR,"SCRIPT_BINDING_VERSION_MAJOR"); + BIND_INT_CONSTANT_NAMED(SCRIPT_BINDING_VERSION_MINOR,"SCRIPT_BINDING_VERSION_MINOR"); + BIND_INT_CONSTANT_NAMED(SCRIPT_BINDING_VERSION_RELEASE,"SCRIPT_BINDING_VERSION_RELEASE"); - // dialog buttons - BIND_INT_CONSTANT(wxOK); - BIND_INT_CONSTANT(wxYES_NO); - BIND_INT_CONSTANT(wxCANCEL); - BIND_INT_CONSTANT(wxID_OK); - BIND_INT_CONSTANT(wxID_YES); - BIND_INT_CONSTANT(wxID_NO); - BIND_INT_CONSTANT(wxID_CANCEL); - BIND_INT_CONSTANT(wxICON_QUESTION); - BIND_INT_CONSTANT(wxICON_INFORMATION); - BIND_INT_CONSTANT(wxICON_WARNING); - BIND_INT_CONSTANT(wxICON_ERROR); - - // wxPathFormat - BIND_INT_CONSTANT(wxPATH_NATIVE); - BIND_INT_CONSTANT(wxPATH_UNIX); - BIND_INT_CONSTANT(wxPATH_BEOS); - BIND_INT_CONSTANT(wxPATH_MAC); - BIND_INT_CONSTANT(wxPATH_DOS); - BIND_INT_CONSTANT(wxPATH_WIN); - BIND_INT_CONSTANT(wxPATH_OS2); - BIND_INT_CONSTANT(wxPATH_VMS); - - // for wxFileName::GetPath() - BIND_INT_CONSTANT(wxPATH_GET_VOLUME); - BIND_INT_CONSTANT(wxPATH_GET_SEPARATOR); - - // wxPathNormalize - BIND_INT_CONSTANT(wxPATH_NORM_ENV_VARS); - BIND_INT_CONSTANT(wxPATH_NORM_DOTS); - BIND_INT_CONSTANT(wxPATH_NORM_TILDE); - BIND_INT_CONSTANT(wxPATH_NORM_CASE); - BIND_INT_CONSTANT(wxPATH_NORM_ABSOLUTE); - BIND_INT_CONSTANT(wxPATH_NORM_LONG); - BIND_INT_CONSTANT(wxPATH_NORM_SHORTCUT); - BIND_INT_CONSTANT(wxPATH_NORM_ALL); // OptionsRelationType BIND_INT_CONSTANT(ortCompilerOptions); @@ -177,8 +152,34 @@ namespace ScriptBindings BIND_INT_CONSTANT(mtEditorManager); BIND_INT_CONSTANT(mtLogManager); BIND_INT_CONSTANT(mtOpenFilesList); + BIND_INT_CONSTANT(mtEditorTab); BIND_INT_CONSTANT(mtUnknown); + // File Type + BIND_INT_CONSTANT(ftCodeBlocksProject); + BIND_INT_CONSTANT(ftCodeBlocksWorkspace); + BIND_INT_CONSTANT(ftDevCppProject); + BIND_INT_CONSTANT(ftMSVC6Project); + BIND_INT_CONSTANT(ftMSVC7Project); + BIND_INT_CONSTANT(ftMSVC10Project); + BIND_INT_CONSTANT(ftMSVC6Workspace); + BIND_INT_CONSTANT(ftMSVC7Workspace); + BIND_INT_CONSTANT(ftXcode1Project); + BIND_INT_CONSTANT(ftXcode2Project); + BIND_INT_CONSTANT(ftSource); + BIND_INT_CONSTANT(ftHeader); + BIND_INT_CONSTANT(ftObject); + BIND_INT_CONSTANT(ftXRCResource); + BIND_INT_CONSTANT(ftResource); + BIND_INT_CONSTANT(ftResourceBin); + BIND_INT_CONSTANT(ftStaticLib); + BIND_INT_CONSTANT(ftDynamicLib); + BIND_INT_CONSTANT(ftExecutable); + BIND_INT_CONSTANT(ftNative); + BIND_INT_CONSTANT(ftXMLDocument); + BIND_INT_CONSTANT(ftScript); + BIND_INT_CONSTANT(ftOther); + // FileTreeDataKind BIND_INT_CONSTANT_NAMED(FileTreeData::ftdkUndefined, "ftdkUndefined"); BIND_INT_CONSTANT_NAMED(FileTreeData::ftdkProject, "ftdkProject"); diff --git a/src/sdk/scripting/bindings/sc_dialog.cpp b/src/sdk/scripting/bindings/sc_dialog.cpp index 804b338b6c..feb506d900 100644 --- a/src/sdk/scripting/bindings/sc_dialog.cpp +++ b/src/sdk/scripting/bindings/sc_dialog.cpp @@ -16,12 +16,13 @@ #include #include #include + #include + #include "scrollingdialog.h" #endif -#include - -#include "sc_base_types.h" +#include "scripting/bindings/sq_wx/sq_wx.h" +#include "scripting/bindings/sc_base_types.h" namespace ScriptBindings { @@ -62,24 +63,19 @@ namespace ScriptBindings // standard event IDs like wxID_OK/wxID_CANCEL/etc. event.Skip(true); - try - { -// Manager::Get()->GetLogManager()->DebugLog(F(_T("Script dialog event: %d"), event.GetId())); - SqPlus::SquirrelFunction cb(cbU2C(m_CallBack)); - if (cb.func.IsNull()) - return; - cb(event.GetId()); - } - catch (SquirrelError& e) - { - Manager::Get()->GetScriptingManager()->DisplayErrors(&e); - } + Sqrat::Function call_back(Sqrat::RootTable(),m_CallBack.ToUTF8()); + if (call_back.IsNull()) + return; + call_back(event.GetId()); + Manager::Get()->GetScriptingManager()->DisplayErrors(); + + } int ShowDialog(const wxString& xrc, const wxString& dlgName, const wxString& callback) { wxString actual = ConfigManager::LocateDataFile(xrc, sdScriptsUser | sdScriptsGlobal); -// Manager::Get()->GetLogManager()->DebugLog(F(_T("Original parameter is: ") + xrc)); + Manager::Get()->GetLogManager()->DebugLog(_T("Loading XRC: ") + actual); if (wxXmlResource::Get()->Load(actual)) { @@ -128,21 +124,24 @@ namespace ScriptBindings if (!s_ActiveDialog) { cbMessageBox(_("XRCID() only valid while inside a ShowDialog() call..."), _("Error"), wxICON_ERROR); - return sa.Return((SQInteger)-1); + sa.PushValue(-1); + return SC_RETURN_VALUE; } wxWindow* win = nullptr; if (sa.GetType(2) == OT_STRING) - win = wxWindow::FindWindowByName(cbC2U(sa.GetString(2)), s_ActiveDialog); + win = wxWindow::FindWindowByName(cbC2U(sa.GetValue(2)), s_ActiveDialog); else - win = wxWindow::FindWindowByName(*SqPlus::GetInstance(v, 2), s_ActiveDialog); - return sa.Return((SQInteger)(win ? win->GetId() : -1)); + win = wxWindow::FindWindowByName(*sa.GetInstance(2), s_ActiveDialog); + sa.PushValue((win ? win->GetId() : -1)); + return SC_RETURN_VALUE; } - void Register_Dialog() + void Register_Dialog( HSQUIRRELVM vm) { - SqPlus::RegisterGlobal(ShowDialog, "ShowDialog"); - SqPlus::RegisterGlobal(EndModal, "EndModal"); - SquirrelVM::CreateFunctionGlobal(XrcId, "XRCID", "*"); + Sqrat::RootTable(vm).Func("ShowDialog",ShowDialog); + Sqrat::RootTable(vm).Func("EndModal",EndModal); + Sqrat::RootTable(vm).SquirrelFunc("EndModal",XrcId); + } } // namespace ScriptBindings diff --git a/src/sdk/scripting/bindings/sc_globals.cpp b/src/sdk/scripting/bindings/sc_globals.cpp index 8fbc91a2be..6f7156f8f1 100644 --- a/src/sdk/scripting/bindings/sc_globals.cpp +++ b/src/sdk/scripting/bindings/sc_globals.cpp @@ -19,9 +19,11 @@ #include #include #include + #include #endif -#include "sc_base_types.h" +#include "scripting/bindings/sc_base_types.h" +#include "scripting/bindings/sq_wx/sq_wx_type_handler.h" #include #include @@ -30,50 +32,82 @@ namespace ScriptBindings { // global funcs - void gDebugLog(const wxString& msg){ Manager::Get()->GetLogManager()->DebugLog(msg); } - void gErrorLog(const wxString& msg){ Manager::Get()->GetLogManager()->LogError(msg); } - void gWarningLog(const wxString& msg){ Manager::Get()->GetLogManager()->LogWarning(msg); } - void gLog(const wxString& msg){ Manager::Get()->GetLogManager()->Log(msg); } - int gMessage(const wxString& msg, const wxString& caption, int buttons){ return cbMessageBox(msg, caption, buttons); } - void gShowMessage(const wxString& msg){ cbMessageBox(msg, _("Script message"), wxICON_INFORMATION | wxOK); } - void gShowMessageWarn(const wxString& msg){ cbMessageBox(msg, _("Script warning"), wxICON_WARNING | wxOK); } - void gShowMessageError(const wxString& msg){ cbMessageBox(msg, _("Script error"), wxICON_ERROR | wxOK); } - void gShowMessageInfo(const wxString& msg){ cbMessageBox(msg, _("Script information"), wxICON_INFORMATION | wxOK); } - wxString gReplaceMacros(const wxString& buffer){ return Manager::Get()->GetMacrosManager()->ReplaceMacros(buffer); } + void gDebugLog(const wxString& msg) { Manager::Get()->GetLogManager()->DebugLog(msg); } + void gErrorLog(const wxString& msg) { Manager::Get()->GetLogManager()->LogError(msg); } + void gWarningLog(const wxString& msg) { Manager::Get()->GetLogManager()->LogWarning(msg); } + void gLog(const wxString& msg) { Manager::Get()->GetLogManager()->Log(msg); } + int gMessage(const wxString& msg, const wxString& caption, int buttons){ return cbMessageBox(msg, caption, buttons); } + void gShowMessage(const wxString& msg) { cbMessageBox(msg, _("Script message"), wxICON_INFORMATION | wxOK); } + void gShowMessageWarn(const wxString& msg) { cbMessageBox(msg, _("Script warning"), wxICON_WARNING | wxOK); } + void gShowMessageError(const wxString& msg) { cbMessageBox(msg, _("Script error"), wxICON_ERROR | wxOK); } + void gShowMessageInfo(const wxString& msg) { cbMessageBox(msg, _("Script information"), wxICON_INFORMATION | wxOK); } + +// FIXME (bluehazzard#1#): Fix the scripts, because replace macros only use one parameter, for compatibility this is implemented + SQInteger gReplaceMacros(HSQUIRRELVM v) + { + StackHandler sa(v); + + if (sa.GetParamCount() == 0) { + return sa.ThrowError(_("ReplaceMacros: wrong number of parameters")); + } + + bool subrequest = false; + wxString origin = sa.GetValue(2); + if(sa.GetParamCount() >= 3) + { + subrequest = sa.GetValue(3); + } + if(sa.HasError()) { + return sa.ThrowError(_("ReplaceMacros: something is wrong")); + } + + wxString ret_val(origin); + Manager::Get()->GetMacrosManager()->ReplaceMacros(ret_val,nullptr,subrequest); + sa.PushInstanceCopy(ret_val); + + return SC_RETURN_VALUE; + } SQInteger IsNull(HSQUIRRELVM v) { StackHandler sa(v); SQUserPointer up = nullptr; sq_getinstanceup(v, 2, &up, nullptr); - return sa.Return(up == nullptr); + sa.PushValue((up == nullptr)); + return SC_RETURN_VALUE; } ProjectManager* getPM() { return Manager::Get()->GetProjectManager(); } + EditorManager* getEM() { return Manager::Get()->GetEditorManager(); } + ConfigManager* getCM() { return Manager::Get()->GetConfigManager(_T("scripts")); } + CompilerFactory* getCF() { static CompilerFactory cf; // all its members are static functions anyway return &cf; } + UserVariableManager* getUVM() { return Manager::Get()->GetUserVariableManager(); } + ScriptingManager* getSM() { return Manager::Get()->GetScriptingManager(); } + bool InstallPlugin(const wxString& pluginName, bool allUsers, bool confirm) { if (cbMessageBox(_("A script is trying to install a Code::Blocks plugin.\n" @@ -84,16 +118,20 @@ namespace ScriptBindings } return Manager::Get()->GetPluginManager()->InstallPlugin(pluginName, allUsers, confirm); } + int ExecutePlugin(const wxString& pluginName) { return Manager::Get()->GetPluginManager()->ExecutePlugin(pluginName); } + int ConfigurePlugin(const wxString& pluginName) { + cbMessageBox(_("\"ConfigurePlugin\" does nothing. Please remove from your code"),_("Squirrel API information"),wxICON_INFORMATION|wxOK); return 0; /* leaving script binding intact for compatibility, but this is factually not implemented at all */ } + // locate and call a menu from string (e.g. "/Valgrind/Run Valgrind::MemCheck") - void CallMenu(const wxString& menuPath) + int CallMenu(const wxString& menuPath) { // this code is partially based on MenuItemsManager::CreateFromString() wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar(); @@ -135,10 +173,14 @@ namespace ScriptBindings #if wxCHECK_VERSION(3, 0, 0) mbar->GetEventHandler()->ProcessEvent(evt); #else - if ( !mbar->ProcessEvent(evt) ) + if(!Manager::Get()->GetAppWindow()->ProcessEvent(evt)) + //if ( !mbar->ProcessEvent(evt) ) { - wxString msg; msg.Printf(_("Calling the menu '%s' with ID %d failed."), menuPath.wx_str(), id); + // TODO (bluehazzard#1#): Report the error to squirrel + wxString msg; + msg.Printf(_("Calling the menu '%s' with ID %d failed."), menuPath.wx_str(), id); cbMessageBox(msg, _("Script error"), wxICON_WARNING); + return -1; } #endif // done @@ -149,110 +191,89 @@ namespace ScriptBindings if (existing != wxNOT_FOUND) menu = menu->GetMenuItems()[existing]->GetSubMenu(); else - break; // failed + return -2; // failed } pos = nextPos; // prepare for next loop + return 0; } } + void Include(const wxString& filename) { getSM()->LoadScript(filename); } + SQInteger Require(HSQUIRRELVM v) { StackHandler sa(v); - const wxString& filename = *SqPlus::GetInstance(v, 2); + wxString filename = sa.GetValue(2); if (!getSM()->LoadScript(filename)) { wxString msg = wxString::Format(_("Failed to load required script: %s"), filename.c_str()); - return sa.ThrowError(cbU2C(msg)); + return sa.ThrowError(msg); } - return sa.Return(static_cast(0)); - } - SQInteger wx_GetColourFromUser(HSQUIRRELVM v) - { - StackHandler sa(v); - const wxColour& c = sa.GetParamCount() == 2 ? *SqPlus::GetInstance(v, 2) : *wxBLACK; - return SqPlus::ReturnCopy(v, wxGetColourFromUser(Manager::Get()->GetAppWindow(), c)); - } - long wx_GetNumberFromUser(const wxString& message, const wxString& prompt, const wxString& caption, long value) - { - return wxGetNumberFromUser(message, prompt, caption, value); - } - wxString wx_GetPasswordFromUser(const wxString& message, const wxString& caption, const wxString& default_value) - { - return wxGetPasswordFromUser(message, caption, default_value); - } - wxString wx_GetTextFromUser(const wxString& message, const wxString& caption, const wxString& default_value) - { - return cbGetTextFromUser(message, caption, default_value); + sa.PushValue(0); + return SC_RETURN_VALUE; } - long wxString_ToLong(wxString const &str) + bool LoadResource(wxString& res) { - long value; - if(!str.ToLong(&value)) - return -1; - return value; + // Do not use this function. Use the function incorporated in the wxDialog class, so resources can get unloaded when they are not needed any more + return Manager::LoadResource(res); } - void Register_Globals() + void Register_Globals(HSQUIRRELVM vm) { - // global funcs - SqPlus::RegisterGlobal(gLog, "Log"); - SqPlus::RegisterGlobal(gDebugLog, "LogDebug"); - SqPlus::RegisterGlobal(gWarningLog, "LogWarning"); - SqPlus::RegisterGlobal(gErrorLog, "LogError"); - - SqPlus::RegisterGlobal(gMessage, "Message"); - SqPlus::RegisterGlobal(gShowMessage, "ShowMessage"); - SqPlus::RegisterGlobal(gShowMessageWarn, "ShowWarning"); - SqPlus::RegisterGlobal(gShowMessageError, "ShowError"); - SqPlus::RegisterGlobal(gShowMessageInfo, "ShowInfo"); - SqPlus::RegisterGlobal(gReplaceMacros, "ReplaceMacros"); - - SqPlus::RegisterGlobal(getPM, "GetProjectManager"); - SqPlus::RegisterGlobal(getEM, "GetEditorManager"); - SqPlus::RegisterGlobal(getCM, "GetConfigManager"); - SqPlus::RegisterGlobal(getUVM, "GetUserVariableManager"); - SqPlus::RegisterGlobal(getSM, "GetScriptingManager"); - SqPlus::RegisterGlobal(getCF, "GetCompilerFactory"); + // global funcs + Sqrat::RootTable(vm).Func("Log", gLog); + Sqrat::RootTable(vm).Func("LogDebug", gDebugLog); + Sqrat::RootTable(vm).Func("LogWarning", gWarningLog); + Sqrat::RootTable(vm).Func("LogError", gErrorLog); + + Sqrat::RootTable(vm).Func("Message", gMessage); + Sqrat::RootTable(vm).Func("ShowMessage",gShowMessage); + Sqrat::RootTable(vm).Func("ShowWarning",gShowMessageWarn); + Sqrat::RootTable(vm).Func("ShowError", gShowMessageError); + Sqrat::RootTable(vm).Func("ShowInfo", gShowMessageInfo); + + Sqrat::RootTable(vm).SquirrelFunc("ReplaceMacros",gReplaceMacros); + + Sqrat::RootTable(vm).Func("GetProjectManager", getPM); + Sqrat::RootTable(vm).Func("GetEditorManager", getEM); + Sqrat::RootTable(vm).Func("GetConfigManager", getCM); + Sqrat::RootTable(vm).Func("GetUserVariableManager",getUVM); + Sqrat::RootTable(vm).Func("GetScriptingManager",getSM); + Sqrat::RootTable(vm).Func("GetCompilerFactory", getCF); // from globals.h - SqPlus::RegisterGlobal(GetArrayFromString, "GetArrayFromString"); - SqPlus::RegisterGlobal(GetStringFromArray, "GetStringFromArray"); - SqPlus::RegisterGlobal(EscapeSpaces, "EscapeSpaces"); - SqPlus::RegisterGlobal(UnixFilename, "UnixFilename"); - SqPlus::RegisterGlobal(FileTypeOf, "FileTypeOf"); - SqPlus::RegisterGlobal(URLEncode, "URLEncode"); - SqPlus::RegisterGlobal(NotifyMissingFile, "NotifyMissingFile"); - SqPlus::RegisterGlobal(GetPlatformsFromString, "GetPlatformsFromString"); - SqPlus::RegisterGlobal(GetStringFromPlatforms, "GetStringFromPlatforms"); + Sqrat::RootTable(vm).Func("GetArrayFromString", GetArrayFromString); + Sqrat::RootTable(vm).Func("GetStringFromArray", GetStringFromArray); + Sqrat::RootTable(vm).Func("EscapeSpaces", EscapeSpaces); + Sqrat::RootTable(vm).Func("UnixFilename", UnixFilename); + Sqrat::RootTable(vm).Func("FileTypeOf", FileTypeOf); + Sqrat::RootTable(vm).Func("URLEncode", URLEncode); + Sqrat::RootTable(vm).Func("NotifyMissingFile", NotifyMissingFile); + Sqrat::RootTable(vm).Func("GetPlatformsFromString",GetPlatformsFromString); + Sqrat::RootTable(vm).Func("GetStringFromPlatforms",GetStringFromPlatforms); - SqPlus::RegisterGlobal(ConfigManager::GetFolder, "GetFolder"); - SqPlus::RegisterGlobal(ConfigManager::LocateDataFile, "LocateDataFile"); + Sqrat::RootTable(vm).Func("GetFolder", ConfigManager::GetFolder); + Sqrat::RootTable(vm).Func("LocateDataFile", ConfigManager::LocateDataFile); - SqPlus::RegisterGlobal(ExecutePlugin, "ExecuteToolPlugin"); - SqPlus::RegisterGlobal(ConfigurePlugin, "ConfigureToolPlugin"); - SqPlus::RegisterGlobal(InstallPlugin, "InstallPlugin"); + Sqrat::RootTable(vm).Func("ExecuteToolPlugin", ExecutePlugin); + Sqrat::RootTable(vm).Func("ConfigureToolPlugin",ConfigurePlugin); + Sqrat::RootTable(vm).Func("InstallPlugin", InstallPlugin); - SqPlus::RegisterGlobal(CallMenu, "CallMenu"); + Sqrat::RootTable(vm).Func("CallMenu", CallMenu); - SqPlus::RegisterGlobal(Include, "Include"); - SquirrelVM::CreateFunctionGlobal(Require, "Require", "*"); - SqPlus::RegisterGlobal(InfoWindow::Display, "InfoWindow"); + //Sqrat::RootTable(vm).Func("LoadResource", LoadResource); - SquirrelVM::CreateFunctionGlobal(IsNull, "IsNull", "*"); + Sqrat::RootTable(vm).Func("Include", Include); + Sqrat::RootTable(vm).SquirrelFunc("Require",Require); - // now for some wx globals (utility) functions - SqPlus::RegisterGlobal(wxLaunchDefaultBrowser, "wxLaunchDefaultBrowser"); - SquirrelVM::CreateFunctionGlobal(wx_GetColourFromUser, "wxGetColourFromUser", "*"); - SqPlus::RegisterGlobal(wx_GetNumberFromUser, "wxGetNumberFromUser"); - SqPlus::RegisterGlobal(wx_GetPasswordFromUser, "wxGetPasswordFromUser"); - SqPlus::RegisterGlobal(wx_GetTextFromUser, "wxGetTextFromUser"); + Sqrat::RootTable(vm).Func("InfoWindow", InfoWindow::Display); - SqPlus::RegisterGlobal(wxString_ToLong, "wxString_ToLong"); + Sqrat::RootTable(vm).SquirrelFunc("IsNull",IsNull); } } diff --git a/src/sdk/scripting/bindings/sc_io.cpp b/src/sdk/scripting/bindings/sc_io.cpp index a48061b80d..7e59214c60 100644 --- a/src/sdk/scripting/bindings/sc_io.cpp +++ b/src/sdk/scripting/bindings/sc_io.cpp @@ -23,7 +23,7 @@ #include #include "scriptsecuritywarningdlg.h" -#include "sc_base_types.h" +#include "scripting/bindings/sc_base_types.h" namespace ScriptBindings { @@ -230,35 +230,37 @@ namespace ScriptBindings { struct IONamespace {}; - void Register_IO() + void Register_IO(HSQUIRRELVM vm) { - SqPlus::SQClassDef("IO"). - + Sqrat::Class io_class(vm,"IO"); + io_class. #ifndef NO_INSECURE_SCRIPTS - staticFunc(&IOLib::CreateDirRecursively, "CreateDirectory"). - staticFunc(&IOLib::RemoveDir, "RemoveDirectory"). - staticFunc(&IOLib::CopyFile, "CopyFile"). - staticFunc(&IOLib::RenameFile, "RenameFile"). - staticFunc(&IOLib::RemoveFile, "RemoveFile"). - staticFunc(&IOLib::WriteFileContents, "WriteFileContents"). - staticFunc(&IOLib::Execute, "Execute"). - staticFunc(&IOLib::ExecuteAndGetOutput, "ExecuteAndGetOutput"). - staticFunc(&IOLib::ExecuteAndGetOutputAndError, "ExecuteAndGetOutputAndError"). + StaticFunc("CreateDirectory", &IOLib::CreateDirRecursively). + StaticFunc("RemoveDirectory", &IOLib::RemoveDir). + StaticFunc("CopyFile", &IOLib::CopyFile). + StaticFunc("RenameFile", &IOLib::RenameFile). + StaticFunc("RemoveFile", &IOLib::RemoveFile). + StaticFunc("WriteFileContents", &IOLib::WriteFileContents). + StaticFunc("Execute", &IOLib::Execute). + StaticFunc("ExecuteAndGetOutput", &IOLib::ExecuteAndGetOutput). + StaticFunc("ExecuteAndGetOutputAndError", &IOLib::ExecuteAndGetOutputAndError). #endif // NO_INSECURE_SCRIPTS - staticFunc(&IOLib::GetCwd, "GetCwd"). - staticFunc(&IOLib::SetCwd, "SetCwd"). + StaticFunc("GetCwd",&IOLib::GetCwd). + StaticFunc("SetCwd",&IOLib::SetCwd). + + StaticFunc("DirectoryExists", &IOLib::DirectoryExists). + StaticFunc("SelectDirectory", &IOLib::ChooseDir). + StaticFunc("FileExists", &IOLib::FileExists). + StaticFunc("SelectFile", &IOLib::ChooseFile). + StaticFunc("ReadFileContents",&IOLib::ReadFileContents); - staticFunc(&IOLib::DirectoryExists, "DirectoryExists"). - staticFunc(&IOLib::ChooseDir, "SelectDirectory"). - staticFunc(&IOLib::FileExists, "FileExists"). - staticFunc(&IOLib::ChooseFile, "SelectFile"). - staticFunc(&IOLib::ReadFileContents, "ReadFileContents"); + Sqrat::RootTable(vm).Bind("IO",io_class); #ifndef NO_INSECURE_SCRIPTS - SqPlus::BindConstant(true, "allowInsecureScripts"); + Sqrat::ConstTable(vm).Const("allowInsecureScripts", true); #else - SqPlus::BindConstant(false, "allowInsecureScripts"); + Sqrat::ConstTable(vm).Const("allowInsecureScripts", false); #endif // NO_INSECURE_SCRIPTS } } // namespace ScriptBindings diff --git a/src/sdk/scripting/bindings/sc_plugin.cpp b/src/sdk/scripting/bindings/sc_plugin.cpp index 8ca3f62cd5..ced60e88e3 100644 --- a/src/sdk/scripting/bindings/sc_plugin.cpp +++ b/src/sdk/scripting/bindings/sc_plugin.cpp @@ -8,7 +8,7 @@ */ #include -#include "sc_plugin.h" +#include #include #include #include @@ -21,20 +21,26 @@ namespace ScriptPluginWrapper { // struct and map for mapping script plugins to menu callbacks struct MenuCallback { - SquirrelObject object; + Sqrat::Object object; int menuIndex; }; typedef std::map ModuleMenuCallbacks; ModuleMenuCallbacks s_MenuCallbacks; // master list of registered script plugins -typedef std::map ScriptPlugins; +typedef std::map ScriptPlugins; ScriptPlugins s_ScriptPlugins; // list of registered script plugins menubar items typedef std::map ScriptPluginsMenus; ScriptPluginsMenus s_ScriptPluginsMenus; +void ClearPlugins() +{ + s_ScriptPlugins.clear(); + s_MenuCallbacks.clear(); +} + //////////////////////////////////////////////////////////////////////////////// // ask the script plugin what menus to add in the menubar // and return an integer array of the menu IDs @@ -46,7 +52,7 @@ wxArrayInt CreateMenu(const wxString& name) ScriptPlugins::iterator it = s_ScriptPlugins.find(name); if (it == s_ScriptPlugins.end()) return ret; - SquirrelObject& o = it->second; + Sqrat::Object& o = it->second; ScriptPluginsMenus::iterator itm = s_ScriptPluginsMenus.find(name); if (itm == s_ScriptPluginsMenus.end()) @@ -55,27 +61,25 @@ wxArrayInt CreateMenu(const wxString& name) } MenuItemsManager& mi = itm->second; - SqPlus::SquirrelFunction f(o, "GetMenu"); - if (f.func.IsNull()) + // TODO (bluehazzard#1#): Cleanup ... + Sqrat::Function f(o,"GetMenu"); + if (f.IsNull()) return ret; - wxArrayString arr; - try - { - arr = f(); - } - catch (SquirrelError e) + Sqrat::SharedPtr arr; + arr = f.Evaluate(); + if(!arr) { - cbMessageBox(cbC2U(e.desc), _("Script error"), wxICON_ERROR); + cbMessageBox(cbC2U(Sqrat::LastErrorString(o.GetVM()).c_str()), _("Script error"), wxICON_ERROR); return ret; } - if (arr.GetCount()) + if (arr->GetCount()) { - for (size_t i = 0; i < arr.GetCount(); ++i) + for (size_t i = 0; i < arr->GetCount(); ++i) { int id = wxNewId(); - id = mi.CreateFromString(arr[i], id); + id = mi.CreateFromString(arr->Item(i), id); ret.Add(id); @@ -108,26 +112,23 @@ wxArrayInt CreateModuleMenu(const ModuleType typ, wxMenu* menu, const FileTreeDa ScriptPlugins::iterator it; for (it = s_ScriptPlugins.begin(); it != s_ScriptPlugins.end(); ++it) { - SquirrelObject& o = it->second; - SqPlus::SquirrelFunction f(o, "GetModuleMenu"); - if (f.func.IsNull()) + Sqrat::Object& o = it->second; + Sqrat::Function f(o,"GetModuleMenu"); + if (f.IsNull()) continue; - wxArrayString arr; - try + Sqrat::SharedPtr arr; + arr = f.Evaluate(typ, data); + if(!arr) { - arr = f(typ, data); - } - catch (SquirrelError e) - { - cbMessageBox(cbC2U(e.desc), _("Script error"), wxICON_ERROR); - continue; + cbMessageBox(cbC2U(Sqrat::LastErrorString(o.GetVM()).c_str()), _("Script error"), wxICON_ERROR); + return ret; } - if (arr.GetCount()==1) // exactly one menu entry + if (arr->GetCount()==1) // exactly one menu entry { int id = wxNewId(); - menu->Append(id, arr[0]); + menu->Append(id, arr->Item(0)); ret.Add(id); MenuCallback callback; @@ -135,13 +136,13 @@ wxArrayInt CreateModuleMenu(const ModuleType typ, wxMenu* menu, const FileTreeDa callback.menuIndex = 0; s_MenuCallbacks.insert(s_MenuCallbacks.end(), std::make_pair(id, callback)); } - else if (arr.GetCount()>1) // more menu entries -> create sub-menu + else if (arr->GetCount()>1) // more menu entries -> create sub-menu { wxMenu* sub = new wxMenu; - for (size_t i = 0; i < arr.GetCount(); ++i) + for (size_t i = 0; i < arr->GetCount(); ++i) { int id = wxNewId(); - sub->Append(id, arr[i]); + sub->Append(id, arr->Item(i)); ret.Add(id); @@ -166,16 +167,13 @@ void OnScriptMenu(int id) if (it != s_MenuCallbacks.end()) { MenuCallback& callback = it->second; - SqPlus::SquirrelFunction f(callback.object, "OnMenuClicked"); - if (!f.func.IsNull()) + Sqrat::Function f(callback.object,"OnMenuClicked"); + if (!f.IsNull()) { - try - { - f(callback.menuIndex); - } - catch (SquirrelError e) + f(callback.menuIndex); + if(Sqrat::Error::Occurred(callback.object.GetVM())) { - cbMessageBox(cbC2U(e.desc), _("Script error"), wxICON_ERROR); + cbMessageBox(cbC2U(Sqrat::Error::Message(callback.object.GetVM()).c_str()), _("Script error"), wxICON_ERROR); } } } @@ -191,16 +189,13 @@ void OnScriptModuleMenu(int id) if (it != s_MenuCallbacks.end()) { MenuCallback& callback = it->second; - SqPlus::SquirrelFunction f(callback.object, "OnModuleMenuClicked"); - if (!f.func.IsNull()) + Sqrat::Function f(callback.object,"OnModuleMenuClicked"); + if (!f.IsNull()) { - try - { - f(callback.menuIndex); - } - catch (SquirrelError e) + f(callback.menuIndex); + if(Sqrat::Error::Occurred(callback.object.GetVM())) { - cbMessageBox(cbC2U(e.desc), _("Script error"), wxICON_ERROR); + cbMessageBox(cbC2U(Sqrat::Error::Message(callback.object.GetVM()).c_str()), _("Script error"), wxICON_ERROR); } } } @@ -212,17 +207,26 @@ void OnScriptModuleMenu(int id) SQInteger RegisterPlugin(HSQUIRRELVM v) { // get squirrel object to register from stack - SquirrelObject o; - o.AttachToStackObject(2); - // first verify that there is a member function to retrieve the plugin info - if (!o.Exists("GetPluginInfo")) + HSQOBJECT t; + sq_getstackobj(v,2,&t); + Sqrat::Object o(t,v); + + // first verify that there is a member function to retrieve the plugin info + Sqrat::Function f(o,"GetPluginInfo"); + if (f.IsNull()) + { return sq_throwerror(v, "Not a script plugin!"); + } + // ask for its registration name - SqPlus::SquirrelFunction f(o, "GetPluginInfo"); - PluginInfo& info = f(); - wxString s = info.name; + Sqrat::SharedPtr info = f.Evaluate(); + if(!info) + { + return sq_throwerror(v, "Error on getting PluginInfo!"); + } + wxString s = info->name; // look if a script plugin with the same name already exists ScriptPlugins::iterator it = s_ScriptPlugins.find(s); @@ -243,27 +247,6 @@ SQInteger RegisterPlugin(HSQUIRRELVM v) return 0; } -//////////////////////////////////////////////////////////////////////////////// -// get a script plugin squirrel object (script-bound function) -//////////////////////////////////////////////////////////////////////////////// -SQInteger GetPlugin(HSQUIRRELVM v) -{ - StackHandler sa(v); - - // get the script plugin's name - const wxString& name = *SqPlus::GetInstance(v, 2); - - // search for it in the registered script plugins list - ScriptPlugins::iterator it = s_ScriptPlugins.find(name); - if (it != s_ScriptPlugins.end()) - { - // found; return the squirrel object - return sa.Return(it->second); - } - - // not found; return nothing - return sa.Return(); -} //////////////////////////////////////////////////////////////////////////////// // execute a script plugin (script-bound function) @@ -275,17 +258,14 @@ int ExecutePlugin(const wxString& name) if (it != s_ScriptPlugins.end()) { // found; execute it - SquirrelObject& o = it->second; - SqPlus::SquirrelFunction f(o, "Execute"); - if (!f.func.IsNull()) + Sqrat::Object& o = it->second; + Sqrat::Function f(o,"Execute"); + if (!f.IsNull()) { - try + f(); + if(Sqrat::Error::Occurred(o.GetVM())) { - f(); - } - catch (SquirrelError e) - { - cbMessageBox(cbC2U(e.desc), _("Script error"), wxICON_ERROR); + cbMessageBox(cbC2U(Sqrat::Error::Message(o.GetVM()).c_str()), _("Script error"), wxICON_ERROR); } } } @@ -336,11 +316,10 @@ const char* s_cbScriptPlugin = //////////////////////////////////////////////////////////////////////////////// // register the script plugin framework //////////////////////////////////////////////////////////////////////////////// -void Register_ScriptPlugin() +void Register_ScriptPlugin(HSQUIRRELVM vm) { - SqPlus::RegisterGlobal(&ScriptPluginWrapper::ExecutePlugin, "ExecutePlugin"); - SquirrelVM::CreateFunctionGlobal(&ScriptPluginWrapper::GetPlugin, "GetPlugin", "*"); - SquirrelVM::CreateFunctionGlobal(&ScriptPluginWrapper::RegisterPlugin, "RegisterPlugin", "*"); + Sqrat::RootTable(vm).Func("ExecutePlugin",&ScriptPluginWrapper::ExecutePlugin); + Sqrat::RootTable(vm).SquirrelFunc("RegisterPlugin",&ScriptPluginWrapper::RegisterPlugin); // load base script plugin @@ -349,25 +328,26 @@ void Register_ScriptPlugin() // loop and the app would die with a stack overflow. We got to load the script manually... // we also have to disable the printfunc for a while - SQPRINTFUNCTION oldPrintFunc = sq_getprintfunc(SquirrelVM::GetVMPtr()); - sq_setprintfunc(SquirrelVM::GetVMPtr(), 0); + SQPRINTFUNCTION oldPrintFunc = sq_getprintfunc(vm); + SQPRINTFUNCTION oldErrorFunc = sq_geterrorfunc(vm); + sq_setprintfunc(vm, 0,0); - // compile and run script - SquirrelObject script; - try - { - script = SquirrelVM::CompileBuffer(s_cbScriptPlugin, "cbScriptPlugin"); - SquirrelVM::RunScript(script); - } - catch (SquirrelError e) - { - cbMessageBox(wxString::Format(_("Failed to register script plugins framework.\n\n%s"), - cbC2U(e.desc).c_str()), - _("Script compile error"), wxICON_ERROR); - } + // compile and run scrip + StackHandler sa(vm); + Sqrat::Script script(vm); - // restore the printfunc - sq_setprintfunc(SquirrelVM::GetVMPtr(), oldPrintFunc); + script.CompileString(s_cbScriptPlugin,"PluginBaseScript (in source code)"); + script.Run(); + if(sa.HasError()) + { + // Warning: DisplayErrors from ScriptingManager causes a infinite loop + cbMessageBox(wxString::Format(_("Failed to register script plugins framework.\n\n")) + sa.GetError(), + _("Script compile error"), + wxICON_ERROR); + } + + // restore the printfunc + sq_setprintfunc(vm, oldPrintFunc,oldErrorFunc); } }; // namespace ScriptBindings diff --git a/src/sdk/scripting/bindings/sc_progress.cpp b/src/sdk/scripting/bindings/sc_progress.cpp index bf94a943e1..ae5049335a 100644 --- a/src/sdk/scripting/bindings/sc_progress.cpp +++ b/src/sdk/scripting/bindings/sc_progress.cpp @@ -17,7 +17,7 @@ #include -#include "sc_base_types.h" +#include "scripting/bindings/sc_base_types.h" class ProgressDialog : public wxProgressDialog { @@ -30,6 +30,14 @@ class ProgressDialog : public wxProgressDialog { } + ProgressDialog(wxString title, wxString Message,int max) + : wxProgressDialog(title, + Message, + max, nullptr, + wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT) + { + } + ~ProgressDialog() { } @@ -45,14 +53,42 @@ class ProgressDialog : public wxProgressDialog } }; -DECLARE_INSTANCE_TYPE(ProgressDialog); namespace ScriptBindings { - void Register_ProgressDialog() + void Register_ProgressDialog(HSQUIRRELVM vm) { - SqPlus::SQClassDef("ProgressDialog"). - emptyCtor(). - func(&ProgressDialog::DoUpdate, "DoUpdate"); + + + /** \ingroup sq_dialogs + *### ProgressDialog() + * Create an Progress Dialog with the Title _"Progress"_ and the message _"Please wait while operation is in progress..."_. + * The Dialog can be updated with the member function _DoUpdate_ + * + *### ProgressDialog(title,Message,max) + * Create an Progress Dialog with the Title _title_ and the message _Message_. + * The Dialog can be updated with the member function _DoUpdate_ + * + * - __title__ The title for the window [wxString] + * - __Message__ The Message which gets displayed to inform the user [wxString] + * - __max__ The value on which the progressbar reaches 100% [int] + * + * + */ + + /** \ingroup sq_dialogs + *### DoUpdate(value,newmsg) + * This member function updates the progressbar with the _value_ and the message _newmsg_. If _value_ is >= _max_. The dialogue will be closed. + * + * - __value__ The title for the window [int] + * - __newmsg__ The Message which gets displayed to inform the user [wxString] + * + */ + Sqrat::Class > progress_dialog(vm,"ProgressDialog"); + progress_dialog. + //Ctor(). + Ctor(). + Func("DoUpdate", &ProgressDialog::DoUpdate); + Sqrat::RootTable(vm).Bind("ProgressDialog",progress_dialog); } } // namespace ScriptBindings diff --git a/src/sdk/scripting/bindings/sc_util_dialogs.cpp b/src/sdk/scripting/bindings/sc_util_dialogs.cpp index 150208af6e..5bdf0bfb4e 100644 --- a/src/sdk/scripting/bindings/sc_util_dialogs.cpp +++ b/src/sdk/scripting/bindings/sc_util_dialogs.cpp @@ -15,7 +15,9 @@ #include #endif -#include "sc_base_types.h" +#include +#include +#include "scripting/bindings/sc_base_types.h" #include #include @@ -24,136 +26,149 @@ #include #include -DECLARE_ENUM_TYPE(EditPairDlg::BrowseMode); + namespace ScriptBindings { - SQInteger EditArrayFileDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) + /*SQInteger EditArrayFileDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) { SQ_DELETE_CLASS(EditArrayFileDlg); - } + }*/ - SQInteger EditArrayFileDlg_Ctor(HSQUIRRELVM v) + SQInteger EditArrayFileDlg_Ctor(HSQUIRRELVM vm) { // (wxWindow* parent, // wxArrayString& array, // bool useRelativePaths = false, // const wxString& basePath = _T("")) - StackHandler sa(v); + StackHandler sa(vm); EditArrayFileDlg* dlg = nullptr; if (sa.GetParamCount() > 3) { dlg = new EditArrayFileDlg(nullptr, - *SqPlus::GetInstance(v, 2), - sa.GetBool(3), - *SqPlus::GetInstance(v, 4)); + *sa.GetInstance( 2), + sa.GetValue(3), + *sa.GetInstance( 4)); } else if (sa.GetParamCount() > 2) { dlg = new EditArrayFileDlg(nullptr, - *SqPlus::GetInstance(v, 2), - sa.GetBool(3)); + *sa.GetInstance( 2), + sa.GetValue(3)); } else if (sa.GetParamCount() > 1) { dlg = new EditArrayFileDlg(nullptr, - *SqPlus::GetInstance(v, 2)); + *sa.GetInstance( 2)); } else - return sa.ThrowError("EditArrayFileDlg needs at least one argument"); + return sa.ThrowError(_("EditArrayFileDlg needs at least one argument")); + - return SqPlus::PostConstruct(v, dlg, EditArrayFileDlg_Dtor); + sq_setinstanceup(vm, 1, dlg); + sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; } - SQInteger EditArrayOrderDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) + /*SQInteger EditArrayOrderDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) { SQ_DELETE_CLASS(EditArrayOrderDlg); - } + }*/ - SQInteger EditArrayOrderDlg_Ctor(HSQUIRRELVM v) + SQInteger EditArrayOrderDlg_Ctor(HSQUIRRELVM vm) { // (wxWindow* parent, const wxArrayString& array = 0L) - StackHandler sa(v); + StackHandler sa(vm); EditArrayOrderDlg* dlg = nullptr; if (sa.GetParamCount() == 1) dlg = new EditArrayOrderDlg(nullptr, wxArrayString()); else if (sa.GetParamCount() == 2) - dlg = new EditArrayOrderDlg(nullptr, *SqPlus::GetInstance(v, 2)); + dlg = new EditArrayOrderDlg(nullptr, *sa.GetInstance( 2)); else - return sa.ThrowError("EditArrayOrderDlg needs at most one argument"); + return sa.ThrowError(_("EditArrayOrderDlg needs at most one argument")); - return SqPlus::PostConstruct(v, dlg, EditArrayOrderDlg_Dtor); + sq_setinstanceup(vm, 1, dlg); + sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; + //return SqPlus::PostConstruct(v, dlg, EditArrayOrderDlg_Dtor); } - SQInteger EditArrayStringDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) + /*SQInteger EditArrayStringDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) { SQ_DELETE_CLASS(EditArrayStringDlg); - } + }*/ - SQInteger EditArrayStringDlg_Ctor(HSQUIRRELVM v) + SQInteger EditArrayStringDlg_Ctor(HSQUIRRELVM vm) { // (wxWindow* parent, const wxArrayString& array) - StackHandler sa(v); + StackHandler sa(vm); EditArrayStringDlg* dlg = nullptr; if (sa.GetParamCount() == 2) - dlg = new EditArrayStringDlg(nullptr, *SqPlus::GetInstance(v, 2)); + dlg = new EditArrayStringDlg(nullptr, *sa.GetInstance( 2)); else - return sa.ThrowError("EditArrayStringDlg needs one argument"); + return sa.ThrowError(_("EditArrayStringDlg needs one argument")); - return SqPlus::PostConstruct(v, dlg, EditArrayStringDlg_Dtor); + sq_setinstanceup(vm, 1, dlg); + sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; + //return SqPlus::PostConstruct(v, dlg, EditArrayStringDlg_Dtor); } - SQInteger EditPairDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) + /*SQInteger EditPairDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) { SQ_DELETE_CLASS(EditPairDlg); - } + }*/ - SQInteger EditPairDlg_Ctor(HSQUIRRELVM v) + SQInteger EditPairDlg_Ctor(HSQUIRRELVM vm) { // (wxWindow* parent, // wxString& key, // wxString& value, // const wxString& title = _("Edit pair"), // BrowseMode allowBrowse = bmDisable); - StackHandler sa(v); + StackHandler sa(vm); EditPairDlg* dlg = nullptr; if (sa.GetParamCount() > 4) { dlg = new EditPairDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - *SqPlus::GetInstance(v, 4), - (EditPairDlg::BrowseMode)sa.GetInt(5)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + *sa.GetInstance( 4), + (EditPairDlg::BrowseMode)sa.GetValue(5)); } else if (sa.GetParamCount() > 3) { dlg = new EditPairDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - *SqPlus::GetInstance(v, 4)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + *sa.GetInstance( 4)); } else if (sa.GetParamCount() > 2) { dlg = new EditPairDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3)); + *sa.GetInstance( 2), + *sa.GetInstance( 3)); } else - return sa.ThrowError("EditPairDlg needs at least two arguments"); + return sa.ThrowError(_("EditPairDlg needs at least two arguments")); + - return SqPlus::PostConstruct(v, dlg, EditPairDlg_Dtor); + sq_setinstanceup(vm, 1, dlg); + sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; + //return SqPlus::PostConstruct(v, dlg, EditPairDlg_Dtor); } - SQInteger EditPathDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) + /*SQInteger EditPathDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) { SQ_DELETE_CLASS(EditPathDlg); - } + }*/ - SQInteger EditPathDlg_Ctor(HSQUIRRELVM v) + SQInteger EditPathDlg_Ctor(HSQUIRRELVM vm) { // (wxWindow* parent, // const wxString& path, // initial path @@ -163,145 +178,159 @@ namespace ScriptBindings // const bool wantDir = true, // whether to open a dir or a file dialog // const bool allowMultiSel = false, // whether to allow for multiple files selection // const wxString& filter = _("All files(*)|*")); // wildcard for files - StackHandler sa(v); + StackHandler sa(vm); EditPathDlg* dlg = nullptr; if (sa.GetParamCount() > 7) { dlg = new EditPathDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - *SqPlus::GetInstance(v, 4), - *SqPlus::GetInstance(v, 5), - sa.GetBool(6), - sa.GetBool(7), - *SqPlus::GetInstance(v, 8)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + *sa.GetInstance( 4), + *sa.GetInstance( 5), + sa.GetValue(6), + sa.GetValue(7), + *sa.GetInstance( 8)); } else if (sa.GetParamCount() > 6) { dlg = new EditPathDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - *SqPlus::GetInstance(v, 4), - *SqPlus::GetInstance(v, 5), - sa.GetBool(6), - sa.GetBool(7)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + *sa.GetInstance( 4), + *sa.GetInstance( 5), + sa.GetValue(6), + sa.GetValue(7)); } else if (sa.GetParamCount() > 5) { dlg = new EditPathDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - *SqPlus::GetInstance(v, 4), - *SqPlus::GetInstance(v, 5), - sa.GetBool(6)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + *sa.GetInstance( 4), + *sa.GetInstance( 5), + sa.GetValue(6)); } else if (sa.GetParamCount() > 4) { dlg = new EditPathDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - *SqPlus::GetInstance(v, 4), - *SqPlus::GetInstance(v, 5)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + *sa.GetInstance( 4), + *sa.GetInstance( 5)); } else if (sa.GetParamCount() > 3) { dlg = new EditPathDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - *SqPlus::GetInstance(v, 4)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + *sa.GetInstance( 4)); } else if (sa.GetParamCount() > 2) { dlg = new EditPathDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3)); + *sa.GetInstance( 2), + *sa.GetInstance( 3)); } else - return sa.ThrowError("EditPathDlg needs at least two arguments"); + return sa.ThrowError(_("EditPathDlg needs at least two arguments")); - return SqPlus::PostConstruct(v, dlg, EditPathDlg_Dtor); + + sq_setinstanceup(vm, 1, dlg); + sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; } - SQInteger GenericMultiLineNotesDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) + /*SQInteger GenericMultiLineNotesDlg_Dtor(SQUserPointer up, cb_unused SQInteger size) { SQ_DELETE_CLASS(GenericMultiLineNotesDlg); - } + }*/ - SQInteger GenericMultiLineNotesDlg_Ctor(HSQUIRRELVM v) + SQInteger GenericMultiLineNotesDlg_Ctor(HSQUIRRELVM vm) { // (wxWindow* parent, // const wxString& caption = _("Notes"), // const wxString& notes = wxEmptyString, // bool readOnly = true); - StackHandler sa(v); + StackHandler sa(vm); GenericMultiLineNotesDlg* dlg = nullptr; if (sa.GetParamCount() > 3) { dlg = new GenericMultiLineNotesDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3), - sa.GetBool(4)); + *sa.GetInstance( 2), + *sa.GetInstance( 3), + sa.GetValue(4)); } else if (sa.GetParamCount() > 2) { dlg = new GenericMultiLineNotesDlg(nullptr, - *SqPlus::GetInstance(v, 2), - *SqPlus::GetInstance(v, 3)); + *sa.GetInstance( 2), + *sa.GetInstance( 3)); } else if (sa.GetParamCount() > 1) { dlg = new GenericMultiLineNotesDlg(nullptr, - *SqPlus::GetInstance(v, 2)); + *sa.GetInstance( 2)); } else dlg = new GenericMultiLineNotesDlg(nullptr); - return SqPlus::PostConstruct(v, dlg, GenericMultiLineNotesDlg_Dtor); + sq_setinstanceup(vm, 1, dlg); + sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; } - SQInteger ShowModalForDialogs(HSQUIRRELVM v) + SQInteger ShowModalForDialogs(HSQUIRRELVM vm) { - StackHandler sa(v); + StackHandler sa(vm); SQUserPointer up = nullptr; - sq_getinstanceup(v, 1, &up, nullptr); + sq_getinstanceup(vm, 1, &up, nullptr); wxScrollingDialog* dlg = (wxScrollingDialog*)up; - return sa.Return(static_cast(dlg->ShowModal())); + sa.PushValue((dlg->ShowModal())); + return SC_RETURN_VALUE; } - void Register_UtilDialogs() + void Register_UtilDialogs(HSQUIRRELVM vm) { - SqPlus::BindConstant(EditPairDlg::bmBrowseForDirectory, "bmBrowseForDirectory"); - SqPlus::BindConstant(EditPairDlg::bmBrowseForFile, "bmBrowseForFile"); - SqPlus::BindConstant(EditPairDlg::bmDisable, "bmDisable"); - - SqPlus::SQClassDef("EditArrayFileDlg"). - staticFuncVarArgs(&EditArrayFileDlg_Ctor, "constructor", "*"). - staticFunc(&ShowModalForDialogs, "ShowModal"); - - SqPlus::SQClassDef("EditArrayOrderDlg"). - staticFuncVarArgs(&EditArrayOrderDlg_Ctor, "constructor", "*"). - staticFunc(&ShowModalForDialogs, "ShowModal"). - func(&EditArrayOrderDlg::SetArray, "SetArray"). - func(&EditArrayOrderDlg::GetArray, "GetArray"); - - SqPlus::SQClassDef("EditArrayStringDlg"). - staticFuncVarArgs(&EditArrayStringDlg_Ctor, "constructor", "*"). - staticFunc(&ShowModalForDialogs, "ShowModal"); - - SqPlus::SQClassDef("EditPairDlg"). - staticFuncVarArgs(&EditPairDlg_Ctor, "constructor", "*"). - staticFunc(&ShowModalForDialogs, "ShowModal"); - - SqPlus::SQClassDef("EditPathDlg"). - staticFuncVarArgs(&EditPathDlg_Ctor, "constructor", "*"). - staticFunc(&ShowModalForDialogs, "ShowModal"). - func(&EditPathDlg::GetPath, "GetPath"); - - SqPlus::SQClassDef("GenericMultiLineNotesDlg"). - staticFuncVarArgs(&GenericMultiLineNotesDlg_Ctor, "constructor", "*"). - staticFunc(&ShowModalForDialogs, "ShowModal"). - func(&GenericMultiLineNotesDlg::GetNotes, "GetNotes"); + Sqrat::ConstTable(vm).Const("bmBrowseForDirectory", EditPairDlg::bmBrowseForDirectory); + Sqrat::ConstTable(vm).Const("bmBrowseForFile", EditPairDlg::bmBrowseForFile); + Sqrat::ConstTable(vm).Const("bmDisable", EditPairDlg::bmDisable); + + Sqrat::Class > array_file_dlg(vm,"EditArrayFileDlg"); + array_file_dlg. + SquirrelFunc("constructor", &EditArrayFileDlg_Ctor). + StaticFunc("ShowModal", &ShowModalForDialogs); + Sqrat::RootTable(vm).Bind("EditArrayFileDlg",array_file_dlg); + + Sqrat::Class > array_order_dlg(vm,"EditArrayOrderDlg"); + array_order_dlg. + SquirrelFunc("constructor",&EditArrayOrderDlg_Ctor). + StaticFunc("ShowModal", &ShowModalForDialogs). + Func("SetArray", &EditArrayOrderDlg::SetArray). + Func("GetArray", &EditArrayOrderDlg::GetArray); + Sqrat::RootTable(vm).Bind("EditArrayOrderDlg",array_order_dlg); + + Sqrat::Class > array_string_dlg(vm,"EditArrayStringDlg"); + array_string_dlg. + SquirrelFunc("constructor", &EditArrayStringDlg_Ctor). + StaticFunc("ShowModal", &ShowModalForDialogs); + Sqrat::RootTable(vm).Bind("EditArrayStringDlg",array_string_dlg); + + Sqrat::Class >edit_pair_dlg(vm,"EditPairDlg"); + edit_pair_dlg. + SquirrelFunc("constructor", &EditPairDlg_Ctor). + StaticFunc("ShowModal", &ShowModalForDialogs); + + Sqrat::Class > edit_path_dlg(vm,"EditPathDlg"); + edit_path_dlg. SquirrelFunc("constructor", &EditPathDlg_Ctor). + StaticFunc("ShowModal", &ShowModalForDialogs). + Func("GetPath", &EditPathDlg::GetPath); + + Sqrat::Class > multi_line_note_dlg(vm,"GenericMultiLineNotesDlg"); + multi_line_note_dlg. + SquirrelFunc("constructor", &GenericMultiLineNotesDlg_Ctor). + StaticFunc("ShowModal", &ShowModalForDialogs). + Func("GetNotes", &GenericMultiLineNotesDlg::GetNotes); } } // namespace ScriptBindings From 6906a349358dd849e8abb9828fe1f5e088dbfbd9 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 17:05:49 +0200 Subject: [PATCH 06/16] [NOT COMPILE] Change cb internals squirrel binding from sqplus to sqrat (2/3) * port c::b internal functions binding to sqrat --- .../scripting/bindings/sc_base_types.h | 110 +- .../scripting/bindings/scriptbindings.h | 7 +- src/sdk/scripting/bindings/scriptbindings.cpp | 1581 +++++++++++------ 3 files changed, 1074 insertions(+), 624 deletions(-) diff --git a/src/include/scripting/bindings/sc_base_types.h b/src/include/scripting/bindings/sc_base_types.h index 36fdabd0c1..8ba851a50b 100644 --- a/src/include/scripting/bindings/sc_base_types.h +++ b/src/include/scripting/bindings/sc_base_types.h @@ -24,84 +24,46 @@ #include #include #include -#include +#include +#include +#include +#include -// wx primitives and types -DECLARE_INSTANCE_TYPE(wxArrayString); -DECLARE_INSTANCE_TYPE(wxColour); -DECLARE_INSTANCE_TYPE(wxFileName); -DECLARE_INSTANCE_TYPE(wxPoint); -DECLARE_INSTANCE_TYPE(wxSize); -DECLARE_INSTANCE_TYPE(wxString); - -// C::B primitives and types -DECLARE_INSTANCE_TYPE(ConfigManager); -DECLARE_INSTANCE_TYPE(EditorManager); -DECLARE_INSTANCE_TYPE(UserVariableManager); -DECLARE_INSTANCE_TYPE(ScriptingManager); -DECLARE_INSTANCE_TYPE(EditorBase); -DECLARE_INSTANCE_TYPE(cbEditor); -DECLARE_INSTANCE_TYPE(CompileOptionsBase); -DECLARE_INSTANCE_TYPE(CompileTargetBase); -DECLARE_INSTANCE_TYPE(ProjectBuildTarget); -DECLARE_INSTANCE_TYPE(cbProject); -DECLARE_INSTANCE_TYPE(ProjectFile); -DECLARE_INSTANCE_TYPE(ProjectManager); -DECLARE_INSTANCE_TYPE(CompilerFactory); -DECLARE_INSTANCE_TYPE(PluginInfo); -DECLARE_INSTANCE_TYPE(FileTreeData); -using SqPlus::GetTypeName; - -// make SqPlus aware of enum-type arguments -#define DECLARE_ENUM_TYPE(T) \ -namespace SqPlus \ -{ \ - inline void Push(HSQUIRRELVM v,T value) { sq_pushinteger(v,value); } \ - inline bool Match(TypeWrapper, HSQUIRRELVM v, int idx) { return sq_gettype(v,idx) == OT_INTEGER; } \ - inline T Get(TypeWrapper,HSQUIRRELVM v,int idx) { SQInteger i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return (T)i; } \ +#define DEFINE_SQRAT_ENUM(N) namespace Sqrat \ +{ \ +template<> \ +struct Var { \ + N value; \ + Var(HSQUIRRELVM v, SQInteger idx) { \ + if (!Sqrat::Error::Occurred(v)) { \ + SQInteger tmp = 0; \ + sq_getinteger(v,idx,&tmp); \ + value = static_cast(tmp); \ + } \ + } \ + static void push(HSQUIRRELVM v, const N value) { \ + sq_pushinteger(v,static_cast(value)); \ + } \ +}; \ } -DECLARE_ENUM_TYPE(wxPathFormat); -DECLARE_ENUM_TYPE(wxPathNormalize); -DECLARE_ENUM_TYPE(PrintColourMode); -DECLARE_ENUM_TYPE(OptionsRelation); -DECLARE_ENUM_TYPE(OptionsRelationType); -DECLARE_ENUM_TYPE(TargetType); -DECLARE_ENUM_TYPE(PCHMode); -DECLARE_ENUM_TYPE(MakeCommand); -DECLARE_ENUM_TYPE(TemplateOutputType); -DECLARE_ENUM_TYPE(SearchDirs); -DECLARE_ENUM_TYPE(ModuleType); -DECLARE_ENUM_TYPE(FileTreeData::FileTreeDataKind); -DECLARE_ENUM_TYPE(TargetFilenameGenerationPolicy); -using SqPlus::Push; +DEFINE_SQRAT_ENUM(TemplateOutputType); +DEFINE_SQRAT_ENUM(FileType); +DEFINE_SQRAT_ENUM(SearchDirs); +DEFINE_SQRAT_ENUM(SupportedPlatforms); +DEFINE_SQRAT_ENUM(TargetFilenameGenerationPolicy); +DEFINE_SQRAT_ENUM(ModuleType); +DEFINE_SQRAT_ENUM(PrintColourMode); +DEFINE_SQRAT_ENUM(PrintScope); +DEFINE_SQRAT_ENUM(PCHMode); +DEFINE_SQRAT_ENUM(MakeCommand); +DEFINE_SQRAT_ENUM(TargetType); +DEFINE_SQRAT_ENUM(OptionsRelation); +DEFINE_SQRAT_ENUM(OptionsRelationType); +DEFINE_SQRAT_ENUM(wxPathNormalize); +DEFINE_SQRAT_ENUM(wxPathFormat); +DEFINE_SQRAT_ENUM(wxCheckBoxState); -namespace SqPlus -{ - // make SqPlus aware of wxString arguments -// inline void Push(HSQUIRRELVM v,const wxString& value) { sq_pushstring(v,cbU2C(value),-1); } -// inline bool Match(TypeWrapper, HSQUIRRELVM v, int idx) { return sq_gettype(v,idx) == OT_STRING; } -// inline wxString Get(TypeWrapper,HSQUIRRELVM v,int idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return cbC2U(s); } - // type info for short unsigned int (missing from SqPlus) - template<> - struct TypeInfo - { - const SQChar * typeName; - TypeInfo() : typeName(sqT("int")) {} - enum {TypeID=VAR_TYPE_INT,Size=sizeof(unsigned short)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } - }; -#ifdef _SQ64 - template<> - struct TypeInfo - { - const SQChar * typeName; - TypeInfo() : typeName(sqT("int")) {} - enum {TypeID=VAR_TYPE_INT,Size=sizeof(SQInt32)}; - operator ScriptVarType() { return ScriptVarType(TypeID); } - }; -#endif -} #endif // SC_BASE_TYPES_H diff --git a/src/include/scripting/bindings/scriptbindings.h b/src/include/scripting/bindings/scriptbindings.h index 5b0f14d73b..6675a010a4 100644 --- a/src/include/scripting/bindings/scriptbindings.h +++ b/src/include/scripting/bindings/scriptbindings.h @@ -6,9 +6,14 @@ #ifndef SCRIPTBINDINGS_H #define SCRIPTBINDINGS_H +#include +#include + + + namespace ScriptBindings { - void RegisterBindings(); + void RegisterBindings(HSQUIRRELVM vm); } #endif // SCRIPTBINDINGS_H diff --git a/src/sdk/scripting/bindings/scriptbindings.cpp b/src/sdk/scripting/bindings/scriptbindings.cpp index 13624bbfd2..170772d62b 100644 --- a/src/sdk/scripting/bindings/scriptbindings.cpp +++ b/src/sdk/scripting/bindings/scriptbindings.cpp @@ -9,741 +9,1224 @@ #include #ifndef CB_PRECOMP - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif #include "cbstyledtextctrl.h" -#include "scriptbindings.h" +#include "scripting/bindings/scriptbindings.h" #include -#include "sc_base_types.h" +#include "scripting/bindings/sc_base_types.h" +#include "scripting/bindings/sc_cb_vm.h" +#include "scripting/bindings/sq_wx/sq_wx.h" + +/** \defgroup Squirrel Squirrel Binding + * \brief The Squirrel scripting Module of Code Blocks + */ namespace ScriptBindings { - extern void Register_Constants(); - extern void Register_Globals(); - extern void Register_wxTypes(); - extern void Register_Dialog(); - extern void Register_ProgressDialog(); - extern void Register_UtilDialogs(); - extern void Register_IO(); - extern void Register_ScriptPlugin(); - - SQInteger ConfigManager_Read(HSQUIRRELVM v) - { - StackHandler sa(v); - int paramCount = sa.GetParamCount(); +// FIXME (bluehazzard#1#): Is there a possibility to remove this forward declaration? +extern void Register_Constants(HSQUIRRELVM vm); +extern void Register_Globals(HSQUIRRELVM vm); +extern void Register_wxTypes(HSQUIRRELVM vm); +extern void Register_Dialog(HSQUIRRELVM vm); +extern void Register_ProgressDialog(HSQUIRRELVM vm); +extern void Register_UtilDialogs(HSQUIRRELVM vm); +extern void Register_IO(HSQUIRRELVM vm); +extern void Register_ScriptPlugin(HSQUIRRELVM vm); + +/** \defgroup sq_config_manager Squirrel Config-Manager binding + * \ingroup Squirrel + * \brief The binding for the Config Manager to Squirrel. It an be used to safe and load configuration Data from the global/local Configuration-File that C::B uses + */ + +/** \ingroup sq_config_manager + *### Read(key,default_value) + * Reads an Value from the Config file + * + * - __key__ A Key which represents the Value + * - __default_value__ A default value if the key was not found in the config file + * + * The first parameter is a Key which represents the Value in the Config file. The second parameter defines a default value which will be returned if the key was not found + * Supported types are int, bool, float and wxString. + */ +SQInteger ConfigManager_Read(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + int paramCount = sa.GetParamCount(); + try + { if (paramCount == 3) { - wxString key = *SqPlus::GetInstance(v, 2); - if (sa.GetType(3) == OT_INTEGER) - return sa.Return((SQInteger)Manager::Get()->GetConfigManager(_T("scripts"))->ReadInt(key, sa.GetInt(3))); - else if (sa.GetType(3) == OT_BOOL) - return sa.Return(Manager::Get()->GetConfigManager(_T("scripts"))->ReadBool(key, sa.GetBool(3))); - else if (sa.GetType(3) == OT_FLOAT) - return sa.Return((float)Manager::Get()->GetConfigManager(_T("scripts"))->ReadDouble(key, sa.GetFloat(3))); + wxString key = *sa.GetInstance(2); + if(key.IsEmpty()) + return sa.ThrowError(_("ConfigManager.read: have no key")); + + SQObjectType config_type = sq_gettype(vm,3); + if (config_type == OT_INTEGER) + { + Sqrat::Var val(vm,3); + int value = Manager::Get()->GetConfigManager(_T("scripts"))->ReadInt(key, val.value); + sa.PushValue(value); + } + else if (config_type == OT_BOOL) + { + Sqrat::Var val(vm,3); + bool value = Manager::Get()->GetConfigManager(_T("scripts"))->ReadBool(key, val.value); + sa.PushValue(value); + } + else if (config_type == OT_FLOAT) + { + Sqrat::Var val(vm,3); + bool value = Manager::Get()->GetConfigManager(_T("scripts"))->ReadDouble(key, val.value); + sa.PushValue(value); + } else { - wxString val = *SqPlus::GetInstance(v, 3); + wxString val = *sa.GetInstance(3); wxString ret = Manager::Get()->GetConfigManager(_T("scripts"))->Read(key, val); - return SqPlus::ReturnCopy(v, ret); + sa.PushInstanceCopy(ret); } + // TODO (bluehazzard#1#): Not sure if this works... + if(sa.HasError()) + return SC_RETURN_FAILED; + else + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"ConfigManager::Read\""); } - SQInteger ConfigManager_Write(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"ConfigManager::Read\"")); +} + +/** \ingroup sq_config_manager + *### Write(key,value) + * Writes an value to the configuration file + * + * - __key__ A Key which represents the Value + * - __value__ The value written to the file + * + * The first parameter is a Key which represents the Value in the Config file. The second parameter defines a default value which will be returned if the key was not found + * Supported types are int, bool, float and wxString. + */ +SQInteger ConfigManager_Write(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + int paramCount = sa.GetParamCount(); + try { - StackHandler sa(v); - int paramCount = sa.GetParamCount(); if (paramCount == 3) { - wxString key = *SqPlus::GetInstance(v, 2); - if (sa.GetType(3) == OT_INTEGER) + wxString *key = sa.GetInstance(2); + + if(key == NULL) + return sa.ThrowError(_T("have no key")); + + SQObjectType config_type = sq_gettype(vm,3); + if (config_type == OT_INTEGER) { - Manager::Get()->GetConfigManager(_T("scripts"))->Write(key, (int)sa.GetInt(3)); - return SQ_OK; + int value = sa.GetValue(3); + Manager::Get()->GetConfigManager(_T("scripts"))->Write(*key, value); + return SC_RETURN_OK; } - else if (sa.GetType(3) == OT_BOOL) + else if (config_type == OT_BOOL) { - Manager::Get()->GetConfigManager(_T("scripts"))->Write(key, (bool)sa.GetBool(3)); - return SQ_OK; + bool value = sa.GetValue(3); + Manager::Get()->GetConfigManager(_T("scripts"))->Write(*key, value); + return SC_RETURN_OK; } - else if (sa.GetType(3) == OT_FLOAT) + else if (config_type == OT_FLOAT) { - Manager::Get()->GetConfigManager(_T("scripts"))->Write(key, sa.GetFloat(3)); - return SQ_OK; + float value = sa.GetValue(3); + Manager::Get()->GetConfigManager(_T("scripts"))->Write(*key, value); + return SC_RETURN_OK; } else { - Manager::Get()->GetConfigManager(_T("scripts"))->Write(key, *SqPlus::GetInstance(v, 3)); - return SQ_OK; + wxString val = sa.GetValue(3); + Manager::Get()->GetConfigManager(_T("scripts"))->Write(*key, val); + return SC_RETURN_OK; } + } else if (paramCount == 4) { - wxString key = *SqPlus::GetInstance(v, 2); - wxString val = *SqPlus::GetInstance(v, 3); + wxString *key = sa.GetInstance(2); + wxString *val = sa.GetInstance(3); if (sa.GetType(4) == OT_BOOL) { - Manager::Get()->GetConfigManager(_T("scripts"))->Write(key, val, sa.GetBool(4)); - return SQ_OK; + bool value = sa.GetInstance(4); + Manager::Get()->GetConfigManager(_T("scripts"))->Write(*key, *val, value); + return SC_RETURN_OK; } } - return sa.ThrowError("Invalid arguments to \"ConfigManager::Write\""); } - SQInteger EditorManager_GetBuiltinEditor(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_T("Invalid arguments to \"ConfigManager::Write\"")); +} + +/** \defgroup sq_editor_manager SquirrelEditor-Manager binding + * \ingroup Squirrel + * \brief The binding for the Editor Manager to Squirrel. + */ + +/** \ingroup sq_editor_manager + *### GetBuiltinEditor(id) + * Writes an value to the configuration file + * + * - __id__ The identifier of the Editor you want + * + * Supported types are int and wxString. + */ +SQInteger EditorManager_GetBuiltinEditor(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { cbEditor* ed = nullptr; if (sa.GetType(2) == OT_INTEGER) - ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(sa.GetInt(2)); + { + ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(sa.GetValue(2)); + } else - ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(*SqPlus::GetInstance(v, 2)); - SqPlus::Push(v, ed); - return 1; + { + wxString *val = sa.GetInstance(2); + ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(*val); + } + sa.PushValue(ed); + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"EditorManager::GetBuiltinEditor\""); } - SQInteger EditorManager_Open(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"EditorManager::GetBuiltinEditor\"")); +} + +/** \ingroup sq_editor_manager + *### Open(FileName) + * Opens a file in the editor + * + * - __FileName__ The Name of the file to be opened + * + * Supported types are wxString. + */ +SQInteger EditorManager_Open(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { - cbEditor* ed = Manager::Get()->GetEditorManager()->Open(*SqPlus::GetInstance(v, 2)); - SqPlus::Push(v, ed); - return 1; + wxString *val = sa.GetInstance(2); + cbEditor* ed = Manager::Get()->GetEditorManager()->Open(*val); + sa.PushValue(ed); + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"EditorManager::Open\""); + return sa.ThrowError(_("Invalid arguments to \"EditorManager::Open\"")); } - SQInteger EditorManager_Close(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } +} + + +/** \ingroup sq_editor_manager + *### Close(id) + * Closes an editor + * + * - __id__ The identifier of the Editor you want close + * + * Supported types are int and wxString. + */ +SQInteger EditorManager_Close(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { if (sa.GetType(2) == OT_INTEGER) - return sa.Return(Manager::Get()->GetEditorManager()->Close(sa.GetInt(2))); + { + sa.PushValue(Manager::Get()->GetEditorManager()->Close(sa.GetValue(2))); + return SC_RETURN_VALUE; + } else - return sa.Return(Manager::Get()->GetEditorManager()->Close(*SqPlus::GetInstance(v, 2))); + { + wxString *val = sa.GetInstance(2); + sa.PushValue(Manager::Get()->GetEditorManager()->Close(*val)); + return SC_RETURN_VALUE; + } } - return sa.ThrowError("Invalid arguments to \"EditorManager::Close\""); } - SQInteger EditorManager_Save(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"EditorManager::Close\"")); +} + +/** \ingroup sq_editor_manager + *### Save(id) + * Save the content from the Editor with the _id_ + * + * - __id__ The identifier of the Editor you want to save + * + * Supported types are int and wxString. + */ +SQInteger EditorManager_Save(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { if (sa.GetType(2) == OT_INTEGER) - return sa.Return(Manager::Get()->GetEditorManager()->Save(sa.GetInt(2))); + { + sa.PushValue(Manager::Get()->GetEditorManager()->Save(sa.GetValue(2))); + return SC_RETURN_VALUE; + } else - return sa.Return(Manager::Get()->GetEditorManager()->Save(*SqPlus::GetInstance(v, 2))); + { + wxString *val = sa.GetInstance(2); + sa.PushValue(Manager::Get()->GetEditorManager()->Save(*val)); + return SC_RETURN_VALUE; + } } - return sa.ThrowError("Invalid arguments to \"EditorManager::Save\""); } - SQInteger cbProject_RemoveFile(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"EditorManager::Save\"")); +} + +/** \defgroup sq_project Squirrel Project Manager binding + * \ingroup Squirrel + * \brief The binding for the Project Manager to Squirrel. + * + * Can be used to manage project and build targets + */ + + +/** \ingroup sq_project + *### RemoveFile(ProjectFile) + * Remove the _ProjectFile_ from the project + * + * - __ProjectFile__ The identifier of the Editor you want to save [wxString | int] + * + */ +SQInteger cbProject_RemoveFile(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { - cbProject* prj = SqPlus::GetInstance(v, 1); + cbProject* prj = sa.GetInstance(1); if (sa.GetType(2) == OT_INTEGER) - return sa.ThrowError("Invalid arguments to \"cbProject::RemoveFile\""); + { + return sa.ThrowError(_("Invalid arguments to \"cbProject::RemoveFile\"")); + } else - return sa.Return(prj->RemoveFile(SqPlus::GetInstance(v, 2))); + { + ProjectFile *val = sa.GetInstance(2); + sa.PushValue(prj->RemoveFile(val)); + return SC_RETURN_VALUE; + } } - return sa.ThrowError("Invalid arguments to \"cbProject::RemoveFile\""); } - SQInteger cbProject_AddFile(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbProject::RemoveFile\"")); +} + +/** \ingroup sq_project + *### AddFile(targetName,filename,compile,link,weight) + * Add a file to the _targetName_ build-target + * + * - __targetName__ targetName The name of the build target to add this file to [wxString] + * - __filename__ The file's filename. This *must* be a filename relative to the project's path. [wxString] + * - __compile__ If true this file is compiled when building the project. [bool] + * - __link__ If true this file is linked when building the project. [bool] + * - __weight__ A value between zero and 100 (defaults to 50). Smaller weight, makes the file compile earlier than those with larger weight. [int] + * + * return Project file + */ +SQInteger cbProject_AddFile(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount >= 3) { - cbProject* prj = SqPlus::GetInstance(v, 1); - wxString str = *SqPlus::GetInstance(v, 3); - bool b1 = paramCount >= 4 ? sa.GetBool(4) : true; - bool b2 = paramCount >= 5 ? sa.GetBool(5) : true; - int i = paramCount == 6 ? sa.GetInt(6) : 50; + cbProject* prj = sa.GetInstance(1); + wxString str = *sa.GetInstance(3); + bool b1 = true; + bool b2 = true; + int i = 50; + if(paramCount >= 4) + { + b1 = sa.GetValue(4); + } + if(paramCount >= 5) + { + b2 = sa.GetValue(5); + } + if(paramCount == 6) + { + i = sa.GetValue(6); + } + if(Sqrat::Error::Occurred(vm)) + { + return sa.ThrowError(_("Invalid arguments to \"cbProject::AddFile\"")); + } + ProjectFile* pf = nullptr; - if (sa.GetType(2) == OT_INTEGER) - pf = prj->AddFile(sa.GetInt(2), str, b1, b2, i); + if (sq_gettype(vm,2) == OT_INTEGER) + { + SQInteger id = sa.GetValue(2); + pf = prj->AddFile(id, str, b1, b2, i); + } else - pf = prj->AddFile(*SqPlus::GetInstance(v, 2), str, b1, b2, i); - SqPlus::Push(v, pf); - return 1; + pf = prj->AddFile(*sa.GetInstance(2), str, b1, b2, i); + + sa.PushValue(pf); + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"cbProject::AddFile\""); } - SQInteger cbProject_GetBuildTarget(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbProject::AddFile\"")); +} + +SQInteger cbProject_GetBuildTarget(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { - cbProject* prj = SqPlus::GetInstance(v, 1); + cbProject* prj = sa.GetInstance(1); ProjectBuildTarget* bt = nullptr; - if (sa.GetType(2) == OT_INTEGER) - bt = prj->GetBuildTarget(sa.GetInt(2)); - else - bt = prj->GetBuildTarget(*SqPlus::GetInstance(v, 2)); - SqPlus::Push(v, bt); - return 1; + try + { + if (sa.GetType(2) == OT_INTEGER) + { + bt = prj->GetBuildTarget(sa.GetValue(2)); + //if(bt == nullptr) + //return sa.ThrowError(wxString::Format(_("Could not find build Targte Nr. %d"),sa.GetValue(2))); + } + else + { + bt = prj->GetBuildTarget(*sa.GetInstance(2)); + //if(bt == nullptr) + //return sa.ThrowError(_("Could not find build Targte") + *sa.GetInstance(2)); + } + } + catch(CBScriptException &e) + { + // a error occurred, we return a null ptr + bt = nullptr; + } + + sa.PushInstance(bt); + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"cbProject::GetBuildTarget\""); } - SQInteger cbProject_RenameBuildTarget(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbProject::GetBuildTarget\"")); +} + +SQInteger cbProject_RenameBuildTarget(HSQUIRRELVM v) +{ + StackHandler sa(v); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 3) { - cbProject* prj = SqPlus::GetInstance(v, 1); + cbProject* prj = sa.GetInstance(1); if (sa.GetType(2) == OT_INTEGER) - return sa.Return(prj->RenameBuildTarget(sa.GetInt(2), *SqPlus::GetInstance(v, 3))); + { + sa.PushValue(prj->RenameBuildTarget(sa.GetValue(2), *sa.GetInstance(3))); + return SC_RETURN_VALUE; + } else - return sa.Return(prj->RenameBuildTarget(*SqPlus::GetInstance(v, 2), *SqPlus::GetInstance(v, 3))); + { + sa.PushValue(prj->RenameBuildTarget(*sa.GetInstance(2), *sa.GetInstance(3))); + return SC_RETURN_VALUE; + } + } - return sa.ThrowError("Invalid arguments to \"cbProject::RenameBuildTarget\""); } - SQInteger cbProject_DuplicateBuildTarget(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbProject::RenameBuildTarget\"")); +} + +SQInteger cbProject_DuplicateBuildTarget(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 3) { - cbProject* prj = SqPlus::GetInstance(v, 1); + cbProject* prj = sa.GetInstance(1); ProjectBuildTarget* bt = nullptr; if (sa.GetType(2) == OT_INTEGER) - bt = prj->DuplicateBuildTarget(sa.GetInt(2), *SqPlus::GetInstance(v, 3)); + { + bt = prj->DuplicateBuildTarget(sa.GetValue(2), *sa.GetInstance(3)); + } else - bt = prj->DuplicateBuildTarget(*SqPlus::GetInstance(v, 2), *SqPlus::GetInstance(v, 3)); - SqPlus::Push(v, bt); - return 1; + { + bt = prj->DuplicateBuildTarget(*sa.GetInstance(2), *sa.GetInstance(3)); + } + sa.PushValue(bt); + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"cbProject::DuplicateBuildTarget\""); } - SQInteger cbProject_RemoveBuildTarget(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbProject::DuplicateBuildTarget\"")); +} + + +SQInteger cbProject_RemoveBuildTarget(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { - cbProject* prj = SqPlus::GetInstance(v, 1); + cbProject* prj = sa.GetInstance(1); if (sa.GetType(2) == OT_INTEGER) - return sa.Return(prj->RemoveBuildTarget(sa.GetInt(2))); + { + sa.PushValue(prj->RemoveBuildTarget(sa.GetValue(2))); + } else - return sa.Return(prj->RemoveBuildTarget(*SqPlus::GetInstance(v, 2))); + { + sa.PushValue(prj->RemoveBuildTarget(*sa.GetInstance(2))); + } + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"cbProject::RemoveBuildTarget\""); } - SQInteger cbProject_ExportTargetAsProject(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbProject::RemoveBuildTarget\"")); +} + +SQInteger cbProject_ExportTargetAsProject(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { - cbProject* prj = SqPlus::GetInstance(v, 1); + cbProject* prj = sa.GetInstance(1); if (sa.GetType(2) == OT_INTEGER) - return sa.Return(prj->ExportTargetAsProject(sa.GetInt(2))); + { + sa.PushValue(prj->ExportTargetAsProject(sa.GetValue(2))); + } else - return sa.Return(prj->ExportTargetAsProject(*SqPlus::GetInstance(v, 2))); + { + sa.PushValue(prj->ExportTargetAsProject(*sa.GetInstance(2))); + } + return SC_RETURN_VALUE; } - return sa.ThrowError("Invalid arguments to \"cbProject::ExportTargetAsProject\""); } - SQInteger ProjectManager_AddFileToProject(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbProject::ExportTargetAsProject\"")); +} + +SQInteger ProjectManager_AddFileToProject(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 4) { if (sa.GetType(4) == OT_INTEGER) { - wxString fname = *SqPlus::GetInstance(v, 2); - cbProject* prj = SqPlus::GetInstance(v, 3); - int idx = sa.GetInt(4); - return sa.Return((SQInteger)Manager::Get()->GetProjectManager()->AddFileToProject(fname, prj, idx)); + wxString fname = *sa.GetInstance(2); + cbProject* prj = sa.GetInstance(3); + int idx = sa.GetValue(4); + sa.PushValue(Manager::Get()->GetProjectManager()->AddFileToProject(fname, prj, idx)); + return SC_RETURN_VALUE; } } - return sa.ThrowError("Invalid arguments to \"ProjectManager::AddFileToProject\""); } + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"ProjectManager::AddFileToProject\"")); +} - SQInteger ProjectManager_GetProjectCount(HSQUIRRELVM v) +SQInteger ProjectManager_GetProjectCount(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int count = sa.GetParamCount(); if (count != 1) - return sa.ThrowError("Invalid arguments to \"ProjectManager::GetProjectCount\""); + return sa.ThrowError(_("Invalid arguments to \"ProjectManager::GetProjectCount\"")); else { - ProjectManager *manager = SqPlus::GetInstance(v, 1); + ProjectManager *manager = sa.GetInstance(1); int project_count = manager->GetProjects()->GetCount(); - return sa.Return((SQInteger)project_count); + sa.PushValue(project_count); + return SC_RETURN_VALUE; } } + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } +} - SQInteger ProjectManager_GetProject(HSQUIRRELVM v) +SQInteger ProjectManager_GetProject(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int count = sa.GetParamCount(); if (count != 2) - return sa.ThrowError("Invalid arguments to \"ProjectManager::GetProject\""); + return sa.ThrowError(_("Invalid arguments to \"ProjectManager::GetProject\"")); else { - ProjectManager *manager = SqPlus::GetInstance(v, 1); - int index = sa.GetInt(2); + ProjectManager *manager = sa.GetInstance(1); + int index = sa.GetValue(2); int project_count = manager->GetProjects()->GetCount(); if(index >= project_count) - return sa.ThrowError("Index out of bounds in \"ProjectManager::GetProject\""); + return sa.ThrowError(_("Index out of bounds in \"ProjectManager::GetProject\"")); else { cbProject *project = (*manager->GetProjects())[index]; - SqPlus::Push(v, project); - return 1; + sa.PushValue(project); + return SC_RETURN_VALUE; } } } - SQInteger ProjectManager_RebuildTree(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } +} +SQInteger ProjectManager_RebuildTree(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 1) { - ProjectManager *manager = SqPlus::GetInstance(v, 1); + ProjectManager *manager = sa.GetInstance(1); if (manager) { manager->GetUI().RebuildTree(); - return sa.Return(); + return SC_RETURN_OK; } - return sa.ThrowError("'this' is NULL!?! (type of ProjectManager*)"); + return sa.ThrowError(_("'this' is NULL!?! (type of ProjectManager*)")); } - return sa.ThrowError("Invalid arguments to \"ProjectManager::RebuildTree\""); } + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"ProjectManager::RebuildTree\"")); +} - SQInteger cbEditor_SetText(HSQUIRRELVM v) +SQInteger cbEditor_SetText(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) { - cbEditor* self = SqPlus::GetInstance(v, 1); + cbEditor* self = sa.GetInstance(1); if (self) { - self->GetControl()->SetText(*SqPlus::GetInstance(v, 2)); - return sa.Return(); + self->GetControl()->SetText(*sa.GetInstance(2)); + return SC_RETURN_OK; } - return sa.ThrowError("'this' is NULL!?! (type of cbEditor*)"); + return sa.ThrowError(_("'this' is NULL!?! (type of cbEditor*)")); } - return sa.ThrowError("Invalid arguments to \"cbEditor::SetText\""); } - SQInteger cbEditor_GetText(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbEditor::SetText\"")); +} + +SQInteger cbEditor_GetText(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 1) { - cbEditor* self = SqPlus::GetInstance(v, 1); + cbEditor* self = sa.GetInstance(1); if (self) { wxString str = self->GetControl()->GetText(); - return SqPlus::ReturnCopy(v, str); + sa.PushInstanceCopy(str); + return SC_RETURN_VALUE; } - return sa.ThrowError("'this' is NULL!?! (type of cbEditor*)"); + return sa.ThrowError(_("'this' is NULL!?! (type of cbEditor*)")); } - return sa.ThrowError("Invalid arguments to \"cbEditor::GetText\""); } - SQInteger CompilerFactory_GetCompilerIndex(HSQUIRRELVM v) + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + return sa.ThrowError(_("Invalid arguments to \"cbEditor::GetText\"")); +} + +SQInteger CompilerFactory_GetCompilerIndex(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try { - StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 2) - return sa.Return((SQInteger)CompilerFactory::GetCompilerIndex(*SqPlus::GetInstance(v, 2))); - return sa.ThrowError("Invalid arguments to \"CompilerFactory::GetCompilerIndex\""); - } - - wxString CompilerFactory_GetCompilerIDByName(const wxString &name) - { - Compiler *compiler = CompilerFactory::GetCompilerByName(name); - return (compiler ? compiler->GetID() : wxString(wxEmptyString)); - } - - void RegisterBindings() - { - if (!SquirrelVM::GetVMPtr()) - cbThrow(_T("Scripting engine not initialized!?")); - - Register_wxTypes(); - Register_Constants(); - Register_Globals(); - Register_IO(); // IO is enabled, but just for harmless functions - Register_Dialog(); - Register_ProgressDialog(); - Register_UtilDialogs(); - - SqPlus::SQClassDef("ConfigManager"). - staticFuncVarArgs(&ConfigManager_Read, "Read", "*"). - staticFuncVarArgs(&ConfigManager_Write, "Write", "*"); - - SqPlus::SQClassDef("ProjectFile"). - func(&ProjectFile::AddBuildTarget, "AddBuildTarget"). - func(&ProjectFile::RenameBuildTarget, "RenameBuildTarget"). - func(&ProjectFile::RemoveBuildTarget, "RemoveBuildTarget"). - func(&ProjectFile::GetBuildTargets, "GetBuildTargets"). - func(&ProjectFile::GetBaseName, "GetBaseName"). - func(&ProjectFile::GetObjName, "GetObjName"). - func(&ProjectFile::SetObjName, "SetObjName"). - func(&ProjectFile::GetParentProject, "GetParentProject"). - func(&ProjectFile::SetUseCustomBuildCommand, "SetUseCustomBuildCommand"). - func(&ProjectFile::SetCustomBuildCommand, "SetCustomBuildCommand"). - func(&ProjectFile::GetUseCustomBuildCommand, "GetUseCustomBuildCommand"). - func(&ProjectFile::GetCustomBuildCommand, "GetCustomBuildCommand"). - var(&ProjectFile::file, "file"). - var(&ProjectFile::relativeFilename, "relativeFilename"). - var(&ProjectFile::relativeToCommonTopLevelPath, "relativeToCommonTopLevelPath"). - var(&ProjectFile::compile, "compile"). - var(&ProjectFile::link, "link"). - var(&ProjectFile::weight, "weight"). - var(&ProjectFile::compilerVar, "compilerVar"). - var(&ProjectFile::buildTargets, "buildTargets"); - - SqPlus::SQClassDef("CompileOptionsBase"). - func(&CompileOptionsBase::AddPlatform, "AddPlatform"). - func(&CompileOptionsBase::RemovePlatform, "RemovePlatform"). - func(&CompileOptionsBase::SetPlatforms, "SetPlatforms"). - func(&CompileOptionsBase::GetPlatforms, "GetPlatforms"). - func(&CompileOptionsBase::SupportsCurrentPlatform, "SupportsCurrentPlatform"). - func(&CompileOptionsBase::SetLinkerOptions, "SetLinkerOptions"). - func(&CompileOptionsBase::SetLinkLibs, "SetLinkLibs"). - func(&CompileOptionsBase::SetCompilerOptions, "SetCompilerOptions"). - func(&CompileOptionsBase::SetResourceCompilerOptions, "SetResourceCompilerOptions"). - func(&CompileOptionsBase::SetIncludeDirs, "SetIncludeDirs"). - func(&CompileOptionsBase::SetResourceIncludeDirs, "SetResourceIncludeDirs"). - func(&CompileOptionsBase::SetLibDirs, "SetLibDirs"). - func(&CompileOptionsBase::SetCommandsBeforeBuild, "SetCommandsBeforeBuild"). - func(&CompileOptionsBase::SetCommandsAfterBuild, "SetCommandsAfterBuild"). - func(&CompileOptionsBase::GetLinkerOptions, "GetLinkerOptions"). - func(&CompileOptionsBase::GetLinkLibs, "GetLinkLibs"). - func(&CompileOptionsBase::GetCompilerOptions, "GetCompilerOptions"). - func(&CompileOptionsBase::GetResourceCompilerOptions, "GetResourceCompilerOptions"). - func(&CompileOptionsBase::GetIncludeDirs, "GetIncludeDirs"). - func(&CompileOptionsBase::GetResourceIncludeDirs, "GetResourceIncludeDirs"). - func(&CompileOptionsBase::GetLibDirs, "GetLibDirs"). - func(&CompileOptionsBase::GetCommandsBeforeBuild, "GetCommandsBeforeBuild"). - func(&CompileOptionsBase::GetCommandsAfterBuild, "GetCommandsAfterBuild"). - func(&CompileOptionsBase::GetModified, "GetModified"). - func(&CompileOptionsBase::SetModified, "SetModified"). - func(&CompileOptionsBase::AddLinkerOption, "AddLinkerOption"). - func(&CompileOptionsBase::AddLinkLib, "AddLinkLib"). - func(&CompileOptionsBase::AddCompilerOption, "AddCompilerOption"). - func(&CompileOptionsBase::AddResourceCompilerOption, "AddResourceCompilerOption"). - func(&CompileOptionsBase::AddIncludeDir, "AddIncludeDir"). - func(&CompileOptionsBase::AddResourceIncludeDir, "AddResourceIncludeDir"). - func(&CompileOptionsBase::AddLibDir, "AddLibDir"). - func(&CompileOptionsBase::AddCommandsBeforeBuild, "AddCommandsBeforeBuild"). - func(&CompileOptionsBase::AddCommandsAfterBuild, "AddCommandsAfterBuild"). - func(&CompileOptionsBase::ReplaceLinkerOption, "ReplaceLinkerOption"). - func(&CompileOptionsBase::ReplaceLinkLib, "ReplaceLinkLib"). - func(&CompileOptionsBase::ReplaceCompilerOption, "ReplaceCompilerOption"). - func(&CompileOptionsBase::ReplaceResourceCompilerOption, "ReplaceResourceCompilerOption"). - func(&CompileOptionsBase::ReplaceIncludeDir, "ReplaceIncludeDir"). - func(&CompileOptionsBase::ReplaceResourceIncludeDir, "ReplaceResourceIncludeDir"). - func(&CompileOptionsBase::ReplaceLibDir, "ReplaceLibDir"). - func(&CompileOptionsBase::RemoveLinkerOption, "RemoveLinkerOption"). - func(&CompileOptionsBase::RemoveLinkLib, "RemoveLinkLib"). - func(&CompileOptionsBase::RemoveCompilerOption, "RemoveCompilerOption"). - func(&CompileOptionsBase::RemoveIncludeDir, "RemoveIncludeDir"). - func(&CompileOptionsBase::RemoveResourceCompilerOption, "RemoveResourceCompilerOption"). - func(&CompileOptionsBase::RemoveResourceIncludeDir, "RemoveResourceIncludeDir"). - func(&CompileOptionsBase::RemoveLibDir, "RemoveLibDir"). - func(&CompileOptionsBase::RemoveCommandsBeforeBuild, "RemoveCommandsBeforeBuild"). - func(&CompileOptionsBase::RemoveCommandsAfterBuild, "RemoveCommandsAfterBuild"). - func(&CompileOptionsBase::GetAlwaysRunPostBuildSteps, "GetAlwaysRunPostBuildSteps"). - func(&CompileOptionsBase::SetAlwaysRunPostBuildSteps, "SetAlwaysRunPostBuildSteps"). - func(&CompileOptionsBase::SetBuildScripts, "SetBuildScripts"). - func(&CompileOptionsBase::GetBuildScripts, "GetBuildScripts"). - func(&CompileOptionsBase::AddBuildScript, "AddBuildScript"). - func(&CompileOptionsBase::RemoveBuildScript, "RemoveBuildScript"). - func(&CompileOptionsBase::SetVar, "SetVar"). - func(&CompileOptionsBase::GetVar, "GetVar"). - func(&CompileOptionsBase::UnsetVar, "UnsetVar"). - func(&CompileOptionsBase::UnsetAllVars, "UnsetAllVars"); - - SqPlus::SQClassDef("CompileTargetBase", "CompileOptionsBase"). - func(&CompileTargetBase::SetTargetFilenameGenerationPolicy, "SetTargetFilenameGenerationPolicy"). -// func(&CompileTargetBase::GetTargetFilenameGenerationPolicy, "GetTargetFilenameGenerationPolicy"). // not exposed because its args are non-const references - func(&CompileTargetBase::GetFilename, "GetFilename"). - func(&CompileTargetBase::GetTitle, "GetTitle"). - func(&CompileTargetBase::SetTitle, "SetTitle"). - func(&CompileTargetBase::SetOutputFilename, "SetOutputFilename"). - func(&CompileTargetBase::SetWorkingDir, "SetWorkingDir"). - func(&CompileTargetBase::SetObjectOutput, "SetObjectOutput"). - func(&CompileTargetBase::SetDepsOutput, "SetDepsOutput"). - func(&CompileTargetBase::GetOptionRelation, "GetOptionRelation"). - func(&CompileTargetBase::SetOptionRelation, "SetOptionRelation"). - func(&CompileTargetBase::GetWorkingDir, "GetWorkingDir"). - func(&CompileTargetBase::GetObjectOutput, "GetObjectOutput"). - func(&CompileTargetBase::GetDepsOutput, "GetDepsOutput"). - func(&CompileTargetBase::GetOutputFilename, "GetOutputFilename"). - func(&CompileTargetBase::SuggestOutputFilename, "SuggestOutputFilename"). - func(&CompileTargetBase::GetExecutableFilename, "GetExecutableFilename"). - func(&CompileTargetBase::GetDynamicLibFilename, "GetDynamicLibFilename"). - func(&CompileTargetBase::GetDynamicLibDefFilename, "GetDynamicLibDefFilename"). - func(&CompileTargetBase::GetStaticLibFilename, "GetStaticLibFilename"). - func(&CompileTargetBase::GetBasePath, "GetBasePath"). - func(&CompileTargetBase::SetTargetType, "SetTargetType"). - func(&CompileTargetBase::GetTargetType, "GetTargetType"). - func(&CompileTargetBase::GetExecutionParameters, "GetExecutionParameters"). - func(&CompileTargetBase::SetExecutionParameters, "SetExecutionParameters"). - func(&CompileTargetBase::GetHostApplication, "GetHostApplication"). - func(&CompileTargetBase::SetHostApplication, "SetHostApplication"). - func(&CompileTargetBase::SetCompilerID, "SetCompilerID"). - func(&CompileTargetBase::GetCompilerID, "GetCompilerID"). - func(&CompileTargetBase::GetMakeCommandFor, "GetMakeCommandFor"). - func(&CompileTargetBase::SetMakeCommandFor, "SetMakeCommandFor"). - func(&CompileTargetBase::MakeCommandsModified, "MakeCommandsModified"); - - SqPlus::SQClassDef("ProjectBuildTarget", "CompileTargetBase"). - func(&ProjectBuildTarget::GetParentProject, "GetParentProject"). - func(&ProjectBuildTarget::GetFullTitle, "GetFullTitle"). - func(&ProjectBuildTarget::GetExternalDeps, "GetExternalDeps"). - func(&ProjectBuildTarget::SetExternalDeps, "SetExternalDeps"). - func(&ProjectBuildTarget::SetAdditionalOutputFiles, "SetAdditionalOutputFiles"). - func(&ProjectBuildTarget::GetAdditionalOutputFiles, "GetAdditionalOutputFiles"). - func(&ProjectBuildTarget::GetIncludeInTargetAll, "GetIncludeInTargetAll"). - func(&ProjectBuildTarget::SetIncludeInTargetAll, "SetIncludeInTargetAll"). - func(&ProjectBuildTarget::GetCreateDefFile, "GetCreateDefFile"). - func(&ProjectBuildTarget::SetCreateDefFile, "SetCreateDefFile"). - func(&ProjectBuildTarget::GetCreateStaticLib, "GetCreateStaticLib"). - func(&ProjectBuildTarget::SetCreateStaticLib, "SetCreateStaticLib"). - func(&ProjectBuildTarget::GetUseConsoleRunner, "GetUseConsoleRunner"). - func(&ProjectBuildTarget::SetUseConsoleRunner, "SetUseConsoleRunner"). - func(&ProjectBuildTarget::GetFilesCount, "GetFilesCount"). - func(&ProjectBuildTarget::GetFile, "GetFile"); - - SqPlus::SQClassDef("cbProject", "CompileTargetBase"). - func(&cbProject::GetModified, "GetModified"). - func(&cbProject::SetModified, "SetModified"). - func(&cbProject::GetMakefile, "GetMakefile"). - func(&cbProject::SetMakefile, "SetMakefile"). - func(&cbProject::IsMakefileCustom, "IsMakefileCustom"). - func(&cbProject::SetMakefileCustom, "SetMakefileCustom"). - func(&cbProject::CloseAllFiles, "CloseAllFiles"). - func(&cbProject::SaveAllFiles, "SaveAllFiles"). - func(&cbProject::Save, "Save"). -// func(&cbProject::SaveAs, "SaveAs"). // *UNSAFE* - func(&cbProject::SaveLayout, "SaveLayout"). - func(&cbProject::LoadLayout, "LoadLayout"). -// func(&cbProject::ShowOptions, "ShowOptions"). - func(&cbProject::GetCommonTopLevelPath, "GetCommonTopLevelPath"). - func(&cbProject::GetFilesCount, "GetFilesCount"). - func(&cbProject::GetFile, "GetFile"). - func(&cbProject::GetFileByFilename, "GetFileByFilename"). - staticFuncVarArgs(&cbProject_RemoveFile, "RemoveFile", "*"). - staticFuncVarArgs(&cbProject_AddFile, "AddFile", "*"). - func(&cbProject::GetBuildTargetsCount, "GetBuildTargetsCount"). - staticFuncVarArgs(&cbProject_GetBuildTarget, "GetBuildTarget", "*"). - func(&cbProject::AddBuildTarget, "AddBuildTarget"). - staticFuncVarArgs(&cbProject_RenameBuildTarget, "RenameBuildTarget", "*"). - staticFuncVarArgs(&cbProject_DuplicateBuildTarget, "DuplicateBuildTarget", "*"). - staticFuncVarArgs(&cbProject_RemoveBuildTarget, "RemoveBuildTarget", "*"). - staticFuncVarArgs(&cbProject_ExportTargetAsProject, "ExportTargetAsProject", "*"). - func(&cbProject::BuildTargetValid, "BuildTargetValid"). - func(&cbProject::GetFirstValidBuildTargetName, "GetFirstValidBuildTargetName"). - func(&cbProject::SetDefaultExecuteTarget, "SetDefaultExecuteTarget"). - func(&cbProject::GetDefaultExecuteTarget, "GetDefaultExecuteTarget"). - func(&cbProject::SetActiveBuildTarget, "SetActiveBuildTarget"). - func(&cbProject::GetActiveBuildTarget, "GetActiveBuildTarget"). - func(&cbProject::SelectTarget, "SelectTarget"). - func(&cbProject::GetCurrentlyCompilingTarget, "GetCurrentlyCompilingTarget"). - func(&cbProject::SetCurrentlyCompilingTarget, "SetCurrentlyCompilingTarget"). - func(&cbProject::GetModeForPCH, "GetModeForPCH"). - func(&cbProject::SetModeForPCH, "SetModeForPCH"). - func(&cbProject::SetExtendedObjectNamesGeneration, "SetExtendedObjectNamesGeneration"). - func(&cbProject::GetExtendedObjectNamesGeneration, "GetExtendedObjectNamesGeneration"). - func(&cbProject::SetNotes, "SetNotes"). - func(&cbProject::GetNotes, "GetNotes"). - func(&cbProject::SetShowNotesOnLoad, "SetShowNotesOnLoad"). - func(&cbProject::GetShowNotesOnLoad, "GetShowNotesOnLoad"). - func(&cbProject::SetCheckForExternallyModifiedFiles, "SetCheckForExternallyModifiedFiles"). - func(&cbProject::GetCheckForExternallyModifiedFiles, "GetCheckForExternallyModifiedFiles"). - func(&cbProject::ShowNotes, "ShowNotes"). - func(&cbProject::AddToExtensions, "AddToExtensions"). - func(&cbProject::DefineVirtualBuildTarget, "DefineVirtualBuildTarget"). - func(&cbProject::HasVirtualBuildTarget, "HasVirtualBuildTarget"). - func(&cbProject::RemoveVirtualBuildTarget, "RemoveVirtualBuildTarget"). - func(&cbProject::GetVirtualBuildTargets, "GetVirtualBuildTargets"). - func(&cbProject::GetVirtualBuildTargetGroup, "GetVirtualBuildTargetGroup"). - func(&cbProject::GetExpandedVirtualBuildTargetGroup, "GetExpandedVirtualBuildTargetGroup"). - func(&cbProject::CanAddToVirtualBuildTarget, "CanAddToVirtualBuildTarget"). - func(&cbProject::SetTitle, "SetTitle"); - - - SqPlus::SQClassDef("ProjectManager"). - func(&ProjectManager::GetDefaultPath, "GetDefaultPath"). - func(&ProjectManager::SetDefaultPath, "SetDefaultPath"). - func(&ProjectManager::GetActiveProject, "GetActiveProject"). - staticFuncVarArgs(&ProjectManager_GetProjectCount, "GetProjectCount", "*"). - staticFuncVarArgs(&ProjectManager_GetProject, "GetProject", "*"). - func(&ProjectManager::SetProject, "SetProject"). - func(&ProjectManager::LoadWorkspace, "LoadWorkspace"). - func(&ProjectManager::SaveWorkspace, "SaveWorkspace"). - func(&ProjectManager::SaveWorkspaceAs, "SaveWorkspaceAs"). - func(&ProjectManager::CloseWorkspace, "CloseWorkspace"). - func(&ProjectManager::IsOpen, "IsOpen"). - func(&ProjectManager::LoadProject, "LoadProject"). - func(&ProjectManager::SaveProject, "SaveProject"). - func(&ProjectManager::SaveProjectAs, "SaveProjectAs"). - func(&ProjectManager::SaveActiveProject, "SaveActiveProject"). - func(&ProjectManager::SaveActiveProjectAs, "SaveActiveProjectAs"). - func(&ProjectManager::SaveAllProjects, "SaveAllProjects"). - func(&ProjectManager::CloseProject, "CloseProject"). - func(&ProjectManager::CloseActiveProject, "CloseActiveProject"). - func(&ProjectManager::CloseAllProjects, "CloseAllProjects"). - func(&ProjectManager::NewProject, "NewProject"). - staticFuncVarArgs(&ProjectManager_AddFileToProject, "AddFileToProject", "*"). -// func(&ProjectManager::AskForBuildTargetIndex, "AskForBuildTargetIndex"). - func(&ProjectManager::AddProjectDependency, "AddProjectDependency"). - func(&ProjectManager::RemoveProjectDependency, "RemoveProjectDependency"). - func(&ProjectManager::ClearProjectDependencies, "ClearProjectDependencies"). - func(&ProjectManager::RemoveProjectFromAllDependencies, "RemoveProjectFromAllDependencies"). - func(&ProjectManager::GetDependenciesForProject, "GetDependenciesForProject"). -// func(&ProjectManager::ConfigureProjectDependencies, "ConfigureProjectDependencies"); - staticFuncVarArgs(&ProjectManager_RebuildTree, "RebuildTree", "*"); - - SqPlus::SQClassDef("EditorBase"). - func(&EditorBase::GetFilename, "GetFilename"). - func(&EditorBase::SetFilename, "SetFilename"). - func(&EditorBase::GetShortName, "GetShortName"). - func(&EditorBase::GetModified, "GetModified"). - func(&EditorBase::SetModified, "SetModified"). - func(&EditorBase::GetTitle, "GetTitle"). - func(&EditorBase::SetTitle, "SetTitle"). - func(&EditorBase::Activate, "Activate"). - func(&EditorBase::Close, "Close"). - func(&EditorBase::Save, "Save"). - func(&EditorBase::IsBuiltinEditor, "IsBuiltinEditor"). - func(&EditorBase::ThereAreOthers, "ThereAreOthers"). - func(&EditorBase::GotoLine, "GotoLine"). - func(&EditorBase::Undo, "Undo"). - func(&EditorBase::Redo, "Redo"). - func(&EditorBase::Cut, "Cut"). - func(&EditorBase::Copy, "Copy"). - func(&EditorBase::Paste, "Paste"). - func(&EditorBase::CanUndo, "CanUndo"). - func(&EditorBase::CanRedo, "CanRedo"). - func(&EditorBase::CanPaste, "CanPaste"). - func(&EditorBase::IsReadOnly, "IsReadOnly"). - func(&EditorBase::HasSelection, "HasSelection"); - - SqPlus::SQClassDef("cbEditor", "EditorBase"). - func(&cbEditor::SetEditorTitle, "SetEditorTitle"). - func(&cbEditor::GetProjectFile, "GetProjectFile"). - func(&cbEditor::Save, "Save"). - func(&cbEditor::SaveAs, "SaveAs"). - func(&cbEditor::FoldAll, "FoldAll"). - func(&cbEditor::UnfoldAll, "UnfoldAll"). - func(&cbEditor::ToggleAllFolds, "ToggleAllFolds"). - func(&cbEditor::FoldBlockFromLine, "FoldBlockFromLine"). - func(&cbEditor::UnfoldBlockFromLine, "UnfoldBlockFromLine"). - func(&cbEditor::ToggleFoldBlockFromLine, "ToggleFoldBlockFromLine"). - func(&cbEditor::GetLineIndentInSpaces, "GetLineIndentInSpaces"). - func(&cbEditor::GetLineIndentString, "GetLineIndentString"). - func(&cbEditor::Touch, "Touch"). - func(&cbEditor::Reload, "Reload"). - func(&cbEditor::Print, "Print"). - func(&cbEditor::AutoComplete, "AutoComplete"). - func(&cbEditor::AddBreakpoint, "AddBreakpoint"). - func(&cbEditor::RemoveBreakpoint, "RemoveBreakpoint"). - func(&cbEditor::ToggleBookmark, "ToggleBookmark"). - func(&cbEditor::HasBookmark, "HasBookmark"). - func(&cbEditor::GotoNextBookmark, "GotoNextBookmark"). - func(&cbEditor::GotoPreviousBookmark, "GotoPreviousBookmark"). - func(&cbEditor::ClearAllBookmarks, "ClearAllBookmarks"). - func(&cbEditor::ToggleBreakpoint, "ToggleBreakpoint"). - func(&cbEditor::HasBreakpoint, "HasBreakpoint"). - func(&cbEditor::GotoNextBreakpoint, "GotoNextBreakpoint"). - func(&cbEditor::GotoPreviousBreakpoint, "GotoPreviousBreakpoint"). - - - // these are not present in cbEditor; included to help scripts edit text - staticFuncVarArgs(&cbEditor_SetText, "SetText", "*"). - staticFuncVarArgs(&cbEditor_GetText, "GetText", "*"); - - SqPlus::SQClassDef("EditorManager"). - func(&EditorManager::New, "New"). - staticFuncVarArgs(&EditorManager_Open, "Open"). - func(&EditorManager::IsBuiltinOpen, "IsBuiltinOpen"). - staticFuncVarArgs(&EditorManager_GetBuiltinEditor, "GetBuiltinEditor", "*"). - func(&EditorManager::GetBuiltinActiveEditor, "GetBuiltinActiveEditor"). - func(&EditorManager::GetActiveEditor, "GetActiveEditor"). - func(&EditorManager::ActivateNext, "ActivateNext"). - func(&EditorManager::ActivatePrevious, "ActivatePrevious"). - func(&EditorManager::SwapActiveHeaderSource, "SwapActiveHeaderSource"). - func(&EditorManager::CloseActive, "CloseActive"). - staticFuncVarArgs(&EditorManager_Close, "Close", "*"). - func(&EditorManager::CloseAll, "CloseAll"). - staticFuncVarArgs(&EditorManager_Save, "Save", "*"). - func(&EditorManager::SaveActive, "SaveActive"). - func(&EditorManager::SaveAs, "SaveAs"). - func(&EditorManager::SaveActiveAs, "SaveActiveAs"). - func(&EditorManager::SaveAll, "SaveAll"); - // func(&EditorManager::ShowFindDialog, "ShowFindDialog"); - - SqPlus::SQClassDef("UserVariableManager"). - func(&UserVariableManager::Exists, "Exists"); - - SqPlus::SQClassDef("ScriptingManager"). - func(&ScriptingManager::RegisterScriptMenu, "RegisterScriptMenu"); - - typedef bool(*CF_INHERITSFROM)(const wxString&, const wxString&); // CompilerInheritsFrom - - SqPlus::SQClassDef("CompilerFactory"). - staticFunc(&CompilerFactory::IsValidCompilerID, "IsValidCompilerID"). - staticFuncVarArgs(&CompilerFactory_GetCompilerIndex, "GetCompilerIndex", "*"). - staticFunc(&CompilerFactory::GetDefaultCompilerID, "GetDefaultCompilerID"). - staticFunc(&CompilerFactory::GetCompilerVersionString, "GetCompilerVersionString"). - staticFunc(&CompilerFactory::CompilerInheritsFrom, "CompilerInheritsFrom"). - staticFunc(CompilerFactory_GetCompilerIDByName, "GetCompilerIDByName"); - - SqPlus::SQClassDef("PluginInfo"). - emptyCtor(). - var(&PluginInfo::name, "name"). - var(&PluginInfo::title, "title"). - var(&PluginInfo::version, "version"). - var(&PluginInfo::description, "description"). - var(&PluginInfo::author, "author"). - var(&PluginInfo::authorEmail, "authorEmail"). - var(&PluginInfo::authorWebsite, "authorWebsite"). - var(&PluginInfo::thanksTo, "thanksTo"). - var(&PluginInfo::license, "license"); - - SqPlus::SQClassDef("FileTreeData"). - func(&FileTreeData::GetKind, "GetKind"). - func(&FileTreeData::GetProject, "GetProject"). - func(&FileTreeData::GetFileIndex, "GetFileIndex"). - func(&FileTreeData::GetProjectFile, "GetProjectFile"). - func(&FileTreeData::GetFolder, "GetFolder"). - func(&FileTreeData::SetKind, "SetKind"). - func(&FileTreeData::SetProject, "SetProject"). - func(&FileTreeData::SetFileIndex, "SetFileIndex"). - func(&FileTreeData::SetProjectFile, "SetProjectFile"). - func(&FileTreeData::SetFolder, "SetFolder"); - - // called last because it needs a few previously registered types - Register_ScriptPlugin(); + { + sa.PushValue(CompilerFactory::GetCompilerIndex(*sa.GetInstance(2))); + return SC_RETURN_VALUE; + } + } + catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); } + return sa.ThrowError(_("Invalid arguments to \"CompilerFactory::GetCompilerIndex\"")); +} + +wxString CompilerFactory_GetCompilerIDByName(const wxString &name) +{ + Compiler *compiler = CompilerFactory::GetCompilerByName(name); + return (compiler ? compiler->GetID() : wxString(wxEmptyString)); +} + + +/** \defgroup sq_cb_global Code::Blocks binding to internal classes and functions + * \ingroup Squirrel + * \brief Code::Blocks binding to internal classes and functions +*/ +void RegisterBindings(HSQUIRRELVM vm) +{ + if (!vm) + cbThrow(_T("Scripting engine not initialized!?")); + + Register_wxGlobals(vm); + Register_wxTypes(vm); + Register_Constants(vm); + Register_Globals(vm); + Register_IO(vm); // IO is enabled, but just for harmless functions + Register_Dialog(vm); + Register_ProgressDialog(vm); + Register_UtilDialogs(vm); + + + Sqrat::Class config_manager(vm,"ConfigManager"); + config_manager. + SquirrelFunc("Read", &ConfigManager_Read). + SquirrelFunc("Write", &ConfigManager_Write); + + Sqrat::RootTable(vm).Bind("ConfigManager",config_manager); + + Sqrat::Class project_file(vm,"ProjectFile"); + project_file. + Func("AddBuildTarget", &ProjectFile::AddBuildTarget). + Func("RenameBuildTarget", &ProjectFile::RenameBuildTarget). + Func("RemoveBuildTarget", &ProjectFile::RemoveBuildTarget). + Func("GetbuildTargets", &ProjectFile::GetBuildTargets). + Func("GetBaseName", &ProjectFile::GetBaseName). + Func("GetObjName", &ProjectFile::GetObjName). + Func("SetObjName", &ProjectFile::SetObjName). + Func("GetParentProject", &ProjectFile::GetParentProject). + Func("SetUseCustomBuildCommand", &ProjectFile::SetUseCustomBuildCommand). + Func("SetCustomBuildCommand", &ProjectFile::SetCustomBuildCommand). + Func("GetUseCustomBuildCommand", &ProjectFile::GetUseCustomBuildCommand). + Func("GetCustomBuildCommand", &ProjectFile::GetCustomBuildCommand). + Var("file", &ProjectFile::file). + Var("relativeFilename", &ProjectFile::relativeFilename). + Var("relativeToCommonTopLevelPath", &ProjectFile::relativeToCommonTopLevelPath). + Var("compile", &ProjectFile::compile). + Var("link", &ProjectFile::link). + Var("weight", &ProjectFile::weight). + Var("compilerVar", &ProjectFile::compilerVar). + Var("buildTargets", &ProjectFile::buildTargets); + + Sqrat::RootTable(vm).Bind("ProjectFile",project_file); + + Sqrat::Class compiler_options_base(vm,"CompileOptionsBase"); + compiler_options_base. + Func("AddPlatform", &CompileOptionsBase::AddPlatform). + Func("RemovePlatform", &CompileOptionsBase::RemovePlatform). + Func("SetPlatforms", &CompileOptionsBase::SetPlatforms). + Func("GetPlatforms", &CompileOptionsBase::GetPlatforms). + Func("SupportsCurrentPlatform", &CompileOptionsBase::SupportsCurrentPlatform). + Func("SetLinkerOptions",&CompileOptionsBase::SetLinkerOptions). + Func("SetLinkLibs", &CompileOptionsBase::SetLinkLibs). + Func("SetCompilerOptions", &CompileOptionsBase::SetCompilerOptions). + Func("SetResourceCompilerOptions", &CompileOptionsBase::SetResourceCompilerOptions). + Func("SetIncludeDirs", &CompileOptionsBase::SetIncludeDirs). + Func("SetResourceIncludeDirs", &CompileOptionsBase::SetResourceIncludeDirs). + Func("SetLibDirs", &CompileOptionsBase::SetLibDirs). + Func("SetCommandsBeforeBuild", &CompileOptionsBase::SetCommandsBeforeBuild). + Func("SetCommandsAfterBuild", &CompileOptionsBase::SetCommandsAfterBuild). + Func("GetLinkerOptions", &CompileOptionsBase::GetLinkerOptions). + Func("GetLinkLibs", &CompileOptionsBase::GetLinkLibs). + Func("GetCompilerOptions", &CompileOptionsBase::GetCompilerOptions). + Func("GetResourceCompilerOptions", &CompileOptionsBase::GetResourceCompilerOptions). + Func("GetIncludeDirs", &CompileOptionsBase::GetIncludeDirs). + Func("GetResourceIncludeDirs", &CompileOptionsBase::GetResourceIncludeDirs). + Func("GetLibDirs", &CompileOptionsBase::GetLibDirs). + Func("GetCommandsBeforeBuild", &CompileOptionsBase::GetCommandsBeforeBuild). + Func("GetCommandsAfterBuild", &CompileOptionsBase::GetCommandsAfterBuild). + Func("GetModified", &CompileOptionsBase::GetModified). + Func("SetModified", &CompileOptionsBase::SetModified). + Func("AddLinkerOption", &CompileOptionsBase::AddLinkerOption). + Func("AddLinkLib", &CompileOptionsBase::AddLinkLib). + Func("AddCompilerOption", &CompileOptionsBase::AddCompilerOption). + Func("AddResourceCompilerOption", &CompileOptionsBase::AddResourceCompilerOption). + Func("AddIncludeDir", &CompileOptionsBase::AddIncludeDir). + Func("AddResourceIncludeDir", &CompileOptionsBase::AddResourceIncludeDir). + Func("AddLibDir", &CompileOptionsBase::AddLibDir). + Func("AddCommandsBeforeBuild", &CompileOptionsBase::AddCommandsBeforeBuild). + Func("AddCommandsAfterBuild", &CompileOptionsBase::AddCommandsAfterBuild). + Func("ReplaceLinkerOption", &CompileOptionsBase::ReplaceLinkerOption). + Func("ReplaceLinkLib", &CompileOptionsBase::ReplaceLinkLib). + Func("ReplaceCompilerOption", &CompileOptionsBase::ReplaceCompilerOption). + Func("ReplaceResourceCompilerOption", &CompileOptionsBase::ReplaceResourceCompilerOption). + Func("ReplaceIncludeDir", &CompileOptionsBase::ReplaceIncludeDir). + Func("ReplaceResourceIncludeDir", &CompileOptionsBase::ReplaceResourceIncludeDir). + Func("ReplaceLibDir", &CompileOptionsBase::ReplaceLibDir). + Func("RemoveLinkerOption", &CompileOptionsBase::RemoveLinkerOption). + Func("RemoveLinkLib", &CompileOptionsBase::RemoveLinkLib). + Func("RemoveCompilerOption", &CompileOptionsBase::RemoveCompilerOption). + Func("RemoveIncludeDir", &CompileOptionsBase::RemoveIncludeDir). + Func("RemoveResourceCompilerOption", &CompileOptionsBase::RemoveResourceCompilerOption). + Func("RemoveResourceIncludeDir",&CompileOptionsBase::RemoveResourceIncludeDir). + Func("RemoveLibDir", &CompileOptionsBase::RemoveLibDir). + Func("RemoveCommandsBeforeBuild", &CompileOptionsBase::RemoveCommandsBeforeBuild). + Func("RemoveCommandsAfterBuild", &CompileOptionsBase::RemoveCommandsAfterBuild). + Func("GetAlwaysRunPostBuildSteps", &CompileOptionsBase::GetAlwaysRunPostBuildSteps). + Func("SetAlwaysRunPostBuildSteps", &CompileOptionsBase::SetAlwaysRunPostBuildSteps). + Func("SetBuildScripts", &CompileOptionsBase::SetBuildScripts). + Func("GetBuildScripts", &CompileOptionsBase::GetBuildScripts). + Func("AddBuildScript", &CompileOptionsBase::AddBuildScript). + Func("RemoveBuildScript", &CompileOptionsBase::RemoveBuildScript). + Func("SetVar", &CompileOptionsBase::SetVar). + Func("GetVar", &CompileOptionsBase::GetVar). + Func("UnsetVar", &CompileOptionsBase::UnsetVar). + Func("UnsetAllVars", &CompileOptionsBase::UnsetAllVars); + + Sqrat::RootTable(vm).Bind("CompileOptionsBase",compiler_options_base); + + Sqrat::DerivedClass compiler_target_base(vm,"CompileTargetBase"); + compiler_target_base. + Func("SetTargetFilenameGenerationPolicy",&CompileTargetBase::SetTargetFilenameGenerationPolicy ). +// Func(&CompileTargetBase::GetTargetFilenameGenerationPolicy "GetTargetFilenameGenerationPolicy"). // not exposed because its args are non-const references + Func("GetFilename", &CompileTargetBase::GetFilename ). + Func("GetTitle", &CompileTargetBase::GetTitle ). + Func("SetTitle", &CompileTargetBase::SetTitle ). + Func("SetOutputFilename", &CompileTargetBase::SetOutputFilename ). + Func("SetWorkingDir", &CompileTargetBase::SetWorkingDir ). + Func("SetObjectOutput", &CompileTargetBase::SetObjectOutput ). + Func("SetDepsOutput", &CompileTargetBase::SetDepsOutput ). + Func("GetOptionRelation", &CompileTargetBase::GetOptionRelation ). + Func("SetOptionRelation", &CompileTargetBase::SetOptionRelation ). + Func("GetWorkingDir", &CompileTargetBase::GetWorkingDir ). + Func("GetObjectOutput", &CompileTargetBase::GetObjectOutput ). + Func("GetDepsOutput", &CompileTargetBase::GetDepsOutput ). + Func("GetOutputFilename", &CompileTargetBase::GetOutputFilename ). + Func("SuggestOutputFilename", &CompileTargetBase::SuggestOutputFilename ). + Func("GetExecutableFilename", &CompileTargetBase::GetExecutableFilename ). + Func("GetDynamicLibFilename", &CompileTargetBase::GetDynamicLibFilename ). + Func("GetDynamicLibDefFilename",&CompileTargetBase::GetDynamicLibDefFilename ). + Func("GetStaticLibFilename", &CompileTargetBase::GetStaticLibFilename ). + Func("GetBasePath", &CompileTargetBase::GetBasePath ). + Func("SetTargetType", &CompileTargetBase::SetTargetType ). + Func("GetTargetType", &CompileTargetBase::GetTargetType ). + Func("GetExecutionParameters", &CompileTargetBase::GetExecutionParameters ). + Func("SetExecutionParameters", &CompileTargetBase::SetExecutionParameters ). + Func("GetHostApplication", &CompileTargetBase::GetHostApplication ). + Func("SetHostApplication", &CompileTargetBase::SetHostApplication ). + Func("SetCompilerID", &CompileTargetBase::SetCompilerID ). + Func("GetCompilerID", &CompileTargetBase::GetCompilerID ). + Func("GetMakeCommandFor", &CompileTargetBase::GetMakeCommandFor ). + Func("SetMakeCommandFor", &CompileTargetBase::SetMakeCommandFor ). + Func("MakeCommandsModified",&CompileTargetBase::MakeCommandsModified ); + + Sqrat::RootTable(vm).Bind("CompileTargetBase",compiler_target_base); + + + Sqrat::DerivedClass project_build_target(vm,"ProjectBuildTarget"); + project_build_target. + Func("GetParentProject", &ProjectBuildTarget::GetParentProject). + Func("GetFullTitle", &ProjectBuildTarget::GetFullTitle). + Func("GetExternalDeps", &ProjectBuildTarget::GetExternalDeps). + Func("SetExternalDeps", &ProjectBuildTarget::SetExternalDeps). + Func("SetAdditionalOutputFiles", &ProjectBuildTarget::SetAdditionalOutputFiles). + Func("GetAdditionalOutputFiles", &ProjectBuildTarget::GetAdditionalOutputFiles). + Func("GetIncludeInTargetAll", &ProjectBuildTarget::GetIncludeInTargetAll). + Func("SetIncludeInTargetAll", &ProjectBuildTarget::SetIncludeInTargetAll). + Func("GetCreateDefFile", &ProjectBuildTarget::GetCreateDefFile). + Func("SetCreateDefFile", &ProjectBuildTarget::SetCreateDefFile). + Func("GetCreateStaticLib", &ProjectBuildTarget::GetCreateStaticLib). + Func("SetCreateStaticLib", &ProjectBuildTarget::SetCreateStaticLib). + Func("GetUseConsoleRunner", &ProjectBuildTarget::GetUseConsoleRunner). + Func("SetUseConsoleRunner", &ProjectBuildTarget::SetUseConsoleRunner). + Func("GetFilesCount", &ProjectBuildTarget::GetFilesCount). + Func("GetFile", &ProjectBuildTarget::GetFile); + + Sqrat::RootTable(vm).Bind("ProjectBuildTarget",project_build_target); + + Sqrat::DerivedClass cb_project(vm,"cbProject"); + cb_project. + Func("GetModified", &cbProject::GetModified). + Func("SetModified", &cbProject::SetModified). + Func("GetMakefile", &cbProject::GetMakefile). + Func("SetMakefile", &cbProject::SetMakefile). + Func("IsMakefileCustom",&cbProject::IsMakefileCustom). + Func("SetMakefileCustom",&cbProject::SetMakefileCustom). + Func("CloseAllFiles", &cbProject::CloseAllFiles). + Func("SaveAllFiles", &cbProject::SaveAllFiles). + Func("Save", &cbProject::Save). +// Func(&cbProject::SaveAs"SaveAs"). // *UNSAFE* + Func("SaveLayout", &cbProject::SaveLayout). + Func("LoadLayout", &cbProject::LoadLayout). +// Func(&cbProject::ShowOptions"ShowOptions"). + Func("GetCommonTopLevelPath",&cbProject::GetCommonTopLevelPath). + Func("GetFilesCount", &cbProject::GetFilesCount). + Func("GetFile", &cbProject::GetFile). + Func("GetFileByFilename", &cbProject::GetFileByFilename). + SquirrelFunc("RemoveFile", &cbProject_RemoveFile). + SquirrelFunc("AddFile", &cbProject_AddFile). + Func("GetBuildTargetsCount",&cbProject::GetBuildTargetsCount). + SquirrelFunc("GetBuildTarget", &cbProject_GetBuildTarget). + Func("AddBuildTarget", &cbProject::AddBuildTarget). + SquirrelFunc("RenameBuildTarget",&cbProject_RenameBuildTarget). + SquirrelFunc("DuplicateBuildTarget",&cbProject_DuplicateBuildTarget). + SquirrelFunc("RemoveBuildTarget",&cbProject_RemoveBuildTarget). + SquirrelFunc("ExportTargetAsProject",&cbProject_ExportTargetAsProject). + Func("BuildTargetValid", &cbProject::BuildTargetValid). + Func("GetFirstValidBuildTargetName",&cbProject::GetFirstValidBuildTargetName). + Func("SetDefaultExecuteTarget", &cbProject::SetDefaultExecuteTarget). + Func("GetDefaultExecuteTarget", &cbProject::GetDefaultExecuteTarget). + Func("SetActiveBuildTarget", &cbProject::SetActiveBuildTarget). + Func("GetActiveBuildTarget", &cbProject::GetActiveBuildTarget). + Func("SelectTarget", &cbProject::SelectTarget). + Func("GetCurrentlyCompilingTarget", &cbProject::GetCurrentlyCompilingTarget). + Func("SetCurrentlyCompilingTarget", &cbProject::SetCurrentlyCompilingTarget). + Func("GetModeForPCH", &cbProject::GetModeForPCH). + Func("SetModeForPCH", &cbProject::SetModeForPCH). + Func("SetExtendedObjectNamesGeneration",&cbProject::SetExtendedObjectNamesGeneration). + Func("GetExtendedObjectNamesGeneration",&cbProject::GetExtendedObjectNamesGeneration). + Func("SetNotes", &cbProject::SetNotes). + Func("GetNotes", &cbProject::GetNotes). + Func("SetShowNotesOnLoad", &cbProject::SetShowNotesOnLoad). + Func("GetShowNotesOnLoad", &cbProject::GetShowNotesOnLoad). + Func("SetCheckForExternallyModifiedFiles", &cbProject::SetCheckForExternallyModifiedFiles). + Func("GetCheckForExternallyModifiedFiles", &cbProject::GetCheckForExternallyModifiedFiles). + Func("ShowNotes", &cbProject::ShowNotes). + Func("AddToExtensions", &cbProject::AddToExtensions). + Func("DefineVirtualBuildTarget", &cbProject::DefineVirtualBuildTarget). + Func("HasVirtualBuildTarget", &cbProject::HasVirtualBuildTarget). + Func("RemoveVirtualBuildTarget", &cbProject::RemoveVirtualBuildTarget). + Func("GetVirtualBuildTargets", &cbProject::GetVirtualBuildTargets). + Func("GetVirtualBuildTargetGroup", &cbProject::GetVirtualBuildTargetGroup). + Func("GetExpandedVirtualBuildTargetGroup",&cbProject::GetExpandedVirtualBuildTargetGroup). + Func("CanAddToVirtualBuildTarget", &cbProject::CanAddToVirtualBuildTarget). + Func("SetTitle", &cbProject::SetTitle); + + Sqrat::RootTable(vm).Bind("cbProject",cb_project); + + + + Sqrat::Class > project_manager(vm,"ProjectManager"); + project_manager. + Func("GetDefaultPath", &ProjectManager::GetDefaultPath). + Func("SetDefaultPath", &ProjectManager::SetDefaultPath). + Func("GetActiveProject", &ProjectManager::GetActiveProject). + SquirrelFunc("GetProjectCount",&ProjectManager_GetProjectCount). + SquirrelFunc("GetProject", &ProjectManager_GetProject). + Func("SetProject", &ProjectManager::SetProject). + Func("LoadWorkspace", &ProjectManager::LoadWorkspace). + Func("SaveWorkspace", &ProjectManager::SaveWorkspace). + Func("SaveWorkspaceAs", &ProjectManager::SaveWorkspaceAs). + Func("CloseWorkspace", &ProjectManager::CloseWorkspace). + Func("IsOpen", &ProjectManager::IsOpen). + Func("LoadProject", &ProjectManager::LoadProject). + Func("SaveProject", &ProjectManager::SaveProject). + Func("SaveProjectAs", &ProjectManager::SaveProjectAs). + Func("SaveActiveProject", &ProjectManager::SaveActiveProject). + Func("SaveActiveProjectAs", &ProjectManager::SaveActiveProjectAs). + Func("SaveAllProjects", &ProjectManager::SaveAllProjects). + Func("CloseProject", &ProjectManager::CloseProject). + Func("CloseActiveProject", &ProjectManager::CloseActiveProject). + Func("CloseAllProjects", &ProjectManager::CloseAllProjects). + Func("NewProject", &ProjectManager::NewProject). + SquirrelFunc("AddFileToProject", &ProjectManager_AddFileToProject). +// Func(&ProjectManager::AskForBuildTargetIndex"AskForBuildTargetIndex"). + Func("AddProjectDependency", &ProjectManager::AddProjectDependency). + Func("RemoveProjectDependency", &ProjectManager::RemoveProjectDependency). + Func("ClearProjectDependencies", &ProjectManager::ClearProjectDependencies). + Func("RemoveProjectFromAllDependencies",&ProjectManager::RemoveProjectFromAllDependencies). + Func("GetDependenciesForProject", &ProjectManager::GetDependenciesForProject). +// Func(&ProjectManager::ConfigureProjectDependencies"ConfigureProjectDependencies"); + SquirrelFunc("RebuildTree", &ProjectManager_RebuildTree); + Sqrat::RootTable(vm).Bind("ProjectManager",project_manager); + + Sqrat::Class > editor_base(vm,"EditorBase"); + editor_base. + Func("GetFilename", &EditorBase::GetFilename). + Func("SetFilename", &EditorBase::SetFilename). + Func("GetShortName", &EditorBase::GetShortName). + Func("GetModified", &EditorBase::GetModified). + Func("SetModified", &EditorBase::SetModified). + Func("GetTitle", &EditorBase::GetTitle). + Func("SetTitle", &EditorBase::SetTitle). + Func("Activate", &EditorBase::Activate). + Func("Close", &EditorBase::Close). + Func("Save", &EditorBase::Save). + Func("IsBuiltinEditor", &EditorBase::IsBuiltinEditor). + Func("ThereAreOthers", &EditorBase::ThereAreOthers). + Func("GotoLine", &EditorBase::GotoLine). + //Func("ToggleBreakpoint",&EditorBase::ToggleBreakpoint). + //Func("HasBreakpoint", &EditorBase::HasBreakpoint). + //Func("GotoNextBreakpoint",&EditorBase::GotoNextBreakpoint). + //Func("GotoPreviousBreakpoint",&EditorBase::GotoPreviousBreakpoint). + //Func("ToggleBookmark", &EditorBase::ToggleBookmark). + //Func("HasBookmark", &EditorBase::HasBookmark). + //Func("GotoNextBookmark",&EditorBase::GotoNextBookmark). + //Func("GotoPreviousBookmark",&EditorBase::GotoPreviousBookmark). + Func("Undo", &EditorBase::Undo). + Func("Redo", &EditorBase::Redo). + Func("Cut", &EditorBase::Cut). + Func("Copy", &EditorBase::Copy). + Func("Paste", &EditorBase::Paste). + Func("CanUndo", &EditorBase::CanUndo). + Func("CanRedo", &EditorBase::CanRedo). + Func("CanPaste", &EditorBase::CanPaste). + Func("IsReadOnly", &EditorBase::IsReadOnly). + Func("HasSelection",&EditorBase::HasSelection); + Sqrat::RootTable(vm).Bind("EditorBase",editor_base); + + Sqrat::DerivedClass > cb_editor(vm,"cbEditor"); + cb_editor. + Func("SetEditorTitle", &cbEditor::SetEditorTitle). + Func("GetProjectFile", &cbEditor::GetProjectFile). + Func("Save", &cbEditor::Save). + Func("SaveAs", &cbEditor::SaveAs). + Func("FoldAll", &cbEditor::FoldAll). + Func("UnfoldAll", &cbEditor::UnfoldAll). + Func("ToggleAllFolds", &cbEditor::ToggleAllFolds). + Func("FoldBlockFromLine", &cbEditor::FoldBlockFromLine). + Func("UnfoldBlockFromLine", &cbEditor::UnfoldBlockFromLine). + Func("ToggleFoldBlockFromLine",&cbEditor::ToggleFoldBlockFromLine). + Func("GetLineIndentInSpaces",&cbEditor::GetLineIndentInSpaces). + Func("GetLineIndentString", &cbEditor::GetLineIndentString). + Func("Touch", &cbEditor::Touch). + Func("Reload", &cbEditor::Reload). + Func("Print", &cbEditor::Print). + Func("AutoComplete", &cbEditor::AutoComplete). + Func("AddBreakpoint", &cbEditor::AddBreakpoint). + Func("RemoveBreakpoint",&cbEditor::RemoveBreakpoint). + // these are not present in cbEditor; included to help scripts edit text + SquirrelFunc("SetText", &cbEditor_SetText). + SquirrelFunc("GetText", &cbEditor_GetText); + Sqrat::RootTable(vm).Bind("cbEditor",cb_editor); + + Sqrat::Class > editor_manager(vm,"EditorManager"); + editor_manager. + Func("New", &EditorManager::New). + SquirrelFunc("Open", &EditorManager_Open). + Func("IsBuiltinOpen", &EditorManager::IsBuiltinOpen). + SquirrelFunc("GetBuiltinEditor",&EditorManager_GetBuiltinEditor). + Func("GetBuiltinActiveEditor",&EditorManager::GetBuiltinActiveEditor). + Func("GetActiveEditor", &EditorManager::GetActiveEditor). + Func("ActivateNext", &EditorManager::ActivateNext). + Func("ActivatePrevious",&EditorManager::ActivatePrevious). + Func("SwapActiveHeaderSource",&EditorManager::SwapActiveHeaderSource). + Func("CloseActive", &EditorManager::CloseActive). + SquirrelFunc("Close", &EditorManager_Close). + Func("CloseAll", &EditorManager::CloseAll). + SquirrelFunc("Save", &EditorManager_Save). + Func("SaveActive", &EditorManager::SaveActive). + Func("SaveAs", &EditorManager::SaveAs). + Func("SaveActiveAs", &EditorManager::SaveActiveAs). + Func("SaveAll", &EditorManager::SaveAll); + // Func(&EditorManager::ShowFindDialog"ShowFindDialog"); + Sqrat::RootTable(vm).Bind("EditorManager",editor_manager); + + + Sqrat::Class > user_variable_manager(vm,"UserVariableManager"); + user_variable_manager. + Func("Exists", &UserVariableManager::Exists); + Sqrat::RootTable(vm).Bind("UserVariableManager",user_variable_manager); + + + /** \brief ScriptingManager class binding. + * \ingroup sq_cb_global + * + * ### ScriptingManager Function bound to squirrel + * | Name | parameter | description | info | + * | :-----------------------:| :-----------------------------------------------------------: | :-----------------------: | :----:| + * | RegisterScriptMenu | [string] menu_path, [string] script_or_func,[bool] isFunc | Register a menu entry | x | + * | DisplayErrors | [string] message, [bool] del_errors | Display scripting errors. Empty string if the cache should be called | x | + */ + + Sqrat::Class > scripting_manager(vm,"ScriptingManager"); + scripting_manager. + Func("RegisterScriptMenu", &ScriptingManager::RegisterScriptMenu). + Func("DisplayErrors", &ScriptingManager::DisplayErrors); + Sqrat::RootTable(vm).Bind("ScriptingManager",scripting_manager); + + typedef bool(*CF_INHERITSFROM)(const wxString&, const wxString&); // CompilerInheritsFrom + + // NOTE this is a remaining of the rebase process. + // It can be removed if no problems were reported + //Sqrat::RootTable(vm).Func("GetCompilerIDByName",CompilerFactory_GetCompilerIDByName); + + Sqrat::Class compiler_factory(vm,"CompilerFactory"); + compiler_factory. + StaticFunc("IsValidCompilerID", &CompilerFactory::IsValidCompilerID). + // FIXME (bluehazzard#1#): This should work, but i'm not sure... + SquirrelFunc("GetCompilerIndex", &CompilerFactory_GetCompilerIndex). + StaticFunc("GetDefaultCompilerID", &CompilerFactory::GetDefaultCompilerID). + StaticFunc("GetCompilerVersionString", &CompilerFactory::GetCompilerVersionString). + StaticFunc("CompilerInheritsFrom",&CompilerFactory::CompilerInheritsFrom). + StaticFunc("GetCompilerIDByName",CompilerFactory_GetCompilerIDByName); + Sqrat::RootTable(vm).Bind("CompilerFactory",compiler_factory); + + Sqrat::Class plugin_info(vm,"PluginInfo"); + plugin_info. + //emptyCtor(). + Var("name", &PluginInfo::name). + Var("title", &PluginInfo::title). + Var("version", &PluginInfo::version). + Var("description", &PluginInfo::description). + Var("author", &PluginInfo::author). + Var("authorEmail", &PluginInfo::authorEmail). + Var("authorWebsite",&PluginInfo::authorWebsite). + Var("thanksTo", &PluginInfo::thanksTo). + Var("license", &PluginInfo::license); + Sqrat::RootTable(vm).Bind("PluginInfo",plugin_info); + + + Sqrat::Class file_tree_data(vm,"FileTreeData"); + file_tree_data. + Func("GetKind", &FileTreeData::GetKind). + Func("GetProject", &FileTreeData::GetProject). + Func("GetFileIndex", &FileTreeData::GetFileIndex). + Func("GetProjectFile", &FileTreeData::GetProjectFile). + Func("GetFolder", &FileTreeData::GetFolder). + Func("SetKind", &FileTreeData::SetKind). + Func("SetProject", &FileTreeData::SetProject). + Func("SetFileIndex", &FileTreeData::SetFileIndex). + Func("SetProjectFile", &FileTreeData::SetProjectFile). + Func("SetFolder", &FileTreeData::SetFolder); + Sqrat::RootTable(vm).Bind("FileTreeData",file_tree_data); + + /** \brief CodeBlocksEvent class binding. + * \ingroup sq_cb_global + * + * Function bound to squirrel: + * + * ### CodeBlocksEvent Function bound to squirrel + * | Name | parameter | description | info | + * | :-----------------------:| :-------------------: | :-----------------------: | :----:| + * | CodeBlocksEvent() | &CodeBlocksEvent | Copy only constructor | x | + * | GetEventType | x | x | x | + * | GetProject | x | x | x | + * | SetProject | x | x | x | + * | GetEditor | x | x | x | + * | SetEditor | x | x | x | + * | GetOldEditor | x | x | x | + * | SetOldEditor | x | x | x | + * | GetX | x | x | x | + * | SetX | x | x | x | + * | GetY | x | x | x | + * | SetY | x | x | x | + * | GetBuildTargetName | x | x | x | + * | GetOldBuildTargetName | x | x | x | + * | SetOldBuildTargetName | x | x | x | + + */ + + Sqrat::Class > cb_event(vm,"CodeBlocksEvent"); + cb_event. + Func("GetEventType", &CodeBlocksEvent::GetEventType). + Func("GetProject", &CodeBlocksEvent::GetProject). + Func("SetProject", &CodeBlocksEvent::SetProject). + Func("GetEditor", &CodeBlocksEvent::GetEditor). + Func("SetEditor", &CodeBlocksEvent::SetEditor). + Func("GetOldEditor", &CodeBlocksEvent::GetOldEditor). + Func("SetOldEditor", &CodeBlocksEvent::SetOldEditor). + //Func("GetPlugin", &CodeBlocksEvent::GetPlugin). + //Func("SetPlugin", &CodeBlocksEvent::SetPlugin). + Func("GetX", &CodeBlocksEvent::GetX). + Func("SetX", &CodeBlocksEvent::SetX). + Func("GetY", &CodeBlocksEvent::GetY). + Func("SetY", &CodeBlocksEvent::SetY). + Func("GetBuildTargetName", &CodeBlocksEvent::GetBuildTargetName). + Func("GetOldBuildTargetName", &CodeBlocksEvent::GetOldBuildTargetName). + Func("SetOldBuildTargetName", &CodeBlocksEvent::SetOldBuildTargetName); + Sqrat::RootTable(vm).Bind("CodeBlocksEvent",cb_event); + + // called last because it needs a few previously registered types + Register_ScriptPlugin(vm); +} } // namespace ScriptBindings From 281401091ca360868737263a8679ea024d69829d Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 17:18:44 +0200 Subject: [PATCH 07/16] [NOT COMPILE] change all wx from sqplus to sqrat * move all wxWidgets related files to sq_wx subfolder * split the string handling in a separate source file * script binding register methods expect a vm parameter so multiple vms can be used + add wxString handler to the sqrat api, to make a automated conversation between squirrel strings and wxStrings (in any direction) + add "_tostring" methods for all wx types + add unicode support for wxString class (only UTF8) + add ToInt and ToDouble to wxString + add "wxT()" + add wxColour(int,int,int) constructor + add wxPoint::Cmp() + add wxSize::Cmp() + add wxStopWatch * move all wxWidgets const to the const table --- src/include/scripting/bindings/sq_wx/sq_wx.h | 27 + .../bindings/sq_wx/sq_wx_type_handler.h | 191 +++++ src/sdk/scripting/bindings/sc_wxtypes.cpp | 412 ---------- .../bindings/sq_wx/sq_util_dialogs.cpp | 176 +++++ src/sdk/scripting/bindings/sq_wx/sq_wx.cpp | 62 ++ .../bindings/sq_wx/sq_wx_constants.cpp | 62 ++ .../scripting/bindings/sq_wx/sq_wx_string.cpp | 707 ++++++++++++++++++ .../scripting/bindings/sq_wx/sq_wxtypes.cpp | 441 +++++++++++ 8 files changed, 1666 insertions(+), 412 deletions(-) create mode 100644 src/include/scripting/bindings/sq_wx/sq_wx.h create mode 100644 src/include/scripting/bindings/sq_wx/sq_wx_type_handler.h delete mode 100644 src/sdk/scripting/bindings/sc_wxtypes.cpp create mode 100644 src/sdk/scripting/bindings/sq_wx/sq_util_dialogs.cpp create mode 100644 src/sdk/scripting/bindings/sq_wx/sq_wx.cpp create mode 100644 src/sdk/scripting/bindings/sq_wx/sq_wx_constants.cpp create mode 100644 src/sdk/scripting/bindings/sq_wx/sq_wx_string.cpp create mode 100644 src/sdk/scripting/bindings/sq_wx/sq_wxtypes.cpp diff --git a/src/include/scripting/bindings/sq_wx/sq_wx.h b/src/include/scripting/bindings/sq_wx/sq_wx.h new file mode 100644 index 0000000000..f3a3699edb --- /dev/null +++ b/src/include/scripting/bindings/sq_wx/sq_wx.h @@ -0,0 +1,27 @@ +/* + * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 + * http://www.gnu.org/licenses/lgpl-3.0.html + */ + +#ifndef SQ_WX_H +#define SQ_WX_H + +#include +#include +#include + + +namespace ScriptBindings +{ + namespace SQ_WX_binding + { + + void bind_wxString(HSQUIRRELVM vm); + } + + void bind_wx_util_dialogs(HSQUIRRELVM vm); + void Register_wxGlobals(HSQUIRRELVM vm); + void bind_wxConstants(HSQUIRRELVM vm); +} + +#endif // SQ_WX_H diff --git a/src/include/scripting/bindings/sq_wx/sq_wx_type_handler.h b/src/include/scripting/bindings/sq_wx/sq_wx_type_handler.h new file mode 100644 index 0000000000..f3bd3867d0 --- /dev/null +++ b/src/include/scripting/bindings/sq_wx/sq_wx_type_handler.h @@ -0,0 +1,191 @@ +#ifndef SQ_WX_TYPE_HANDLER_H_INCLUDED +#define SQ_WX_TYPE_HANDLER_H_INCLUDED + +#include +#include + +namespace Sqrat +{ +template<> +struct Var { + wxString value; + Var(HSQUIRRELVM v, SQInteger idx) { + if (!Sqrat::Error::Occurred(v)) { + wxString* ptr = ClassType::GetInstance(v, idx); + if (ptr != NULL) { + value = *ptr; + } else { + Sqrat::Error::Clear(v); + switch(sq_gettype(v,idx)) + { + case OT_INTEGER: // It is a const char '' + { + SQInteger val; + sq_getinteger(v,idx,&val); + value.Printf(wxT("%c"),static_cast(val)); + break; + } + default: + { + const SQChar* str; + sq_tostring(v, idx); + sq_getstring(v, -1, &str); + value = wxString::FromUTF8(str); + sq_pop(v, 1); + break; + } + } + } + } + } + + static void push(HSQUIRRELVM v, const wxString& value) { + ClassType::PushInstanceCopy(v, value); + } +}; + +template<> +struct Var { + wxString value; + Var(HSQUIRRELVM v, SQInteger idx) { + if (!Sqrat::Error::Occurred(v)) { + wxString* ptr = ClassType::GetInstance(v, idx); + if (ptr != NULL) { + value = *ptr; + } else { + Sqrat::Error::Clear(v); + switch(sq_gettype(v,idx)) + { + case OT_INTEGER: // It is a const char '' + { + SQInteger val; + sq_getinteger(v,idx,&val); + value.Printf(wxT("%c"),static_cast(val)); + break; + } + default: + { + const SQChar* str; + sq_tostring(v, idx); + sq_getstring(v, -1, &str); + value = wxString::FromUTF8(str); + sq_pop(v, 1); + break; + } + } + } + } + } + + static void push(HSQUIRRELVM v, const wxString value) { + ClassType::PushInstanceCopy(v, value); + } +}; + + +template<> +struct Var { + + wxString value; + + Var(HSQUIRRELVM v, SQInteger idx) { + if (!Sqrat::Error::Occurred(v)) { + wxString* ptr = ClassType::GetInstance(v, idx); + if (ptr != NULL) { + value = *ptr; + } else { + Sqrat::Error::Clear(v); + const SQChar* str; + sq_tostring(v, idx); + sq_getstring(v, -1, &str); + value = wxString::FromUTF8(str); + sq_pop(v, 1); + } + } + } + static void push(HSQUIRRELVM v, const wxString& value) { + ClassType::PushInstanceCopy(v, value); + } +}; + +template<> +struct Var { + + wxString value; + + Var(HSQUIRRELVM v, SQInteger idx) { + if (!Sqrat::Error::Occurred(v)) { + wxString* ptr = ClassType::GetInstance(v, idx); + if (ptr != NULL) { + value = *ptr; + } else { + Sqrat::Error::Clear(v); + const SQChar* str; + sq_tostring(v, idx); + sq_getstring(v, -1, &str); + value = wxString::FromUTF8(str); + sq_pop(v, 1); + } + } + } + + static void push(HSQUIRRELVM v, const wxString& value) { + ClassType::PushInstanceCopy(v, value); + } +}; + + +template<> +struct Var { + wxString* value; + Var(HSQUIRRELVM v, SQInteger idx){ + if (!Sqrat::Error::Occurred(v)) { + value = ClassType::GetInstance(v, idx); + if (value != NULL) { + return; + } else { + Sqrat::Error::Clear(v); + Sqrat::Error::Throw(v,"Tried to get an wxString* from a string"); + } + } + } + static void push(HSQUIRRELVM v, wxString* value) { + ClassType::PushInstanceCopy(v, *value); + } +}; + + +/* +template +struct Var { + T* const value; + Var(HSQUIRRELVM vm, SQInteger idx) : value(ClassType::GetInstance(vm, idx)) { + } + static void push(HSQUIRRELVM vm, T* const value) { + ClassType::PushInstance(vm, value); + } +}; + +template +struct Var { + const T* value; + Var(HSQUIRRELVM vm, SQInteger idx) : value(ClassType::GetInstance(vm, idx)) { + } + static void push(HSQUIRRELVM vm, const T* value) { + ClassType::PushInstance(vm, const_cast(value)); + } +}; + +template +struct Var { + const T* const value; + Var(HSQUIRRELVM vm, SQInteger idx) : value(ClassType::GetInstance(vm, idx)) { + } + static void push(HSQUIRRELVM vm, const T* const value) { + ClassType::PushInstance(vm, const_cast(value)); + } +};*/ + +} + +#endif // SQ_WX_TYPE_HANDLER_H_INCLUDED diff --git a/src/sdk/scripting/bindings/sc_wxtypes.cpp b/src/sdk/scripting/bindings/sc_wxtypes.cpp deleted file mode 100644 index a4fc848232..0000000000 --- a/src/sdk/scripting/bindings/sc_wxtypes.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 - * http://www.gnu.org/licenses/lgpl-3.0.html - * - * $Revision$ - * $Id$ - * $HeadURL$ - */ - -#include "sdk_precomp.h" -#ifndef CB_PRECOMP - #include - #include -#endif -#include -#include - -#include "sc_base_types.h" - -namespace ScriptBindings -{ - /////////////////// - // wxArrayString // - /////////////////// - SQInteger wxArrayString_Index(HSQUIRRELVM v) - { - CompileTimeAssertion::eval>::Assert(); - StackHandler sa(v); - wxArrayString& self = *SqPlus::GetInstance(v, 1); - wxString inpstr = *SqPlus::GetInstance(v, 2); - bool chkCase = true; - bool frmEnd = false; - if (sa.GetParamCount() >= 3) - chkCase = sa.GetBool(3); - if (sa.GetParamCount() == 4) - frmEnd = sa.GetBool(4); - return sa.Return((SQInteger)self.Index(inpstr.c_str(), chkCase, frmEnd)); - } - SQInteger wxArrayString_SetItem(HSQUIRRELVM v) - { - StackHandler sa(v); - if (sa.GetParamCount() != 3) - return sq_throwerror(v, "wxArrayString::SetItem wrong number of parameters!"); - wxArrayString& self = *SqPlus::GetInstance(v, 1); - int index = sa.GetInt(2); - if (index < 0 || size_t(index) >= self.GetCount()) - return sq_throwerror(v, "wxArrayString::SetItem index out of bounds!"); - const wxString &value = *SqPlus::GetInstance(v, 3); - self[index] = value; - return 0; - } - - ////////////// - // wxColour // - ////////////// - SQInteger wxColour_OpToString(HSQUIRRELVM v) - { - StackHandler sa(v); - wxColour& self = *SqPlus::GetInstance(v, 1); - wxString str = wxString::Format(_T("[r=%d, g=%d, b=%d]"), self.Red(), self.Green(), self.Blue()); - return sa.Return((const SQChar*)str.mb_str(wxConvUTF8)); - } - - //////////////// - // wxFileName // - //////////////// - SQInteger wxFileName_OpToString(HSQUIRRELVM v) - { - StackHandler sa(v); - wxFileName& self = *SqPlus::GetInstance(v, 1); - return sa.Return((const SQChar*)self.GetFullPath().mb_str(wxConvUTF8)); - } - - ///////////// - // wxPoint // - ///////////// - - // wxPoint operator== - SQInteger wxPoint_OpCmp(HSQUIRRELVM v) - { - StackHandler sa(v); - wxPoint& self = *SqPlus::GetInstance(v, 1); - wxPoint& other = *SqPlus::GetInstance(v, 2); - return sa.Return(self==other); - } - SQInteger wxPoint_x(HSQUIRRELVM v) - { - StackHandler sa(v); - wxPoint& self = *SqPlus::GetInstance(v, 1); - return sa.Return((SQInteger)(self.x)); - } - SQInteger wxPoint_y(HSQUIRRELVM v) - { - StackHandler sa(v); - wxPoint& self = *SqPlus::GetInstance(v, 1); - return sa.Return((SQInteger)(self.y)); - } - - ////////////// - // wxString // - ////////////// - - // the _() function for scripts - wxString static_(const SQChar* str) - { - return wxGetTranslation(cbC2U(str)); - } - - // the _T() function for scripts - wxString static_T(const SQChar* str) - { - return cbC2U(str); - } - - // wxString operator+ - SQInteger wxString_OpAdd(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString result; - wxString& str1 = *SqPlus::GetInstance(v, 1); - if (sa.GetType(2) == OT_INTEGER) - { -#ifdef _SQ64 - result.Printf(_T("%s%ld"), str1.c_str(), sa.GetInt(2)); -#else - result.Printf(_T("%s%d"), str1.c_str(), sa.GetInt(2)); -#endif - } - else if (sa.GetType(2) == OT_FLOAT) - result.Printf(_T("%s%f"), str1.c_str(), sa.GetFloat(2)); - else if (sa.GetType(2) == OT_USERPOINTER) - result.Printf(_T("%s%p"), str1.c_str(), sa.GetUserPointer(2)); - else if (sa.GetType(2) == OT_STRING) - result.Printf(_T("%s%s"), str1.c_str(), cbC2U(sa.GetString(2)).c_str()); - else - result = str1 + *SqPlus::GetInstance(v, 2); - return SqPlus::ReturnCopy(v, result); - } - - SQInteger wxString_OpCmp(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& str1 = *SqPlus::GetInstance(v, 1); - if (sa.GetType(2) == OT_STRING) - return sa.Return((SQInteger)str1.Cmp(cbC2U(sa.GetString(2)))); - return sa.Return((SQInteger)str1.Cmp(*SqPlus::GetInstance(v, 2))); - } - - SQInteger wxString_OpToString(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - return sa.Return((const SQChar*)self.mb_str(wxConvUTF8)); - } - - SQInteger wxString_AddChar(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - int idx = sa.GetInt(2); - char tmp[8] = {}; - sprintf(tmp, "%c", idx); - self += cbC2U(tmp); - return sa.Return(); - } - SQInteger wxString_GetChar(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - int idx = sa.GetInt(2); - return sa.Return((SQInteger)(((const char*)cbU2C(self))[idx])); - } - SQInteger wxString_Matches(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - wxString& other = *SqPlus::GetInstance(v, 2); - return sa.Return(self.Matches(other)); - } - SQInteger wxString_AfterFirst(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - SQInteger search_char = static_cast( sa.GetInt(2) ); - if ( !search_char ) // Probably it's a wxString - { - wxString& temp = *SqPlus::GetInstance(v, 2); - #if wxCHECK_VERSION(3, 0, 0) - search_char = static_cast( temp.GetChar(0).GetValue() ); - #else - search_char = static_cast( temp.GetChar(0) ); - #endif - } - return SqPlus::ReturnCopy( v, self.AfterFirst( static_cast( search_char ) ) ); - } - SQInteger wxString_AfterLast(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - SQInteger search_char = static_cast( sa.GetInt(2) ); - if ( !search_char ) // Probably it's a wxString - { - wxString& temp = *SqPlus::GetInstance(v, 2); - #if wxCHECK_VERSION(3, 0, 0) - search_char = static_cast( temp.GetChar(0).GetValue() ); - #else - search_char = static_cast( temp.GetChar(0) ); - #endif - } - return SqPlus::ReturnCopy( v, self.AfterLast( static_cast( search_char ) ) ); - } - SQInteger wxString_BeforeFirst(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - SQInteger search_char = static_cast( sa.GetInt(2) ); - if ( !search_char ) // Probably it's a wxString - { - wxString& temp = *SqPlus::GetInstance(v, 2); - #if wxCHECK_VERSION(3, 0, 0) - search_char = static_cast( temp.GetChar(0).GetValue() ); - #else - search_char = static_cast( temp.GetChar(0) ); - #endif - } - return SqPlus::ReturnCopy( v, self.BeforeFirst( static_cast( search_char ) ) ); - } - SQInteger wxString_BeforeLast(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - SQInteger search_char = static_cast( sa.GetInt(2) ); - if ( !search_char ) // Probably it's a wxString - { - wxString& temp = *SqPlus::GetInstance(v, 2); - #if wxCHECK_VERSION(3, 0, 0) - search_char = static_cast( temp.GetChar(0).GetValue() ); - #else - search_char = static_cast( temp.GetChar(0) ); - #endif - } - return SqPlus::ReturnCopy( v, self.BeforeLast( static_cast( search_char ) ) ); - } - SQInteger wxString_Replace(HSQUIRRELVM v) - { - StackHandler sa(v); - wxString& self = *SqPlus::GetInstance(v, 1); - wxString from = *SqPlus::GetInstance(v, 2); - wxString to = *SqPlus::GetInstance(v, 3); - bool all = true; - if (sa.GetParamCount() == 4) - all = sa.GetBool(4); - return sa.Return((SQInteger)self.Replace(from, to, all)); - } - -//////////////////////////////////////////////////////////////////////////////// - - void Register_wxTypes() - { -#if wxCHECK_VERSION(3, 0, 0) - typedef const wxString& (wxArrayString::*WXARRAY_STRING_ITEM)(size_t nIndex) const; -#else - typedef wxString& (wxArrayString::*WXARRAY_STRING_ITEM)(size_t nIndex) const; -#endif - - /////////////////// - // wxArrayString // - /////////////////// - SqPlus::SQClassDef("wxArrayString"). - emptyCtor(). - func(&wxArrayString::Add, "Add"). - func(&wxArrayString::Clear, "Clear"). -// func(&wxArrayString::Index, "Index"). - staticFuncVarArgs(&wxArrayString_Index, "Index", "*"). - func(&wxArrayString::GetCount, "GetCount"). - func(&wxArrayString::Item, "Item"). - staticFuncVarArgs(&wxArrayString_SetItem, "SetItem", "*"); - - ////////////// - // wxColour // - ////////////// - typedef void(wxColour::*WXC_SET)(const unsigned char, const unsigned char, const unsigned char, const unsigned char); - typedef bool (wxColour::*WXC_ISOK)() const; - SqPlus::SQClassDef("wxColour"). - emptyCtor(). - staticFuncVarArgs(&wxColour_OpToString, "_tostring", ""). - func(&wxColour::Blue, "Blue"). - func(&wxColour::Green, "Green"). - func(&wxColour::Red, "Red"). - func(&wxColour::IsOk, "IsOk"). - func(&wxColour::Set, "Set"); - - //////////////// - // wxFileName // - //////////////// - typedef void(wxFileName::*WXFN_ASSIGN_FN)(const wxFileName&); - typedef void(wxFileName::*WXFN_ASSIGN_STR)(const wxString&, wxPathFormat); - typedef wxString(wxFileName::*WXFN_GETPATH)(int, wxPathFormat)const; -#if wxCHECK_VERSION(3, 0, 0) - typedef bool(wxFileName::*WXFN_SETCWD)()const; -#else - typedef bool(wxFileName::*WXFN_SETCWD)(); -#endif - typedef bool(wxFileName::*WXFN_ISFILEWRITEABLE)()const; - - SqPlus::SQClassDef("wxFileName"). - emptyCtor(). - staticFuncVarArgs(&wxFileName_OpToString, "_tostring", ""). - func(&wxFileName::Assign, "Assign"). - func(&wxFileName::Assign, "Assign"). - func(&wxFileName::AssignCwd, "AssignCwd"). - func(&wxFileName::AssignDir, "AssignDir"). - func(&wxFileName::AssignHomeDir, "AssignHomeDir"). - func(&wxFileName::Clear, "Clear"). - func(&wxFileName::ClearExt, "ClearExt"). -// func(&wxFileName::GetCwd, "GetCwd"). - func(&wxFileName::GetDirCount, "GetDirCount"). - func(&wxFileName::GetDirs, "GetDirs"). - func(&wxFileName::GetExt, "GetExt"). - func(&wxFileName::GetFullName, "GetFullName"). - func(&wxFileName::GetFullPath, "GetFullPath"). - func(&wxFileName::GetLongPath, "GetLongPath"). - func(&wxFileName::GetName, "GetName"). - func(&wxFileName::GetPath, "GetPath"). - func(&wxFileName::GetShortPath, "GetShortPath"). - func(&wxFileName::GetVolume, "GetVolume"). - func(&wxFileName::HasExt, "HasExt"). - func(&wxFileName::HasName, "HasName"). - func(&wxFileName::HasVolume, "HasVolume"). - func(&wxFileName::InsertDir, "InsertDir"). - func(&wxFileName::IsAbsolute, "IsAbsolute"). - func(&wxFileName::IsOk, "IsOk"). - func(&wxFileName::IsRelative, "IsRelative"). - func(&wxFileName::IsDir, "IsDir"). - func(&wxFileName::MakeAbsolute, "MakeAbsolute"). - func(&wxFileName::MakeRelativeTo, "MakeRelativeTo"). - func(&wxFileName::Normalize, "Normalize"). - func(&wxFileName::PrependDir, "PrependDir"). - func(&wxFileName::RemoveDir, "RemoveDir"). - func(&wxFileName::RemoveLastDir, "RemoveLastDir"). - func(&wxFileName::SameAs, "SameAs"). - func(&wxFileName::SetCwd, "SetCwd"). - func(&wxFileName::SetExt, "SetExt"). - func(&wxFileName::SetEmptyExt, "SetEmptyExt"). - func(&wxFileName::SetFullName, "SetFullName"). - func(&wxFileName::SetName, "SetName"). - func(&wxFileName::SetVolume, "SetVolume"). - func(&wxFileName::IsFileWritable,"IsFileWritable"); - - ///////////// - // wxPoint // - ///////////// - SqPlus::SQClassDef("wxPoint"). - emptyCtor(). - staticFuncVarArgs(&wxPoint_OpCmp, "_cmp", "*"). - var(&wxPoint::x, "x"). - var(&wxPoint::y, "y"); - - //////////// - // wxSize // - //////////// - typedef void(wxSize::*WXS_SET)(int, int); - typedef void(wxSize::*WXS_SETH)(int); - typedef void(wxSize::*WXS_SETW)(int); - SqPlus::SQClassDef("wxSize"). - emptyCtor(). - func(&wxSize::GetWidth, "GetWidth"). - func(&wxSize::GetHeight, "GetHeight"). - func(&wxSize::Set, "Set"). - func(&wxSize::SetHeight, "SetHeight"). - func(&wxSize::SetWidth, "SetWidth"); - - ////////////// - // wxString // - ////////////// - SqPlus::RegisterGlobal(&static_, "_"); - SqPlus::RegisterGlobal(&static_T, "_T"); - - typedef int(wxString::*WXSTR_FIRST_STR)(const wxString&)const; - typedef wxString&(wxString::*WXSTR_REMOVE_2)(size_t pos, size_t len); - - SqPlus::SQClassDef("wxString"). - emptyCtor(). - staticFuncVarArgs(&wxString_OpAdd, "_add", "*"). - staticFuncVarArgs(&wxString_OpCmp, "_cmp", "*"). - staticFuncVarArgs(&wxString_OpToString, "_tostring", ""). - func(&wxString::First, "Find"). - staticFuncVarArgs(&wxString_Matches, "Matches", "*"). - staticFuncVarArgs(&wxString_AddChar, "AddChar", "n"). - staticFuncVarArgs(&wxString_GetChar, "GetChar", "n"). - func(&wxString::IsEmpty, "IsEmpty"). - func(&wxString::Length, "Length"). - func(&wxString::Length, "length"). - func(&wxString::Length, "len"). - func(&wxString::Length, "size"). - func(&wxString::Lower, "Lower"). - func(&wxString::LowerCase, "LowerCase"). - func(&wxString::MakeLower, "MakeLower"). - func(&wxString::Upper, "Upper"). - func(&wxString::UpperCase, "UpperCase"). - func(&wxString::MakeUpper, "MakeUpper"). - func(&wxString::Mid, "Mid"). - func(&wxString::Remove, "Remove"). - func(&wxString::RemoveLast, "RemoveLast"). - staticFuncVarArgs(&wxString_Replace, "Replace", "*"). - func(&wxString::Right, "Right"). - staticFuncVarArgs(&wxString_AfterFirst, "AfterFirst", "*"). - staticFuncVarArgs(&wxString_AfterLast, "AfterLast", "*"). - staticFuncVarArgs(&wxString_BeforeFirst, "BeforeFirst", "*"). - staticFuncVarArgs(&wxString_BeforeLast, "BeforeLast", "*"); - } -}; diff --git a/src/sdk/scripting/bindings/sq_wx/sq_util_dialogs.cpp b/src/sdk/scripting/bindings/sq_wx/sq_util_dialogs.cpp new file mode 100644 index 0000000000..895575d82a --- /dev/null +++ b/src/sdk/scripting/bindings/sq_wx/sq_util_dialogs.cpp @@ -0,0 +1,176 @@ +/* + * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 + * http://www.gnu.org/licenses/lgpl-3.0.html + * + * $Revision$ + * $Id$ + * $HeadURL$ + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + + +/** \defgroup sq_dialogs Squirrel User dialogs + * \ingroup Squirrel + * \brief Useful dialogs for interacting with user + */ + +namespace ScriptBindings +{ + SQInteger wx_GetColourFromUser(HSQUIRRELVM vm) + { + StackHandler sa(vm); + const wxColour& c = sa.GetParamCount() == 2 ? *sa.GetInstance(2) : *wxBLACK; + sa.PushInstanceCopy(wxGetColourFromUser(Manager::Get()->GetAppWindow(),c)); + return SC_RETURN_VALUE; + } + + long wx_GetNumberFromUser(const wxString& message, const wxString& prompt, const wxString& caption, long value) + { + return wxGetNumberFromUser(message, prompt, caption, value); + } + wxString wx_GetPasswordFromUser(const wxString& message, const wxString& caption, const wxString& default_value) + { + return wxGetPasswordFromUser(message, caption, default_value); + } + wxString wx_GetTextFromUser(const wxString& message, const wxString& caption, const wxString& default_value) + { + return wxGetTextFromUser(message, caption, default_value); + } + + wxArrayString wx_GetFileFromUser(const wxString& message, const wxString& caption, const wxString& default_value,const wxString& wildcart,long style) + { + wxFileDialog* filedlg; + filedlg = new wxFileDialog(nullptr,message,default_value,wxEmptyString,wildcart,style); + wxArrayString ret; + if(filedlg->ShowModal() == wxID_OK) + { + filedlg->GetPaths(ret); + } + return ret; + } + + wxString wx_GetDirFromUser(const wxString& message, const wxString& default_path,long style) + { + return wxDirSelector(message,default_path,style,wxDefaultPosition,nullptr); + } + + void bind_wx_util_dialogs(HSQUIRRELVM vm) + { + /** \ingroup sq_dialogs + *### wxGetColourFromUser(value) + * + * - __value__ A default value [wxColor] + * + * This function displays an dialog with the possibility to ask a color from the user + * + * - __return__ The Value entered by the user or _value_ + */ + /** \ingroup sq_dialogs + *### wxGetNumberFromUser(message,prompt,caption,value) + * + * - __message__ Message to inform the user [wxString] + * - __prompt__ Prompt to inform the user [wxString] + * - __caption__ The caption for the Dialog [wxString] + * - __value__ A default value [int] + * + * This function displays an dialog with the possibility to ask a number from the user + * + * - __return__ The Value entered by the user or _value_ + */ + + /** \ingroup sq_dialogs + *### wxGetPasswordFromUser(message,prompt,caption,value) + * + * - __message__ Message to inform the user [wxString] + * - __caption__ The caption for the Dialog [wxString] + * - __value__ A default value [wxString] + * + * This function displays an dialog with the possibility to ask for a password + * + * - __return__ The Value entered by the user or _value_ + */ + + /** \ingroup sq_dialogs + *### wxGetTextFromUser(key,default_value) + * + * - __message__ Message to inform the user [wxString] + * - __caption__ The caption for the Dialog [wxString] + * - __value__ A default value [wxString] + * + * This function displays an dialog with the possibility to ask for a text from the user + * + * - __return__ The Value entered by the user or _value_ + */ + + /** \ingroup sq_dialogs + *### wxGetFileFromUser(message, caption, default_value,wildcart,style) + * + * - __message__ Message to inform the user [wxString] + * - __caption__ ... [wxString] + * - __default_value__ The Default file/path [wxString] + * - __wildcart__ The wildcart to filter the files [wxString] + * - __style__ The styles: wxFD_DEFAULT_STYLE, wxFD_OPEN, wxFD_SAVE, wxFD_OVERWRITE_PROMPT, wxFD_FILE_MUST_EXIST, wxFD_MULTIPLE, wxFD_CHANGE_DIR, wxFD_PREVIEW + * + * + * This function displays an dialog with the possibility to ask for one or multiple files to be saved or loaded + * + * - __return__ A wxArrayString with the given files (empty if the user canceled the dialog) + */ + + /** \ingroup sq_dialogs + *### wxBell() + * + * Ring the system Bell + * + * - __return__ + */ + + /** \ingroup sq_dialogs + *### wxDirSelector(message,default_value,style) + * + * - __message__ Message to inform the user [wxString] + * - __default_value__ The Default path [wxString] + * - __style__ The styles: wxDD_DEFAULT_STYLE, wxDD_DIR_MUST_EXIST, wxDD_CHANGE_DIR + * + * This function displays an dialog with the possibility to ask for a path + * + * - __return__ A wxString with the given path ( a empty string if the user aborts the dialog) + */ + + BIND_INT_CONSTANT(wxDD_DEFAULT_STYLE); + BIND_INT_CONSTANT(wxDD_DIR_MUST_EXIST); + BIND_INT_CONSTANT(wxDD_CHANGE_DIR); + + // FileDialog styles + BIND_INT_CONSTANT(wxFD_DEFAULT_STYLE); + BIND_INT_CONSTANT(wxFD_OPEN); + BIND_INT_CONSTANT(wxFD_SAVE); + BIND_INT_CONSTANT(wxFD_OVERWRITE_PROMPT); + BIND_INT_CONSTANT(wxFD_FILE_MUST_EXIST); + BIND_INT_CONSTANT(wxFD_MULTIPLE); + BIND_INT_CONSTANT(wxFD_CHANGE_DIR); + BIND_INT_CONSTANT(wxFD_PREVIEW); + + + Sqrat::RootTable() + .SquirrelFunc(_SC("wxGetColourFromUser"),&wx_GetColourFromUser) + .Func(_SC("wxGetNumberFromUser"),&wx_GetNumberFromUser) + .Func(_SC("wxGetPasswordFromUser"),&wx_GetPasswordFromUser) + .Func(_SC("wxGetTextFromUser"),&wx_GetTextFromUser) + .Func(_SC("wxGetFileFromUser"),&wx_GetFileFromUser) + .Func(_SC("wxBell"),&wxBell) + .Func(_SC("wxDirSelector"),&wx_GetDirFromUser); + + } +} diff --git a/src/sdk/scripting/bindings/sq_wx/sq_wx.cpp b/src/sdk/scripting/bindings/sq_wx/sq_wx.cpp new file mode 100644 index 0000000000..18c840bc45 --- /dev/null +++ b/src/sdk/scripting/bindings/sq_wx/sq_wx.cpp @@ -0,0 +1,62 @@ +/* + * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 + * http://www.gnu.org/licenses/lgpl-3.0.html + * + * $Revision$ + * $Id$ + * $HeadURL$ + */ + + +#include +#include +#include + +namespace ScriptBindings +{ + + long long EmptyFunction() + { + return 0; + } + + SQInteger sc_wxLongLong_tostring(HSQUIRRELVM vm) + { + StackHandler sa(vm); + if(sa.GetParamCount() < 1) + return sa.ThrowError(_("wxLongLong::_tostring() wrong number of parameter")); + try + { + wxLongLong* inst = sa.GetInstance(1); + sa.PushValue(inst->ToString().ToUTF8().data()); + return SC_RETURN_VALUE; + } catch (CBScriptException &e) + { + return sa.ThrowError(_("wxLongLong::_tostring()")+ e.Message()); + } + } + + /** \brief Bind wx Types (wxString,wxIntArray etc.) to the vm + * + * \param vm HSQUIRRELVM A Squirrel vm to which wx is bound + * + */ + void Register_wxGlobals(HSQUIRRELVM vm) + { + + SQ_WX_binding::bind_wxString(vm); + bind_wx_util_dialogs(vm); + bind_wxConstants(vm); + + Sqrat::Class stop_watch(vm,"wxStopWatch"); + stop_watch + .Func("Pause",&wxStopWatch::Pause) + .Func("Resume",&wxStopWatch::Resume) + .Func("Start",&wxStopWatch::Start) + .Func("Time",&wxStopWatch::Time); + Sqrat::RootTable(vm).Bind("wxStopWatch",stop_watch); + + Sqrat::RootTable(vm).Func("wxLaunchDefaultBrowser", wxLaunchDefaultBrowser); + + } +} diff --git a/src/sdk/scripting/bindings/sq_wx/sq_wx_constants.cpp b/src/sdk/scripting/bindings/sq_wx/sq_wx_constants.cpp new file mode 100644 index 0000000000..955855f399 --- /dev/null +++ b/src/sdk/scripting/bindings/sq_wx/sq_wx_constants.cpp @@ -0,0 +1,62 @@ + +#include +#include +#include +#include +#include + +namespace ScriptBindings +{ + + +void bind_wxConstants(HSQUIRRELVM vm) +{ +/** \defgroup sq_wx_constants wxWidgets constants bound to squirrel + * \ingroup Squirrel + * \brief +*/ + + // path separator for filenames + BIND_WXSTR_CONSTANT_NAMED(wxString(wxFILE_SEP_PATH), "wxFILE_SEP_PATH"); + + // wxPathFormat + BIND_INT_CONSTANT(wxPATH_NATIVE); + BIND_INT_CONSTANT(wxPATH_UNIX); + BIND_INT_CONSTANT(wxPATH_BEOS); + BIND_INT_CONSTANT(wxPATH_MAC); + BIND_INT_CONSTANT(wxPATH_DOS); + BIND_INT_CONSTANT(wxPATH_WIN); + BIND_INT_CONSTANT(wxPATH_OS2); + BIND_INT_CONSTANT(wxPATH_VMS); + + // for wxFileName::GetPath() + BIND_INT_CONSTANT(wxPATH_GET_VOLUME); + BIND_INT_CONSTANT(wxPATH_GET_SEPARATOR); + + // wxPathNormalize + BIND_INT_CONSTANT(wxPATH_NORM_ENV_VARS); + BIND_INT_CONSTANT(wxPATH_NORM_DOTS); + BIND_INT_CONSTANT(wxPATH_NORM_TILDE); + BIND_INT_CONSTANT(wxPATH_NORM_CASE); + BIND_INT_CONSTANT(wxPATH_NORM_ABSOLUTE); + BIND_INT_CONSTANT(wxPATH_NORM_LONG); + BIND_INT_CONSTANT(wxPATH_NORM_SHORTCUT); + BIND_INT_CONSTANT(wxPATH_NORM_ALL); + + // dialog buttons + BIND_INT_CONSTANT(wxOK); + BIND_INT_CONSTANT(wxYES_NO); + BIND_INT_CONSTANT(wxCANCEL); + BIND_INT_CONSTANT(wxID_OK); + BIND_INT_CONSTANT(wxID_YES); + BIND_INT_CONSTANT(wxID_NO); + BIND_INT_CONSTANT(wxID_CANCEL); + BIND_INT_CONSTANT(wxICON_QUESTION); + BIND_INT_CONSTANT(wxICON_INFORMATION); + BIND_INT_CONSTANT(wxICON_WARNING); + BIND_INT_CONSTANT(wxICON_ERROR); + BIND_INT_CONSTANT(wxICON_HAND); + +} + +} diff --git a/src/sdk/scripting/bindings/sq_wx/sq_wx_string.cpp b/src/sdk/scripting/bindings/sq_wx/sq_wx_string.cpp new file mode 100644 index 0000000000..242ab499c1 --- /dev/null +++ b/src/sdk/scripting/bindings/sq_wx/sq_wx_string.cpp @@ -0,0 +1,707 @@ +/* + * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 + * http://www.gnu.org/licenses/lgpl-3.0.html + * + * $Revision$ + * $Id$ + * $HeadURL$ + */ + +#include +#include +#include + +#include "scripting/bindings/sq_wx/sq_wx.h" +#include "scripting/bindings/sc_binding_util.h" +#include "scripting/bindings/sc_cb_vm.h" + +// We need at least version 2.8.5 +#if !wxCHECK_VERSION(2, 8, 5) +#error Minimal wxWidgets version is 2.8.5 +#endif + +namespace ScriptBindings +{ +namespace SQ_WX_binding +{ + +/** \defgroup sq_wxstring wxString binding to Squirrel + * \ingroup Squirrel + * \brief The binding of the wxString class to Squirrel + * + * ### Attention + * The wxString binding is UTF8 capable, so all characters should work. But if you use unicode you can't use + * the single quotes ('') for constants in wxString::Replace or wxString::AfterFirst because squirrel uses + * internally only char for constants and so they have not enough space. You have to use double quotes ("") + * instead. + */ + + /** + * \ingroup sq_wxstring + * \brief Function bound to squirrel: + * + * ### wxString Function bound to squirrel + * | Name | parameter | description | info | + * | :-------------- | :--------------------------- | :------------------------ | :--------- | + * | wxString() | string; wxString; SQchar; int; float | create a wxString object | x | + * | Append | x | x | x | + * | IsEmpty | x | x | x | + * | Length | x | x | x | + * | len | x | x | x | + * | size | x | x | x | + * | Lower | x | x | x | + * | LowerCase | x | x | x | + * | MakeLower | x | x | x | + * | Upper | x | x | x | + * | MakeUpper | x | x | x | + * | Mid | x | x | x | + * | Remove | x | x | x | + * | RemoveLast | x | x | x | + * | Replace | x | x | x | + * | AfterFirst | x | x | x | + * | BeforeFirst | x | x | x | + * | BeforeLast | x | x | x | + * | Right | x | x | x | + * | Matches | x | x | x | + * | GetChar | x | x | x | + * | AddChar | x | x | x | + * | Find | x | x | x | + * | insert | size_t nPos, string | x | x | + * | replace | size_t nStart, size_t nLen, string x | x | x | + * | ToInt | int base | returns a table with two entries: the _value_ and a bool _success_ which is true on success | x | + * | ToDouble | | returns a table with two entries: the _value_ and a bool _success_ which is true on success | x | + * + * ### Global function for wxSting + * | Name | parameter | description | info | + * | :-------------- | :-------------------- | :-------------- | :--------- | + * | _T() | string | converts a normal string to a wxString object. Needed only for compatibility | x | + * | wxT() | string | same as _T | x | + * | _() | string | search for the translation of the string and return a wxString object. | x | + * + * ### Example for ToInt/ToDouble + * + * ~~~~~~~~~ + * local string = wxString("42"); + * local ret_val = string.ToInt(10); + * if(!ret_val.success) + * error("Could not convert string to int"); + * + * print("String to int result: " + ret_val.value +"\n" ); + * ~~~~~~~~~ + * + */ + + + +/** \brief Converts a wxString to a sqrat/squirrel string. + * Takes care of the UNICODE conversion. Scripts use internally UTF8, wxString uses the system specified Encoding + * + * \param input wxString Input String + * \return Sqrat::string A squirrel string (char) + * + */ +Sqrat::string cWxToStdString(wxString input) +{ + return Sqrat::string( input.ToUTF8()); +} + +/** \brief Converts a squirrel String to a wxString. + * Takes care of the UNICODE conversion + * + * \param input SQChar* Pointer to the inout string + * \return wxString A wxString object + * + */ +wxString StdToWxString(SQChar* input) +{ + return wxString::FromUTF8(input); +} + +/** \brief Converts a squirrel String to a translated wxString. + * Takes care of the UNICODE conversion + * + * \param input SQChar* Pointer to the inout string + * \return wxString A wxString object + * + */ +wxString StdToWxStringTranslated(SQChar* input) +{ + return wxGetTranslation(wxString::FromUTF8(input)); +} + +/** \brief The constructor function which squirrel uses for creating a wxWidgets object from various other types + * + * types supported: wxString, native string, int, float, empty + * \param vm HSQUIRRELVM + * \return SQInteger + * + */ +static SQInteger wxString_constructor(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try + { + if (sa.GetParamCount() == 1) //Empty constructor.... + { + wxString* instance = new wxString(); + Sqrat::DefaultAllocator::SetInstance(vm,1,instance); + //sq_setinstanceup(vm, 1, instance); + //sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; + } + else if (sa.GetParamCount() == 2) // 1 Parameter + { + // Lets check which type it is + //copy Constructor? + Sqrat::Var copy(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + wxString* instance = new wxString(copy.value); + Sqrat::DefaultAllocator::SetInstance(vm,1,instance); + //sq_setinstanceup(vm, 1, instance); + //sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; + } + // it was not the copy ctr + // lets test if it is a squirrel string + Sqrat::Error::Clear(vm); + Sqrat::Var char_arr(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + wxString* instance = new wxString(wxString::FromUTF8(char_arr.value)); + Sqrat::DefaultAllocator::SetInstance(vm,1,instance); + //sq_setinstanceup(vm, 1, instance); + //sq_setreleasehook(vm, 1, &Sqrat::DefaultAllocator::Delete); + return SC_RETURN_OK; + } + // Wrong ctr parameter + Sqrat::Error::Clear(vm); + return sa.ThrowError(Sqrat::FormatTypeError(vm, 2, Sqrat::ClassType::ClassName() + _SC("|SQChar*")).c_str()); + } + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::constructor:") + e.Message()); + } + + return sa.ThrowError(_T("wxString::constructor: wrong number of parameters")); +} + +/** \brief The operator+ for wxString in squirrel + * + * \param vm HSQUIRRELVM + * \return SQInteger + * + */ +static SQInteger wxString_add(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try + { + if (sa.GetParamCount() == 1) //no parameter to add + { + return sa.ThrowError(_T("wxString operator+: wrong number of parameters")); + } + else if (sa.GetParamCount() == 2) // 1 Parameter + { + // Lets check which type it is + + //First get the "this" + wxString* instance = Sqrat::ClassType::GetInstance(vm, 1); + if(instance == NULL) + { + return sa.ThrowError(_T("wxString operator+: no base")); + } + + wxString ret(*instance); // create the return value + + // Test if we add wxString + Sqrat::Var copy(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + ret.Append(copy.value); + Sqrat::Var::push(vm, ret); + return SC_RETURN_VALUE; + } + // Test if we add squirrel string + Sqrat::Error::Clear(vm); + Sqrat::Var char_arr(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + ret.Append(wxString::FromUTF8(char_arr.value)); + Sqrat::Var::push(vm, ret); + return SC_RETURN_VALUE; + } + // Test if we add a int (this probably will never happen, because squirrel transforms it to a string?) + Sqrat::Error::Clear(vm); + Sqrat::Var int_val(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + ret.Append(wxString::Format(wxT("%d"),int_val.value)); + Sqrat::Var::push(vm, ret); + return SC_RETURN_VALUE; + } + // Test if we add a floating point number (this probably will never happen, because squirrel transforms it to a string?) + Sqrat::Error::Clear(vm); + Sqrat::Var float_val(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + ret.Append(wxString::Format(wxT("%f"),int_val.value)); + Sqrat::Var::push(vm, ret); + return SC_RETURN_VALUE; + } + // Wrong type of parameter + wxString error_msg; + return sa.ThrowError(Sqrat::FormatTypeError(vm, 2, Sqrat::ClassType::ClassName() + _SC("|SQChar*|int|float")).c_str()); + } + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString operator+:") + e.Message()); + } + return sa.ThrowError(_T("wxString operator+: wrong number of parameters")); +} + +/** \brief Compare two strings. This function is only used for > and <. For == you have to use a function like wxString::Compare() + * + * \param vm HSQUIRRELVM + * \return SQInteger + * + */ +static SQInteger wxString_OpCmp(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try + { + int ret = 0; + if (sa.GetParamCount() < 2) + { + sa.ThrowError(_T("wxString operator cmp (<,>): wrong number of parameters")); + } + //First get the "this" + wxString* lhs = sa.GetInstance(1); + wxString rhs; + if(lhs == NULL) + { + sa.ThrowError(_T("wxString cmp (<,>): have no base")); + } + Sqrat::Var str_val(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + ret = lhs->CompareTo(str_val.value); + Sqrat::Var::push(vm, ret); + return SC_RETURN_VALUE; + } + Sqrat::Error::Clear(vm); + Sqrat::Var char_arr(vm, 2); + if (!Sqrat::Error::Occurred(vm)) + { + ret = lhs->CompareTo(wxString::Format(wxT("%s"),char_arr.value)); + Sqrat::Var::push(vm, ret); + return SC_RETURN_VALUE; + } + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString operator cmp (<,>): ") + e.Message()); + } + return sa.ThrowError(_T("wxString operator cmp (<,>): wrong number of parameters")); +} + +static SQInteger wxString_Replace(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + try + { + if (sa.GetParamCount() < 3) + { + sa.ThrowError(_T("wxString::Replace: wrong number of parameters")); + } + //First get the "this" + wxString* self = Sqrat::ClassType::GetInstance(vm, 1); + if(self == NULL) + { + sa.ThrowError(_T("wxString::Replace: have no base")); + } + + bool all = true; + Sqrat::Var old_str(vm,2); + Sqrat::Var new_str(vm,3); + if(Sqrat::Error::Occurred(vm)) + { + return sa.ThrowError(Sqrat::FormatTypeError(vm, 2, Sqrat::ClassType::ClassName()).c_str()); + } + + if(sa.GetParamCount() == 4) + { + Sqrat::Var all_val(vm,4); + if(Sqrat::Error::Occurred(vm)) + { + return sa.ThrowError(Sqrat::FormatTypeError(vm, 2, _SC("bool")).c_str()); + } + + all = all_val.value; + } + Sqrat::Var::push(vm, self->Replace(old_str.value, new_str.value, all)); + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::Replace: ") + e.Message()); + } +} + +SQInteger wxString_AfterFirst(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + if (sa.GetParamCount() < 2) + { + return sa.ThrowError(_T("wxString::AfterFirst: wrong number of parameters")); + } + try + { + //First get the "this" + wxString* self = Sqrat::ClassType::GetInstance(vm, 1); + if(self == NULL) + { + return sa.ThrowError(_T("wxString::AfterFirst: have no base")); + } + + wxString search_char= sa.GetValue(2); + + sa.PushValue(self->AfterFirst(search_char[0])); + //Sqrat::Var::push(vm, self->AfterFirst(search_char[0])); + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::AfterFirst: ") + e.Message()); + } +} + +SQInteger wxString_AfterLast(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + if (sa.GetParamCount() < 2) + { + return sa.ThrowError(_T("wxString::AfterLast: wrong number of parameters")); + } + try + { + //First get the "this" + wxString* self = sa.GetInstance(1); //Sqrat::ClassType::GetInstance(vm, 1); + if(self == NULL) + { + return sa.ThrowError(_T("wxString::AfterLast: have no base")); + } + + wxString search_char = sa.GetValue(2); + + + sa.PushValue(self->AfterLast(search_char[0])); + //Sqrat::Var::push(vm, self->AfterLast(search_char[0])); + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::AfterLast: ") + e.Message()); + } +} + +SQInteger wxString_BeforeFirst(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + if (sa.GetParamCount() < 2) + { + return sa.ThrowError(_T("wxString::BeforeFirst: wrong number of parameters")); + } + try + { + //First get the "this" + wxString* self = Sqrat::ClassType::GetInstance(vm, 1); + if(self == NULL) + { + return sa.ThrowError(_T("wxString::BeforeFirst: have no base")); + } + wxString search_char = sa.GetValue(2); + + + sa.PushValue(self->BeforeFirst(search_char[0])); + + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::BeforeFirst:") + e.Message()); + } +} + +SQInteger wxString_BeforeLast(HSQUIRRELVM vm) +{ + StackHandler sa(vm); + + if (sa.GetParamCount() < 2) + { + return sa.ThrowError(_T("wxString::BeforeLast: wrong number of parameters")); + } + try + { + //First get the "this" + wxString* self = sa.GetInstance(1); + if(self == NULL) + { + return sa.ThrowError(_T("wxString::BeforeLast: have no base")); + } + + wxString search_char = sa.GetValue(2); + + sa.PushValue(self->BeforeLast(search_char[0])); + + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::BeforeLast:") + e.Message()); + } +} + + +SQInteger wxString_Matches(HSQUIRRELVM v) +{ + StackHandler sa(v); + try + { + + wxString& self = *sa.GetInstance(1); + wxString other = sa.GetValue(2); + sa.PushValue(self.Matches(other)); + + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::Matches: ") + e.Message()); + } +} + +SQInteger wxString_GetChar(HSQUIRRELVM v) +{ + StackHandler sa(v); + try + { + + wxString& self = *sa.GetInstance(1); + unsigned int pos = sa.GetValue(2); + if(pos >= self.length()) + return SC_RETURN_FAILED; + + SQChar tmp = self.To8BitData()[pos]; + sa.PushValue(static_cast(tmp)); + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::GetChar: ") + e.Message()); + } +} + +SQInteger wxString_AddChar(HSQUIRRELVM v) +{ + StackHandler sa(v); + try + { + wxString& self = *sa.GetInstance(1); + wxString character = sa.GetValue(2); + sa.PushValue(self.Append(character)); + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::AddChar: ") + e.Message()); + } +} + +SQInteger wxString_Find(HSQUIRRELVM v) +{ + StackHandler sa(v); + try + { + wxString& self = *sa.GetInstance(1); + wxString other = sa.GetValue(2); + sa.PushValue(self.Find(other)); + return SC_RETURN_VALUE; + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::Find: ") + e.Message()); + } +} + + +SQInteger wxString_ToInt(HSQUIRRELVM v) +{ + StackHandler sa(v); + try + { + wxString& self = *sa.GetInstance(1); + int base = 10; + if(sa.GetParamCount() == 2) + base = sa.GetValue(2); + + long tmp = 0; + bool ret = self.ToLong(&tmp,base); + + Sqrat::Table ret_table(v); + + // TODO (bluehazzard#1#): Inform squirrel user about overflow, underflow? + if(ret && tmp <= std::numeric_limits::max() && tmp >= std::numeric_limits::min()) + { + ret_table.SetValue("success",true); + ret_table.SetValue("value",tmp); + } + else + { + ret_table.SetValue("success", false); + ret_table.SetValue("value", 0); + } + sa.PushValue(ret_table); + + return SC_RETURN_VALUE; + + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::ToInt: ") + e.Message()); + } +} + +SQInteger wxString_ToDouble(HSQUIRRELVM v) +{ + StackHandler sa(v); + try + { + wxString& self = *sa.GetInstance(1); + + + double tmp = 0; + bool ret = self.ToDouble(&tmp); + + Sqrat::Table ret_table(v); + ret_table.SetValue("success",ret); + if(ret) + { + if(tmp <= std::numeric_limits::max() && tmp >= std::numeric_limits::min()) // don't make an overflow + ret_table.SetValue("value",(float) tmp); + else + ret_table.SetValue("value",(float) std::numeric_limits::infinity()); + } + else + ret_table.SetValue("value", std::numeric_limits::quiet_NaN()); + + sa.PushValue(ret_table); + return SC_RETURN_VALUE; + + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::ToDouble: ") + e.Message()); + } +} + +SQInteger wxString_ToLong(HSQUIRRELVM v) +{ + StackHandler sa(v); + try + { + wxString& param = *sa.GetInstance(2); + + + long tmp = 0; + bool ret = param.ToLong(&tmp); + + Sqrat::Table ret_table(v); + // TODO (bluehazzard#1#): Inform squirrel user about overflow, underflow? + if(ret && tmp <= std::numeric_limits::max() && tmp >= std::numeric_limits::min()) + { + ret_table.SetValue("success",true); + ret_table.SetValue("value",tmp); + } + else + { + ret_table.SetValue("success", false); + ret_table.SetValue("value", 0); + } + sa.PushValue(ret_table); + return SC_RETURN_VALUE; + + } + catch(CBScriptException &e) + { + return sa.ThrowError(_("wxString::ToLong: ") + e.Message()); + } +} + +/** \brief Bind wxString to the Squirrel vm + * + * \param vm HSQUIRRELVM vm to which wxString should be bound + * \return void + * + */ +void bind_wxString(HSQUIRRELVM vm) +{ + using namespace Sqrat; + + Class bwxString(vm,"wxString"); + bwxString.SquirrelFunc("constructor",&wxString_constructor) + .SquirrelFunc(_SC("_cmp"),&wxString_OpCmp) + .SquirrelFunc("_add", &wxString_add) + .GlobalFunc(_SC("_tostring"),&cWxToStdString) + + .Func("Append",&wxString::Append) + .Func("IsEmpty",&wxString::IsEmpty) + .Func("Length", &wxString::Len) + .Func("length", &wxString::Len) + .Func("len", &wxString::Len) + .Func("size", &wxString::Len) + .Func("Lower", &wxString::Lower) + .Func("LowerCase", &wxString::LowerCase) + .Func("MakeLower", &wxString::MakeLower) + .Func("Upper", &wxString::Upper) + .Func("UpperCase", &wxString::UpperCase) + .Func("MakeUpper", &wxString::MakeUpper) + .Func("Mid", &wxString::Mid) + .Func("Remove", &wxString::Remove) + .Func("RemoveLast", &wxString::RemoveLast) + .Func("insert",&wxString::insert) + .Func("Cmp",&wxString::Cmp) + .Func("CmpNoCase",&wxString::CmpNoCase) + .Overload("replace",&wxString::replace) + .Overload("replace",&wxString::replace) + .SquirrelFunc("Replace", &wxString_Replace) + .SquirrelFunc("AfterFirst", &wxString_AfterFirst) + .SquirrelFunc("AfterLast", &wxString_AfterLast) + .SquirrelFunc("BeforeFirst",&wxString_BeforeFirst) + .SquirrelFunc("BeforeLast", &wxString_BeforeLast) + .Func("Right", &wxString::Right) + // TODO (bluehazzard#1#): In wx2.9 this is wxString not wxChar + .SquirrelFunc("Matches",&wxString_Matches) + .SquirrelFunc("GetChar",&wxString_GetChar) + .SquirrelFunc("AddChar",&wxString_AddChar) + .SquirrelFunc("Find", &wxString_Find) + .SquirrelFunc("ToInt", &wxString_ToInt) + .SquirrelFunc("ToDouble",&wxString_ToDouble) + ; + RootTable(vm).Bind(_SC("wxString"),bwxString); + + + RootTable(vm).Func(_SC("_T"),&StdToWxString); + RootTable(vm).Func(_SC("wxT"),&StdToWxString); + RootTable(vm).Func(_SC("_"),&StdToWxStringTranslated); + + Sqrat::RootTable(vm).SquirrelFunc("wxString_ToLong",&wxString_ToLong); +} + + +} // namespace SQ_WX_binding + +} // namespace ScriptBinding diff --git a/src/sdk/scripting/bindings/sq_wx/sq_wxtypes.cpp b/src/sdk/scripting/bindings/sq_wx/sq_wxtypes.cpp new file mode 100644 index 0000000000..8819b60ae5 --- /dev/null +++ b/src/sdk/scripting/bindings/sq_wx/sq_wxtypes.cpp @@ -0,0 +1,441 @@ +/* + * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 + * http://www.gnu.org/licenses/lgpl-3.0.html + * + * $Revision$ + * $Id$ + * $HeadURL$ + */ + +#include "sdk_precomp.h" +#ifndef CB_PRECOMP + #include + #include +#endif +#include +#include + +#include "scripting/bindings/sc_binding_util.h" +#include "scripting/bindings/sc_base_types.h" +#include "scripting/bindings/sc_cb_vm.h" + +namespace ScriptBindings +{ + /////////////////// + // wxArrayString // + /////////////////// + #if wxCHECK_VERSION(3, 0, 0) + typedef const wxString& (wxArrayString::*WXARRAY_STRING_ITEM)(size_t nIndex) const; + #else + typedef wxString& (wxArrayString::*WXARRAY_STRING_ITEM)(size_t nIndex) const; + #endif + SQInteger wxArrayString_Index(HSQUIRRELVM v) + { + CompileTimeAssertion::eval>::Assert(); + StackHandler sa(v); + try + { + wxArrayString& self = *sa.GetInstance(1); + wxString inpstr = sa.GetValue(2); + + bool chkCase = true; + bool frmEnd = false; + if (sa.GetParamCount() >= 3) + chkCase = sa.GetValue(3); + if (sa.GetParamCount() == 4) + frmEnd = sa.GetValue(4); + sa.PushValue(self.Index(inpstr.c_str(), chkCase, frmEnd)); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + SQInteger wxArrayString_SetItem(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + if (sa.GetParamCount() != 3) + return sa.ThrowError(wxT("wxArrayString::SetItem wrong number of parameters!")); + + wxArrayString& self = *sa.GetInstance(1); + int index = sa.GetValue(2); + if (index < 0 || size_t(index) >= self.GetCount()) + return sa.ThrowError(wxT("wxArrayString::SetItem index out of bounds!")); + + const wxString &value = *sa.GetInstance(3); + self[index] = value; + return SC_RETURN_OK; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + SQInteger wxArrayString_Item(HSQUIRRELVM vm) + { + StackHandler sa(vm); + try + { + wxArrayString* inst = sa.GetInstance(1); + int pos = sa.GetValue(2); + + if(inst->GetCount() == 0 || inst->GetCount() < (size_t) pos) + return sa.ThrowError("wxArrayString: GetCount < pos"); + + sa.PushValue(inst->Item(pos)); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + SQInteger wxArrayString_ToString(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxArrayString& self = *sa.GetInstance(1); + wxString str = _("["); + unsigned int i; + for(i = 0; i < self.GetCount()-1;++i) + { + str << self[i] << _(" , "); + } + if(self.GetCount() > 0) + str << self[i]; + + str << _("]"); + sa.PushValue(str.mb_str(wxConvUTF8).data()); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + ////////////// + // wxColour // + ////////////// + SQInteger wxColour_OpToString(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxColour& self = *sa.GetInstance(1); + wxString str = wxString::Format(_T("[r=%d, g=%d, b=%d]"), self.Red(), self.Green(), self.Blue()); + sa.PushValue(str.mb_str(wxConvUTF8).data()); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + SQInteger wxColour_IsOk(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxColour& self = *sa.GetInstance(1); + bool ret = self.IsOk(); + sa.PushValue(ret); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + //////////////// + // wxFileName // + //////////////// + SQInteger wxFileName_OpToString(HSQUIRRELVM vm) + { + StackHandler sa(vm); + try + { + wxFileName& self = *sa.GetInstance(1); + sa.PushValue(self.GetFullPath().mb_str(wxConvUTF8)); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + SQInteger wxFileName_GetPathSeparator(HSQUIRRELVM vm) + { + StackHandler sa(vm); + try + { + wxPathFormat format = sa.GetValue(2); + sa.PushValue(wxString(wxFileName::GetPathSeparator(format))); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + + ///////////// + // wxPoint // + ///////////// + + // wxPoint operator >= <= > < + SQInteger wxPoint_OpCmp(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxPoint& self = *sa.GetInstance(1); + wxPoint& other = *sa.GetInstance(2); + int ret = 0; + if(self != other) + ret = 1; + sa.PushValue(ret); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + // wxPoint compare + SQInteger wxPoint_Cmp(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxPoint& self = *sa.GetInstance(1); + wxPoint& other = *sa.GetInstance(2); + sa.PushValue(self==other); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + + SQInteger wxPoint_OpTostring(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxPoint& self = *sa.GetInstance(1); + wxString output; + output.Printf(_("[%d,%d]"),self.x,self.y); + sa.PushValue(output.mb_str(wxConvUTF8)); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + SQInteger wxPoint_x(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxPoint& self = *sa.GetInstance(1); + sa.PushValue(self.x); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + SQInteger wxPoint_y(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxPoint& self = *sa.GetInstance(1); + sa.PushValue(self.y); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + ////////////// + // wxSize // + ////////////// + SQInteger wxSize_OpTostring(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxSize& self = *sa.GetInstance(1); + wxString output; + output.Printf(_("[%d,%d]"),self.GetX(),self.GetY()); + sa.PushValue(output.mb_str(wxConvUTF8)); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } + + SQInteger wxSize_Cmp(HSQUIRRELVM v) + { + StackHandler sa(v); + try + { + wxSize& self = *sa.GetInstance(1); + wxSize& other = *sa.GetInstance(2); + sa.PushValue(self==other); + return SC_RETURN_VALUE; + } catch(CBScriptException &e) + { + return sa.ThrowError(e.Message()); + } + } +//////////////////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////////////////// + + void Register_wxTypes(HSQUIRRELVM vm) + { + + /////////////////// + // wxArrayString // + /////////////////// + Sqrat::Class array_string(vm,"wxArrayString"); + array_string + //emptyCtor(). + //Ctor<>(). + .Func("Add", &wxArrayString::Add ) + .Func("Clear", &wxArrayString::Clear ) + .SquirrelFunc("Index", &wxArrayString_Index) + .Func("GetCount", &wxArrayString::GetCount) + .SquirrelFunc("Item", &wxArrayString_Item) + .SquirrelFunc("SetItem", &wxArrayString_SetItem) + .SquirrelFunc("_tostring", &wxArrayString_ToString); + + Sqrat::RootTable(vm).Bind("wxArrayString",array_string); + + ////////////// + // wxColour // + ////////////// + typedef void(wxColour::*WXC_SET)(const unsigned char, const unsigned char, const unsigned char, const unsigned char); + Sqrat::Class wx_colour(vm,"wxColour"); + wx_colour. + Ctor(). + Ctor(). + //emptyCtor(). + SquirrelFunc("_tostring", &wxColour_OpToString). + Func("Blue", &wxColour::Blue). + Func("Green", &wxColour::Green). + Func("Red", &wxColour::Red). + SquirrelFunc("IsOk", &wxColour_IsOk). + Func("Set", &wxColour::Set); + Sqrat::RootTable(vm).Bind("wxColour",wx_colour); + + //////////////// + // wxFileName // + //////////////// + typedef void(wxFileName::*WXFN_ASSIGN_FN)(const wxFileName&); + typedef void(wxFileName::*WXFN_ASSIGN_STR)(const wxString&, wxPathFormat); + typedef wxString(wxFileName::*WXFN_GETPATH)(int, wxPathFormat)const; +#if wxCHECK_VERSION(2, 9, 1) + typedef bool(wxFileName::*WXFN_SETCWD)()const; +#else + typedef bool(wxFileName::*WXFN_SETCWD)(); +#endif + typedef bool(wxFileName::*WXFN_ISFILEWRITEABLE)()const; + + Sqrat::Class wx_filename(vm,"wxFileName"); + wx_filename. + //emptyCtor(). + SquirrelFunc("_tostring", &wxFileName_OpToString). + Func("Assign", &wxFileName::Assign). + Func("Assign", &wxFileName::Assign). + Func("AssignCwd", &wxFileName::AssignCwd). + Func("AssignDir", &wxFileName::AssignDir). + Func("AssignHomeDir", &wxFileName::AssignHomeDir). + Func("Clear", &wxFileName::Clear). + Func("ClearExt", &wxFileName::ClearExt). +/// TODO (bluehazzard#1#): GetCwd missing +// Func("GetCwd",&wxFileName::GetCwd). + Func("GetDirCount", &wxFileName::GetDirCount). + Func("GetDirs", &wxFileName::GetDirs). + Func("GetExt", &wxFileName::GetExt). + Func("GetFullName", &wxFileName::GetFullName). + Func("GetFullPath", &wxFileName::GetFullPath). + Func("GetLongPath", &wxFileName::GetLongPath). + Func("GetName", &wxFileName::GetName). + Func("GetPath",&wxFileName::GetPath). + Func("GetShortPath", &wxFileName::GetShortPath). + Func("GetVolume", &wxFileName::GetVolume). + Func("HasExt", &wxFileName::HasExt). + Func("HasName", &wxFileName::HasName). + Func("HasVolume", &wxFileName::HasVolume). + Func("InsertDir", &wxFileName::InsertDir). + Func("IsAbsolute", &wxFileName::IsAbsolute). + Func("IsOk", &wxFileName::IsOk). + Func("IsRelative", &wxFileName::IsRelative). + Func("IsDir", &wxFileName::IsDir). + Func("MakeAbsolute", &wxFileName::MakeAbsolute). + Func("MakeRelativeTo", &wxFileName::MakeRelativeTo). + Func("Normalize", &wxFileName::Normalize). + Func("PrependDir", &wxFileName::PrependDir). + Func("RemoveDir", &wxFileName::RemoveDir). + Func("RemoveLastDir", &wxFileName::RemoveLastDir). + Func("SameAs", &wxFileName::SameAs). + Func("SetCwd",&wxFileName::SetCwd). + Func("SetExt", &wxFileName::SetExt). + Func("SetEmptyExt", &wxFileName::SetEmptyExt). + Func("SetFullName", &wxFileName::SetFullName). + Func("SetName", &wxFileName::SetName). + Func("SetVolume", &wxFileName::SetVolume). + Func("IsFileWritable",&wxFileName::IsFileWritable). + StaticFunc("GetPathSeparators", &wxFileName::GetPathSeparators). + SquirrelFunc("GetPathSeparator", &wxFileName_GetPathSeparator); + + Sqrat::RootTable(vm).Bind("wxFileName",wx_filename); + + ///////////// + // wxPoint // + ///////////// + Sqrat::Class wx_point(vm,"wxPoint"); + wx_point. + Ctor(). + Ctor(). + SquirrelFunc("_cmp", &wxPoint_OpCmp). + SquirrelFunc("Cmp", &wxPoint_Cmp). + SquirrelFunc("_tostring", &wxPoint_OpTostring). + Var("x", &wxPoint::x). + Var("y", &wxPoint::y); + Sqrat::RootTable(vm).Bind("wxPoint",wx_point); + + //////////// + // wxSize // + //////////// + typedef void(wxSize::*WXS_SET)(int, int); + typedef void(wxSize::*WXS_SETH)(int); + typedef void(wxSize::*WXS_SETW)(int); + Sqrat::Class wx_size(vm,"wxSize"); + wx_size. + Ctor(). + Ctor(). + SquirrelFunc("_tostring", &wxSize_OpTostring). + SquirrelFunc("Cmp", &wxSize_Cmp). + Func("GetWidth", &wxSize::GetWidth). + Func("GetHeight", &wxSize::GetHeight). + Func("Set",&wxSize::Set). + Func("SetHeight", &wxSize::SetHeight). + Func("SetWidth", &wxSize::SetWidth); + Sqrat::RootTable(vm).Bind("wxSize",wx_size); + + } +}; From 9a6ff673ade13c57e4e2f8dcc19b9510619f0db5 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 17:23:55 +0200 Subject: [PATCH 08/16] [NOT COMPILE] update scripting console to work with sqrat, add colors for console output (errors in red) --- src/src/scriptconsole.cpp | 72 ++++++++++++++++++++++++++--------- src/src/scriptconsole.h | 1 + src/wxsmith/ScriptConsole.wxs | 2 +- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/src/scriptconsole.cpp b/src/src/scriptconsole.cpp index 9557282167..a0776abfe4 100644 --- a/src/src/scriptconsole.cpp +++ b/src/src/scriptconsole.cpp @@ -8,7 +8,7 @@ */ #include -#include +#include #include "scriptconsole.h" @@ -43,19 +43,32 @@ const long ScriptConsole::ID_PANEL1 = wxNewId(); static ScriptConsole* s_Console = nullptr; static SQPRINTFUNCTION s_OldPrintFunc = nullptr; +static SQPRINTFUNCTION s_OldErrorFunc = nullptr; static void ScriptConsolePrintFunc(HSQUIRRELVM /*v*/, const SQChar * s, ...) +// FIXME (bluehazzard#1#): buffer overflow { - static SQChar temp[2048]; va_list vl; va_start(vl,s); - scvsprintf( temp,s,vl); - wxString msg = cbC2U(temp); + wxString msg; + PrintSquirrelToWxString(msg,s,vl); va_end(vl); if (s_Console) s_Console->Log(msg); - Manager::Get()->GetScriptingManager()->InjectScriptOutput(msg); + Manager::Get()->GetScriptingManager()->InjectScriptOutput(msg); // FIXME (bluehazzard#1#): This function call (and the function itself) makes no sense sorry... +} + +static void ScriptConsoleErrorFunc(HSQUIRRELVM /*v*/, const SQChar * s, ...) +{ + va_list vl; + va_start(vl,s); + wxString msg; + PrintSquirrelToWxString(msg,s,vl); + va_end(vl); + + if (s_Console) + s_Console->Error(msg); } BEGIN_EVENT_TABLE(ScriptConsole,wxPanel) @@ -71,7 +84,7 @@ ScriptConsole::ScriptConsole(wxWindow* parent,wxWindowID id) Create(parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("id")); BoxSizer1 = new wxBoxSizer(wxVERTICAL); - txtConsole = new wxTextCtrl(this, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL, wxDefaultValidator, _T("ID_TEXTCTRL1")); + txtConsole = new wxTextCtrl(this, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH|wxHSCROLL, wxDefaultValidator, _T("ID_TEXTCTRL1")); wxFont txtConsoleFont(10,wxFONTFAMILY_MODERN,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL,false,wxEmptyString,wxFONTENCODING_DEFAULT); txtConsole->SetFont(txtConsoleFont); BoxSizer1->Add(txtConsole, 1, wxALL|wxEXPAND, 0); @@ -112,12 +125,19 @@ ScriptConsole::ScriptConsole(wxWindow* parent,wxWindowID id) txtCommand->Append(wxEmptyString); if (!s_Console) { + s_Console = this; - s_OldPrintFunc = sq_getprintfunc(SquirrelVM::GetVMPtr()); - sq_setprintfunc(SquirrelVM::GetVMPtr(), ScriptConsolePrintFunc); + ScriptBindings::CBsquirrelVM *vm = Manager::Get()->GetScriptingManager()->GetVM(); + if(vm == nullptr) + { + // We have no vm registered... + Error(_("No default vm registered for the scripting console, please contact the developer")); + } else { + vm->GetPrintFunc(s_OldPrintFunc,s_OldErrorFunc); + vm->SetPrintFunc(ScriptConsolePrintFunc,ScriptConsoleErrorFunc); + } } - - Log(_("Welcome to the script console!")); + Log(_("Welcome to the script console!\n")); } ScriptConsole::~ScriptConsole() @@ -125,8 +145,11 @@ ScriptConsole::~ScriptConsole() if (s_Console == this) { s_Console = nullptr; - if (SquirrelVM::GetVMPtr()) - sq_setprintfunc(SquirrelVM::GetVMPtr(), s_OldPrintFunc); + + ScriptBindings::CBsquirrelVM *vm = ScriptBindings::CBsquirrelVMManager::Get()->GetVM(Sqrat::DefaultVM::Get()); + if(vm != NULL) + vm->SetPrintFunc(s_OldPrintFunc,s_OldErrorFunc); + } //(*Destroy(ScriptConsole) @@ -136,9 +159,22 @@ ScriptConsole::~ScriptConsole() void ScriptConsole::Log(const wxString& msg) { txtConsole->AppendText(msg); +// if (msg.Last() != _T('\n')) +// txtConsole->AppendText(_T('\n')); +// txtConsole->ScrollLines(-1); + Manager::ProcessPendingEvents(); +} + + +void ScriptConsole::Error(const wxString& msg) +{ + wxTextAttr old = txtConsole->GetDefaultStyle(); + txtConsole->SetDefaultStyle(wxTextAttr(wxColor(235,0,0))); + txtConsole->AppendText(msg); if (msg.Last() != _T('\n')) txtConsole->AppendText(_T('\n')); -// txtConsole->ScrollLines(-1); + + txtConsole->SetDefaultStyle(old); Manager::ProcessPendingEvents(); } @@ -154,14 +190,14 @@ void ScriptConsole::OnbtnExecuteClick(cb_unused wxCommandEvent& event) } Log(_T("> ") + cmd); - if (Manager::Get()->GetScriptingManager()->LoadBuffer(cmd, _T("ScriptConsole"))) + if (Manager::Get()->GetScriptingManager()->LoadBuffer(cmd, _("ScriptConsole"))) { if (txtCommand->FindString(cmd) == wxNOT_FOUND) txtCommand->Insert(cmd, 1); // right after the blank entry txtCommand->SetValue(wxEmptyString); } else - txtConsole->AppendText(Manager::Get()->GetScriptingManager()->GetErrorString()); + Error(Manager::Get()->GetScriptingManager()->GetErrorString()); txtCommand->SetFocus(); } @@ -179,11 +215,11 @@ void ScriptConsole::OnbtnLoadClick(cb_unused wxCommandEvent& event) { mgr->Write(_T("/file_dialogs/file_run_script/directory"), dlg.GetDirectory()); if (Manager::Get()->GetScriptingManager()->LoadScript(dlg.GetPath())) - Log(_("Script loaded successfully")); + Log(_("\n*** Script loaded successfully ***\n")); else { - Log(_("Loading script failed.")); - txtConsole->AppendText(Manager::Get()->GetScriptingManager()->GetErrorString()); + Error(_("\n*** Loading script failed. ***\n")); + Error(Manager::Get()->GetScriptingManager()->GetErrorString()); } } txtCommand->SetFocus(); diff --git a/src/src/scriptconsole.h b/src/src/scriptconsole.h index 464b1939dc..4e0250eb4d 100644 --- a/src/src/scriptconsole.h +++ b/src/src/scriptconsole.h @@ -29,6 +29,7 @@ class ScriptConsole: public wxPanel virtual ~ScriptConsole(); void Log(const wxString& msg); + void Error(const wxString& msg); //(*Identifiers(ScriptConsole) static const long ID_TEXTCTRL1; diff --git a/src/wxsmith/ScriptConsole.wxs b/src/wxsmith/ScriptConsole.wxs index d8c0d1a61b..53d0ba72bc 100644 --- a/src/wxsmith/ScriptConsole.wxs +++ b/src/wxsmith/ScriptConsole.wxs @@ -9,7 +9,7 @@ 10 modern - + wxALL|wxEXPAND From 7410010653beef628dfcb1677008bd4a80d23716 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 17:31:15 +0200 Subject: [PATCH 09/16] [NOT COMPILE] update all codeblocks main application bindings * Squirrel errors get reported in a seperate dialog and in the cb log output. Included is a stack trace and the local variables from the top function call --- src/src/app.cpp | 37 ++++++++++++++++++------------ src/src/main.cpp | 42 +++++++++++++++++------------------ src/src/projectoptionsdlg.cpp | 31 +++++++++++++------------- 3 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/src/app.cpp b/src/src/app.cpp index 33e44714af..908d5b6be3 100644 --- a/src/src/app.cpp +++ b/src/src/app.cpp @@ -38,7 +38,7 @@ #include #include #include -#include + #include "appglobals.h" #include "associations.h" @@ -47,6 +47,8 @@ #include "crashhandler.h" #include "projectmanagerui.h" #include "splashscreen.h" +#include + #ifndef __WXMSW__ #include "prefix.h" // binreloc @@ -730,7 +732,9 @@ bool CodeBlocksApp::OnInit() LoaderBase* loader = Manager::Get()->GetFileManager()->Load(m_Script); if (loader->GetData()) - Manager::Get()->GetScriptingManager()->LoadBuffer(cbC2U(loader->GetData())); + Manager::Get()->GetScriptingManager()->LoadBuffer(cbC2U(loader->GetData()),_("Command_line_script")); + + Manager::Get()->GetScriptingManager()->DisplayErrors(); delete loader; frame->Close(); @@ -740,15 +744,14 @@ bool CodeBlocksApp::OnInit() CheckVersion(); // run startup script - try - { - wxString startup = ConfigManager::LocateDataFile(_T("startup.script"), sdScriptsUser | sdScriptsGlobal); - if (!startup.IsEmpty()) - Manager::Get()->GetScriptingManager()->LoadScript(startup); - } - catch (SquirrelError& exception) + // FIXME (bluehazzard#1#): Right squirrel error handling + + wxString startup = ConfigManager::LocateDataFile(_T("startup.script"), sdScriptsUser | sdScriptsGlobal); + + if (!startup.IsEmpty()) { - Manager::Get()->GetScriptingManager()->DisplayErrors(&exception); + Manager::Get()->GetScriptingManager()->LoadScript(startup); + Manager::Get()->GetScriptingManager()->DisplayErrors(); } Manager::ProcessPendingEvents(); @@ -781,10 +784,11 @@ bool CodeBlocksApp::OnInit() { exception.ShowErrorMessage(); } - catch (SquirrelError& exception) + /*catch (SquirrelError& exception) +// FIXME (bluehazzard#1#): squirrel error { Manager::Get()->GetScriptingManager()->DisplayErrors(&exception); - } + }*/ catch (const char* message) { wxSafeShowMessage(_T("Exception"), cbC2U(message)); @@ -855,10 +859,11 @@ int CodeBlocksApp::OnRun() { exception.ShowErrorMessage(); } - catch (SquirrelError& exception) + /* catch (SquirrelError& exception) +// FIXME (bluehazzard#1#): squirrel error { Manager::Get()->GetScriptingManager()->DisplayErrors(&exception); - } + }*/ catch (const char* message) { wxSafeShowMessage(_("Exception"), cbC2U(message)); @@ -1182,6 +1187,10 @@ int CodeBlocksApp::ParseCmdLine(MainFrame* handlerFrame, const wxString& CmdLine m_Clean = parser.Found(_T("clean")); parser.Found(_T("target"), &m_BatchTarget); parser.Found(_T("script"), &m_Script); + + + + // initial setting for batch flag (will be reset when ParseCmdLine() is called again). m_Batch = m_Build || m_ReBuild || m_Clean; diff --git a/src/src/main.cpp b/src/src/main.cpp index 24f440da97..051f4ecef5 100644 --- a/src/src/main.cpp +++ b/src/src/main.cpp @@ -849,14 +849,17 @@ void MainFrame::SetupDebuggerUI() } } -DECLARE_INSTANCE_TYPE(MainFrame); void MainFrame::RegisterScriptFunctions() { - SqPlus::SQClassDef("MainFrame"). - func(&MainFrame::Open, "Open"); + ScriptBindings::CBsquirrelVM *vm = Manager::Get()->GetScriptingManager()->GetVM(); + Sqrat::Class > main_frame(vm->GetSqVM(), "MainFrame"); + main_frame.Func("Open",&MainFrame::Open); - SqPlus::BindVariable(this, "App", SqPlus::VAR_ACCESS_READ_ONLY); + Sqrat::RootTable(vm->GetSqVM()).Bind("MainFrame",main_frame); + Sqrat::RootTable(vm->GetSqVM()).SetInstance("App",this); + + //SqPlus::BindVariable(this,, SqPlus::VAR_ACCESS_READ_ONLY); } void MainFrame::RunStartupScripts() @@ -874,27 +877,22 @@ void MainFrame::RunStartupScripts() if (!se.enabled) continue; - try + wxString startup = se.script; + if (wxFileName(se.script).IsRelative()) + startup = ConfigManager::LocateDataFile(se.script, sdScriptsUser | sdScriptsGlobal); + if (!startup.IsEmpty()) { - wxString startup = se.script; - if (wxFileName(se.script).IsRelative()) - startup = ConfigManager::LocateDataFile(se.script, sdScriptsUser | sdScriptsGlobal); - if (!startup.IsEmpty()) - { - if (!se.registered) - Manager::Get()->GetScriptingManager()->LoadScript(startup); - else if (!se.menu.IsEmpty()) - Manager::Get()->GetScriptingManager()->RegisterScriptMenu(se.menu, startup, false); - else - Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script/function '%s' not loaded: invalid configuration"), se.script.wx_str())); - } + if (!se.registered) + Manager::Get()->GetScriptingManager()->LoadScript(startup); + else if (!se.menu.IsEmpty()) + Manager::Get()->GetScriptingManager()->RegisterScriptMenu(se.menu, startup, false); else - Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script '%s' not found"), se.script.wx_str())); - } - catch (SquirrelError& exception) - { - Manager::Get()->GetScriptingManager()->DisplayErrors(&exception); + Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script/function '%s' not loaded: invalid configuration"), se.script.wx_str())); } + else + Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script '%s' not found"), se.script.wx_str())); + + Manager::Get()->GetScriptingManager()->DisplayErrors(); } } } diff --git a/src/src/projectoptionsdlg.cpp b/src/src/projectoptionsdlg.cpp index 75a37a0b42..23995690d9 100644 --- a/src/src/projectoptionsdlg.cpp +++ b/src/src/projectoptionsdlg.cpp @@ -39,7 +39,8 @@ #include -#include "scripting/sqplus/sqplus.h" + +#include #include "annoyingdialog.h" #include "configurationpanel.h" @@ -940,25 +941,23 @@ void ProjectOptionsDlg::OnScriptsOverviewSelChanged(cb_unused wxTreeEvent& event bool ProjectOptionsDlg::IsScriptValid(ProjectBuildTarget* target, const wxString& script) { static const wxString clearout_buildscripts = _T("SetBuildOptions <- null;"); - try - { - wxString script_nomacro = script; - Manager::Get()->GetMacrosManager()->ReplaceMacros(script_nomacro, target); - script_nomacro = wxFileName(script_nomacro).IsAbsolute() ? script_nomacro : m_Project->GetBasePath() + wxFILE_SEP_PATH + script_nomacro; - Manager::Get()->GetScriptingManager()->LoadBuffer(clearout_buildscripts); // clear previous script's context - Manager::Get()->GetScriptingManager()->LoadScript(script_nomacro); - SqPlus::SquirrelFunction setopts("SetBuildOptions"); - - if (setopts.func.IsNull()) - return false; - return true; - } - catch (SquirrelError& e) + wxString script_nomacro = script; + Manager::Get()->GetMacrosManager()->ReplaceMacros(script_nomacro, target); + script_nomacro = wxFileName(script_nomacro).IsAbsolute() ? script_nomacro : m_Project->GetBasePath() + wxFILE_SEP_PATH + script_nomacro; + Manager::Get()->GetScriptingManager()->LoadBuffer(clearout_buildscripts,_T("ClearBuildScripts")); // clear previous script's context + Manager::Get()->GetScriptingManager()->LoadScript(script_nomacro); + Sqrat::Function setopts(Sqrat::RootTable(Sqrat::DefaultVM::Get()), "SetBuildOptions"); + if (setopts.IsNull()) + return false; + + wxString Errors = Manager::Get()->GetScriptingManager()->GetErrorString(true); + if(Errors!= wxEmptyString) { - Manager::Get()->GetScriptingManager()->DisplayErrors(&e); + Manager::Get()->GetScriptingManager()->DisplayErrors(Errors); return false; } + return true; } bool ProjectOptionsDlg::ValidateTargetName(const wxString& name) From c163f857d1ec9fc86f5bfd5b69f6086201a9ab71 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 17:32:19 +0200 Subject: [PATCH 10/16] [NOT COMPILE] change sdk related binding (3/3) API change: ReplaceMacros has now a parameter to describe the name in what context it is called. This is used for error reporting for the scripting engine. Parameter has default value so no code rework is needed --- src/include/macrosmanager.h | 2 +- src/include/scriptingmanager.h | 110 ++++++++++-- src/plugins/codecompletion/nativeparser.cpp | 13 +- src/sdk/compilercommandgenerator.cpp | 23 ++- src/sdk/macrosmanager.cpp | 11 +- src/sdk/scriptingmanager.cpp | 188 ++++++++++++-------- 6 files changed, 245 insertions(+), 102 deletions(-) diff --git a/src/include/macrosmanager.h b/src/include/macrosmanager.h index 89629f54eb..ea6c17a558 100644 --- a/src/include/macrosmanager.h +++ b/src/include/macrosmanager.h @@ -27,7 +27,7 @@ class DLLIMPORT MacrosManager : public Mgr friend class Mgr; void CreateMenu(wxMenuBar* menuBar); void ReleaseMenu(wxMenuBar* menuBar); - void ReplaceMacros(wxString& buffer, ProjectBuildTarget* target = nullptr, bool subrequest = false); + void ReplaceMacros(wxString& buffer, ProjectBuildTarget* target = nullptr, bool subrequest = false,wxString name = wxEmptyString); wxString ReplaceMacros(const wxString& buffer, ProjectBuildTarget* target = nullptr); void ReplaceEnvVars(wxString& buffer) { ReplaceMacros(buffer); } /* misnomer, should be ReplaceVariables */; void RecalcVars(cbProject* project, EditorBase* editor, ProjectBuildTarget* target); diff --git a/src/include/scriptingmanager.h b/src/include/scriptingmanager.h index a3cfc54619..ad5c4f4445 100644 --- a/src/include/scriptingmanager.h +++ b/src/include/scriptingmanager.h @@ -12,14 +12,30 @@ #ifndef CB_PRECOMP #include "cbexception.h" // cbThrow #include "globals.h" // cbC2U + #include #endif #include "settings.h" #include "manager.h" #include "menuitemsmanager.h" #include +#include +#include +#include +#include "scripting/squirrel/sqrdbg.h" +#include "scripting/squirrel/sqdbgserver.h" -struct SquirrelError; +#define SCRIPT_BINDING_VERSION_MAJOR 2 +#define SCRIPT_BINDING_VERSION_MINOR 0 +#define SCRIPT_BINDING_VERSION_RELEASE 0 + +namespace ScriptBindings +{ + class cbScriptPlugin; +} + + +void PrintSquirrelToWxString(wxString &msg,const SQChar *s, va_list& vl); /** @brief Provides scripting in Code::Blocks. * @@ -31,6 +47,7 @@ struct SquirrelError; * Manager::Get()->GetScriptingManager()->LoadScript(_T("some.script")); * @endcode * + * The following is outdated ;) soon: * And here's an example to call a script function: * * @code @@ -47,6 +64,9 @@ struct SquirrelError; * The templated type denotes the function's return type. Also note that the * function name is not unicode (we 're not using Squirrel in unicode mode). */ + +using namespace ScriptBindings; + class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHandler { friend class Mgr; @@ -74,39 +94,54 @@ class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHan * * @param buffer The script buffer to compile and run. * @param debugName A debug name. This will appear in any errors displayed. + * @param real_path If the debug name is not a path to a real file this has to be set on false. (This is needed to create a temporary file to allow the debugger to open also memory files) * @return True if the script compiled, false if not. */ - bool LoadBuffer(const wxString& buffer, const wxString& debugName = _T("CommandLine")); + bool LoadBuffer(const wxString& buffer,wxString debugName/* = _T("CommandLine")*/,bool real_path = false); /** @brief Loads a string buffer and captures its output. * * @param buffer The script buffer to compile and run. * @return The script's output (if any). */ - wxString LoadBufferRedirectOutput(const wxString& buffer); + wxString LoadBufferRedirectOutput(const wxString& buffer,const wxString& name); + // TODO (bluehazzard#1#): Delete this if the Sqrat API doesn't change /** @brief Returns an accumulated error string. * - * Returns an error string for the passed exception (if any) plus + * Returns an error string for the passed vm (if any) plus * any accumulated script engine errors (e.g. from failed function calls). - * @param exception A pointer to the exception object containing the error. Can be NULL (default). + * @param The vm from which the error should come * @param clearErrors If true (default), when this function returns all * accumulated error messages are cleared. * @return The error string. If empty, it means "no errors". */ - wxString GetErrorString(SquirrelError* exception = nullptr, bool clearErrors = true); + //wxString GetErrorString(Sqrat::Exception* exception = nullptr, bool clearErrors = true); + wxString GetErrorString(bool clearErrors = true); + + /** @brief Display error dialog. + * + * Displays an error dialog containing exception info and any other + * script errors. If error_msg isempty the GetErrorString String is called + * internally and if no error is found no error is displayed and the function returns _false_ + * @param error_msg The error message displayed with the error dialog + * @param clearErrors If true (default), when this function returns all + * accumulated error messages are cleared. + * @return _true_ if a error occurred, _false_ otherwise + */ + bool DisplayErrors(wxString error_msg = wxEmptyString, bool clearErrors = true); /** @brief Display error dialog. * * Displays an error dialog containing exception info and any other - * script errors. Calls GetErrorString() internally. - * You should normally call this function inside your catch handler for - * SquirrelFunction<>() calls. - * @param exception A pointer to the exception object containing the error. Can be NULL (default). + * script errors. If error_msg isempty the GetErrorString String is called + * internally and if no error is found no error is displayed and the function returns _false_ + * @param pre_error Text printed previous the error * @param clearErrors If true (default), when this function returns all * accumulated error messages are cleared. + * @return _true_ if a error occurred, _false_ otherwise */ - void DisplayErrors(SquirrelError* exception = nullptr, bool clearErrors = true); + bool DisplayErrorsAndText(wxString pre_error, bool clearErrors = true); /** @brief Injects script output. * @@ -124,7 +159,7 @@ class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHan */ int Configure(); - /** @brief Registers a script plugin menu IDs with the callback function. + /** @brief Registers a script plugin * * @param name The script plugin's name. * @param ids The menu IDs to bind. @@ -132,6 +167,14 @@ class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHan */ bool RegisterScriptPlugin(const wxString& name, const wxArrayInt& ids); + /** @brief Unregisters a script plugin + * + * @param name The script plugin's name. + * @param ids The menu IDs to bind. + * @return True on success, false on failure. + */ + bool UnRegisterScriptPlugin(const wxString& name); + /** @brief Script-bound function to register a script with a menu item. * * @param menuPath The full menu path. This can be separated by slashes (/) @@ -221,6 +264,42 @@ class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHan cbThrow(_T("Can't assign a ScriptingManager* !!!")); return *this; } + + ScriptBindings::CBSquirrelThread * CreateSandbox(); + + ScriptBindings::CBsquirrelVM* GetVM() {return m_vm;}; + + + /** \brief Search the plugin _Name_ and run its _Execute_ function + * + * \param Name wxString + * \return int 1 On success + * -1 On script error. The error was reported by the script + * -2 "Execute" could not be found in the script + * -3 The script _Name_ could not be found + * + */ + int ExecutePlugin(wxString Name); + + /** \brief Search and return the Plugin with the _Name_ + * + * \param Name wxString + * \return cbScriptPlugin* nullptr it not found + * + */ + cbScriptPlugin* GetPlugin(wxString Name); + + /** \brief Ask all script plugins to create the "right click" menu + * + * \param type const ModuleType + * \param menu wxMenu* + * \param data const FileTreeData* + * \return void + * + */ + void CreateModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data); + + private: // needed for SqPlus bindings ScriptingManager(cb_unused const ScriptingManager& rhs); // prevent copy construction @@ -228,6 +307,9 @@ class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHan void OnScriptMenu(wxCommandEvent& event); void OnScriptPluginMenu(wxCommandEvent& event); void RegisterScriptFunctions(); + void OnDebugTimer(wxTimerEvent& event); + + wxTimer m_DebugerUpdateTimer; ScriptingManager(); ~ScriptingManager(); @@ -241,9 +323,11 @@ class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHan wxString scriptOrFunc; bool isFunc; }; + typedef std::map MenuIDToScript; MenuIDToScript m_MenuIDToScript; + bool m_AttachedToMainWindow; wxString m_CurrentlyRunningScriptFile; @@ -252,6 +336,8 @@ class DLLIMPORT ScriptingManager : public Mgr, public wxEvtHan MenuItemsManager m_MenuItemsManager; + ScriptBindings::CBsquirrelVM* m_vm; + DECLARE_EVENT_TABLE() }; diff --git a/src/plugins/codecompletion/nativeparser.cpp b/src/plugins/codecompletion/nativeparser.cpp index 90a8937c1b..caa873644c 100644 --- a/src/plugins/codecompletion/nativeparser.cpp +++ b/src/plugins/codecompletion/nativeparser.cpp @@ -35,6 +35,7 @@ #endif #include +#include #include #include @@ -2228,10 +2229,12 @@ bool NativeParser::AddProjectDefinedMacros(cbProject* project, ParserBase* parse wxString defs; wxArrayString opts; + wxArrayString names; if ( !parser->Options().platformCheck || (parser->Options().platformCheck && project->SupportsCurrentPlatform()) ) { opts = project->GetCompilerOptions(); + names.Add(project->GetTitle() + _T(" compiler options"),opts.Count()); } ProjectBuildTarget* target = project->GetBuildTarget(project->GetActiveBuildTarget()); @@ -2242,7 +2245,11 @@ bool NativeParser::AddProjectDefinedMacros(cbProject* project, ParserBase* parse { wxArrayString targetOpts = target->GetCompilerOptions(); for (size_t i = 0; i < targetOpts.GetCount(); ++i) + { opts.Add(targetOpts[i]); + names.Add(target->GetTitle()); + } + } } // In case of virtual targets, collect the defines from all child targets. @@ -2257,7 +2264,11 @@ bool NativeParser::AddProjectDefinedMacros(cbProject* project, ParserBase* parse { wxArrayString targetOpts = target->GetCompilerOptions(); for (size_t j = 0; j < targetOpts.GetCount(); ++j) + { opts.Add(targetOpts[j]); + names.Add(target->GetTitle()); + } + } } } @@ -2265,7 +2276,7 @@ bool NativeParser::AddProjectDefinedMacros(cbProject* project, ParserBase* parse for (size_t i = 0; i < opts.GetCount(); ++i) { wxString def = opts[i]; - Manager::Get()->GetMacrosManager()->ReplaceMacros(def); + Manager::Get()->GetMacrosManager()->ReplaceMacros(def,nullptr,false,names[i]); if ( !def.StartsWith(defineCompilerSwitch) ) continue; diff --git a/src/sdk/compilercommandgenerator.cpp b/src/sdk/compilercommandgenerator.cpp index ab75abc3b5..9c56a92c50 100644 --- a/src/sdk/compilercommandgenerator.cpp +++ b/src/sdk/compilercommandgenerator.cpp @@ -25,7 +25,7 @@ #include "filefilters.h" #include "scripting/bindings/sc_base_types.h" -#include "scripting/sqplus/sqplus.h" +#include "scripting/bindings/sc_cb_vm.h" // move this to globals if needed inline wxString UnquoteStringIfNeeded(const wxString& str) @@ -530,7 +530,7 @@ void CompilerCommandGenerator::DoBuildScripts(cbProject* project, CompileTargetB } // clear previous script's context - Manager::Get()->GetScriptingManager()->LoadBuffer(clearout_buildscripts); + Manager::Get()->GetScriptingManager()->LoadBuffer(clearout_buildscripts,_T("ClearBuildScript")); // if the script doesn't exist, just return if (!Manager::Get()->GetScriptingManager()->LoadScript(script_nomacro)) @@ -538,15 +538,22 @@ void CompilerCommandGenerator::DoBuildScripts(cbProject* project, CompileTargetB m_NotLoadedScripts.Add(script_nomacro); continue; } - - try + ScriptBindings::CBsquirrelVM *vm = Manager::Get()->GetScriptingManager()->GetVM(); + Sqrat::Function func(Sqrat::RootTable(vm->GetSqVM()),funcName.ToUTF8()); + if(func.IsNull()) { - SqPlus::SquirrelFunction f(cbU2C(funcName)); - f(target); + //Could not find the function + wxString msg; + msg << _("Function ") << funcName << _("could not be found in:\n ") << script_nomacro; + Manager::Get()->GetScriptingManager()->DisplayErrors(msg); + m_ScriptsWithErrors.Add(script_nomacro); } - catch (SquirrelError& e) + func(target); + if(vm->HasError()) { - Manager::Get()->GetScriptingManager()->DisplayErrors(&e); + wxString msg; + msg << _("In Script ") << script_nomacro << _(" occurred this error:\n ") << vm->getLastErrorMsg(); + Manager::Get()->GetScriptingManager()->DisplayErrors(msg); m_ScriptsWithErrors.Add(script_nomacro); } } diff --git a/src/sdk/macrosmanager.cpp b/src/sdk/macrosmanager.cpp index 64afcdadb9..873cf098d6 100644 --- a/src/sdk/macrosmanager.cpp +++ b/src/sdk/macrosmanager.cpp @@ -31,8 +31,6 @@ #include // wxStandardPaths #include -#include "scripting/sqplus/sqplus.h" -#include "scripting/bindings/scriptbindings.h" #include "cbstyledtextctrl.h" @@ -429,7 +427,7 @@ void MacrosManager::RecalcVars(cbProject* project, EditorBase* editor, ProjectBu m_Macros[_T("DAYCOUNT")] = wxString::Format(_T("%d"), ts.GetDays()); } -void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, bool subrequest) +void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, bool subrequest,wxString name) { if (buffer.IsEmpty()) return; @@ -474,7 +472,12 @@ void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, while (m_RE_Script.Matches(buffer)) { search = m_RE_Script.GetMatch(buffer, 1); - replace = Manager::Get()->GetScriptingManager()->LoadBufferRedirectOutput(m_RE_Script.GetMatch(buffer, 2)); + wxString sc_name(_T("Replace Macro Target: ")); + if(target != nullptr) + sc_name.Append(target->GetTitle()); + else + sc_name.Append(name); + replace = Manager::Get()->GetScriptingManager()->LoadBufferRedirectOutput(m_RE_Script.GetMatch(buffer, 2),sc_name); buffer.Replace(search, replace, false); } diff --git a/src/sdk/scriptingmanager.cpp b/src/sdk/scriptingmanager.cpp index d081a79a46..8eb5bf4eeb 100644 --- a/src/sdk/scriptingmanager.cpp +++ b/src/sdk/scriptingmanager.cpp @@ -24,15 +24,21 @@ #include #include #include + #include + #include + #endif #include "crc32.h" #include "menuitemsmanager.h" #include "genericmultilinenotesdlg.h" -#include "sqplus.h" -#include "scriptbindings.h" -#include "sc_plugin.h" -#include "sqstdstring.h" +#include "scripting/sqrat.h" +#include "scripting/bindings/scriptbindings.h" +#include "scripting/bindings/sc_plugin.h" +#include "scripting/squirrel/sqstdstring.h" + +#include + template<> ScriptingManager* Mgr::instance = nullptr; template<> bool Mgr::isShutdown = false; @@ -44,7 +50,7 @@ void PrintSquirrelToWxString(wxString& msg, const SQChar* s, va_list& vl) { int buffer_size = 2048; SQChar* tmp_buffer; - for (;;buffer_size*=2) + for(;;buffer_size*=2) { tmp_buffer = new SQChar [buffer_size]; int retvalue = vsnprintf(tmp_buffer, buffer_size, s, vl); @@ -60,6 +66,18 @@ void PrintSquirrelToWxString(wxString& msg, const SQChar* s, va_list& vl) } } +static void CaptureScriptErrors(HSQUIRRELVM /*v*/, const SQChar * s, ...) +{ + va_list vl; + va_start(vl,s); + wxString msg; + PrintSquirrelToWxString(msg,s,vl); + va_end(vl); + + s_ScriptErrors << msg; + Manager::Get()->GetLogManager()->LogError(_("Script error: ") + msg); +} + static void ScriptsPrintFunc(HSQUIRRELVM /*v*/, const SQChar * s, ...) { va_list vl; @@ -92,18 +110,17 @@ ScriptingManager::ScriptingManager() //ctor // initialize but don't load the IO lib - SquirrelVM::Init((SquirrelInitFlags)(sqifAll & ~sqifIO)); + m_vm = new ScriptBindings::CBsquirrelVM(1024,(ScriptBindings::VM_LIB_ALL & ~ScriptBindings::VM_LIB_IO)); - if (!SquirrelVM::GetVMPtr()) + if (!m_vm->GetSqVM()) cbThrow(_T("Can't create scripting engine!")); - sq_setprintfunc(SquirrelVM::GetVMPtr(), ScriptsPrintFunc); - sqstd_register_stringlib(SquirrelVM::GetVMPtr()); - + m_vm->SetPrintFunc(ScriptsPrintFunc,CaptureScriptErrors); + m_vm->SetMeDefault(); RefreshTrusts(); // register types - ScriptBindings::RegisterBindings(); + ScriptBindings::RegisterBindings(m_vm->GetSqVM()); } ScriptingManager::~ScriptingManager() @@ -123,7 +140,10 @@ ScriptingManager::~ScriptingManager() } Manager::Get()->GetConfigManager(_T("security"))->Write(_T("/trusted_scripts"), myMap); - SquirrelVM::Shutdown(); + //Delete all Sqrat::Object elements, before the vm shuts down + ScriptBindings::ScriptPluginWrapper::ClearPlugins(); + + m_vm->Shutdown(); } void ScriptingManager::RegisterScriptFunctions() @@ -150,7 +170,6 @@ bool ScriptingManager::LoadScript(const wxString& filename) f.Open(fname); found = f.IsOpened(); } - if (!found) { // check in standard script dirs @@ -164,20 +183,20 @@ bool ScriptingManager::LoadScript(const wxString& filename) } } // read file - wxString contents = cbReadFileContents(f); + wxString contents= cbReadFileContents(f,wxFONTENCODING_UTF8); // Script files are UTF8 encoded, on windows are problems with the automatic detection of the encoding m_CurrentlyRunningScriptFile = fname; - bool ret = LoadBuffer(contents, fname); - m_CurrentlyRunningScriptFile.Clear(); + bool ret = LoadBuffer(contents, fname,true); + //m_CurrentlyRunningScriptFile.Clear(); // I'm not 100% sure if this is the correct approach to search for local scripts (and if we want to allow local scripts) return ret; } -bool ScriptingManager::LoadBuffer(const wxString& buffer, const wxString& debugName) +bool ScriptingManager::LoadBuffer(const wxString& buffer,wxString debugName,bool real_path) { // includes guard to avoid recursion wxString incName = UnixFilename(debugName); if (m_IncludeSet.find(incName) != m_IncludeSet.end()) { - Manager::Get()->GetLogManager()->LogWarning(F(_T("Ignoring Include(\"%s\") because it would cause recursion..."), incName.wx_str())); + Manager::Get()->GetLogManager()->LogWarning(F(_("Ignoring Include(\"%s\") because it would cause recursion..."), incName.wx_str())); return true; } m_IncludeSet.insert(incName); @@ -187,77 +206,92 @@ bool ScriptingManager::LoadBuffer(const wxString& buffer, const wxString& debugN s_ScriptErrors.Clear(); // compile script - SquirrelObject script; - try - { - script = SquirrelVM::CompileBuffer(cbU2C(buffer), cbU2C(debugName)); - } - catch (SquirrelError e) - { - cbMessageBox(wxString::Format(_T("Filename: %s\nError: %s\nDetails: %s"), debugName.c_str(), cbC2U(e.desc).c_str(), s_ScriptErrors.c_str()), _("Script compile error"), wxICON_ERROR); - m_IncludeSet.erase(incName); - return false; - } + // Make sure that the directory has a valid name (don't mix slash and backslash) + wxFileName tmp_name(debugName); + debugName = tmp_name.GetFullPath(); - // run script - try - { - SquirrelVM::RunScript(script); - } - catch (SquirrelError e) + SC_ERROR_STATE ret = m_vm->doString(buffer,debugName); + if(ret != SC_NO_ERROR) { - cbMessageBox(wxString::Format(_T("Filename: %s\nError: %s\nDetails: %s"), debugName.c_str(), cbC2U(e.desc).c_str(), s_ScriptErrors.c_str()), _("Script run error"), wxICON_ERROR); + DisplayErrors(); m_IncludeSet.erase(incName); return false; } + m_IncludeSet.erase(incName); return true; } -wxString ScriptingManager::LoadBufferRedirectOutput(const wxString& buffer) +wxString ScriptingManager::LoadBufferRedirectOutput(const wxString& buffer,const wxString& name) { // wxCriticalSectionLocker c(cs); s_ScriptErrors.Clear(); ::capture.Clear(); - sq_setprintfunc(SquirrelVM::GetVMPtr(), CaptureScriptOutput); - bool res = LoadBuffer(buffer); - sq_setprintfunc(SquirrelVM::GetVMPtr(), ScriptsPrintFunc); + // FIXME (bluehazzard#1#): Here is a absolute mess with the error handling... + + SQPRINTFUNCTION old_printFunc = nullptr; + SQPRINTFUNCTION old_errorFunc = nullptr; + + m_vm->GetPrintFunc(old_printFunc,old_errorFunc); + + // Redirect the script output to the ::capture string + m_vm->SetPrintFunc(CaptureScriptOutput,CaptureScriptErrors); + + bool res = LoadBuffer(buffer,name); + + // restore the old output + m_vm->SetPrintFunc(old_printFunc,old_errorFunc); return res ? ::capture : (wxString) wxEmptyString; } -wxString ScriptingManager::GetErrorString(SquirrelError* exception, bool clearErrors) +wxString ScriptingManager::GetErrorString( bool clearErrors) { - wxString msg; - if (exception) - msg << cbC2U(exception->desc); - msg << s_ScriptErrors; + //ScriptBindings::StackHandler sa(m_vm->GetVM()); + return m_vm->getLastErrorMsg(); + //return sa.GetError(clearErrors); +} - if (clearErrors) - s_ScriptErrors.Clear(); +bool ScriptingManager::DisplayErrorsAndText(wxString pre_error, bool clearErrors) +{ + if(!m_vm->HasError()) // If no error return + return false; - return msg; + pre_error.Append(GetErrorString(clearErrors)); + return DisplayErrors(pre_error,clearErrors); } -void ScriptingManager::DisplayErrors(SquirrelError* exception, bool clearErrors) +bool ScriptingManager::DisplayErrors(wxString error_msg, bool clearErrors) { - wxString msg = GetErrorString(exception, clearErrors); - if (!msg.IsEmpty()) + + if(error_msg == wxEmptyString) + { + if(!m_vm->HasError()) // If no error return + return false; + + error_msg = GetErrorString(clearErrors); + } + + + if (!error_msg.IsEmpty()) { - if (cbMessageBox(_("Script errors have occured...\nPress 'Yes' to see the exact errors."), + if (cbMessageBox(_("Script errors have occurred...\nPress 'Yes' to see the exact errors."), _("Script errors"), wxICON_ERROR | wxYES_NO | wxNO_DEFAULT) == wxID_YES) { GenericMultiLineNotesDlg dlg(Manager::Get()->GetAppWindow(), _("Script errors"), - msg, + error_msg, true); dlg.ShowModal(); } + Manager::Get()->GetLogManager()->DebugLog(_("Scripting error: ") + error_msg); + return true; } + return false; } void ScriptingManager::InjectScriptOutput(const wxString& output) @@ -270,7 +304,7 @@ int ScriptingManager::Configure() return -1; } -bool ScriptingManager::RegisterScriptPlugin(const wxString& /*name*/, const wxArrayInt& ids) +bool ScriptingManager::RegisterScriptPlugin(const wxString& name, const wxArrayInt& ids) { // attach this event handler in the main window (one-time run) if (!m_AttachedToMainWindow) @@ -288,6 +322,13 @@ bool ScriptingManager::RegisterScriptPlugin(const wxString& /*name*/, const wxAr return true; } +void ScriptingManager::OnScriptPluginMenu(wxCommandEvent& event) +{ + ScriptBindings::ScriptPluginWrapper::OnScriptMenu(event.GetId()); + DisplayErrors(); +} + + bool ScriptingManager::RegisterScriptMenu(const wxString& menuPath, const wxString& scriptOrFunc, bool isFunction) { // attach this event handler in the main window (one-time run) @@ -326,10 +367,11 @@ bool ScriptingManager::RegisterScriptMenu(const wxString& menuPath, const wxStri return false; } + bool ScriptingManager::UnRegisterScriptMenu(cb_unused const wxString& menuPath) { // TODO: not implemented - Manager::Get()->GetLogManager()->DebugLog(_T("ScriptingManager::UnRegisterScriptMenu() not implemented")); + Manager::Get()->GetLogManager()->DebugLog(_("ScriptingManager::UnRegisterScriptMenu() not implemented")); return false; } @@ -355,6 +397,7 @@ bool ScriptingManager::IsScriptTrusted(const wxString& script) return false; } + bool ScriptingManager::IsCurrentlyRunningScriptTrusted() { return IsScriptTrusted(m_CurrentlyRunningScriptFile); @@ -421,12 +464,13 @@ const ScriptingManager::TrustedScripts& ScriptingManager::GetTrustedScripts() return m_TrustedScripts; } + void ScriptingManager::OnScriptMenu(wxCommandEvent& event) { MenuIDToScript::iterator it = m_MenuIDToScript.find(event.GetId()); if (it == m_MenuIDToScript.end()) { - cbMessageBox(_("No script associated with this menu?!?"), _("Error"), wxICON_ERROR); + cbMessageBox(_T("No script associated with this menu?!?"), _T("Error"), wxICON_ERROR); return; } @@ -435,40 +479,32 @@ void ScriptingManager::OnScriptMenu(wxCommandEvent& event) // is it a function? if (mbs.isFunc) { - try - { - SqPlus::SquirrelFunction f(cbU2C(mbs.scriptOrFunc)); - f(); - } - catch (SquirrelError exception) + + Sqrat::Function f(m_vm->GetRootTable(),cbU2C(mbs.scriptOrFunc)); + if(f.IsNull()) { - DisplayErrors(&exception); + cbMessageBox(_T("Error on finding:") + mbs.scriptOrFunc, _T("Error"), wxICON_ERROR); + return; } + f(); + DisplayErrors(); return; } // script loading below - + wxString script = ConfigManager::LocateDataFile(mbs.scriptOrFunc, sdScriptsUser | sdScriptsGlobal); if (wxGetKeyState(WXK_SHIFT)) { - wxString script = ConfigManager::LocateDataFile(mbs.scriptOrFunc, sdScriptsUser | sdScriptsGlobal); Manager::Get()->GetEditorManager()->Open(script); return; } // run script - try - { - if (!LoadScript(mbs.scriptOrFunc)) - cbMessageBox(_("Could not run script: ") + mbs.scriptOrFunc, _("Error"), wxICON_ERROR); - } - catch (SquirrelError exception) + + if (m_vm->doFile(script) != SC_NO_ERROR) { - DisplayErrors(&exception); + cbMessageBox(_("Could not run script: ") + script, _("Error"), wxICON_ERROR); } -} -void ScriptingManager::OnScriptPluginMenu(wxCommandEvent& event) -{ - ScriptBindings::ScriptPluginWrapper::OnScriptMenu(event.GetId()); + DisplayErrors(); } From 77c1e3e52a74324117e36a52eb3bb70936133db5 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 24 May 2016 18:59:28 +0200 Subject: [PATCH 11/16] Update Project files --- src/CodeBlocks-unix.cbp | 206 ++++++++++++++++++++-------------- src/CodeBlocks.cbp | 209 +++++++++++++++++++++-------------- src/CodeBlocks_wx30-unix.cbp | 203 +++++++++++++++++++--------------- src/CodeBlocks_wx30.cbp | 196 ++++++++++++++++++-------------- src/CodeBlocks_wx30_64.cbp | 198 +++++++++++++++++++-------------- 5 files changed, 591 insertions(+), 421 deletions(-) diff --git a/src/CodeBlocks-unix.cbp b/src/CodeBlocks-unix.cbp index 9d4e6c4dae..fb5086861c 100644 --- a/src/CodeBlocks-unix.cbp +++ b/src/CodeBlocks-unix.cbp @@ -50,7 +50,6 @@