Updated project structure:
CMake changes: - Replace text files containing paths to installation, with install commands - You can set paths as cache variable - Added new option INSTALL_AFTER_BUILD Code changes: - Revert the changes to allow usage for older versions of g2o (like 0.1.9) This change is only temporary, to publish the release module fo the older g2o versions.
This commit is contained in:
43
dependencies/sqrat/include/sqmodule.h
vendored
43
dependencies/sqrat/include/sqmodule.h
vendored
@@ -189,49 +189,6 @@ extern "C" {
|
||||
/*debug*/
|
||||
SQRESULT (*stackinfos)(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);
|
||||
void (*setdebughook)(HSQUIRRELVM v);
|
||||
|
||||
/*missing vm*/
|
||||
void (*setsharedforeignptr)(HSQUIRRELVM v, SQUserPointer p);
|
||||
SQUserPointer (*getsharedforeignptr)(HSQUIRRELVM v);
|
||||
void (*setvmreleasehook)(HSQUIRRELVM v, SQRELEASEHOOK hook);
|
||||
SQRELEASEHOOK (*getvmreleasehook)(HSQUIRRELVM v);
|
||||
void (*setsharedreleasehook)(HSQUIRRELVM v, SQRELEASEHOOK hook);
|
||||
SQRELEASEHOOK (*getsharedreleasehook)(HSQUIRRELVM v);
|
||||
SQPRINTFUNCTION (*geterrorfunc)(HSQUIRRELVM v);
|
||||
SQInteger (*getversion)();
|
||||
|
||||
/*missing object creation handling*/
|
||||
void (*newtableex)(HSQUIRRELVM v, SQInteger initialcapacity);
|
||||
SQRESULT (*setclosureroot)(HSQUIRRELVM v, SQInteger idx);
|
||||
SQRESULT (*getclosureroot)(HSQUIRRELVM v, SQInteger idx);
|
||||
void (*pushthread)(HSQUIRRELVM v, HSQUIRRELVM thread);
|
||||
SQRESULT (*type_of)(HSQUIRRELVM v, SQInteger idx);
|
||||
SQHash (*gethash)(HSQUIRRELVM v, SQInteger idx);
|
||||
SQRELEASEHOOK (*getreleasehook)(HSQUIRRELVM v, SQInteger idx);
|
||||
SQRESULT (*getfunctioninfo)(HSQUIRRELVM v, SQInteger level, SQFunctionInfo* fi);
|
||||
SQRESULT (*getclosurename)(HSQUIRRELVM v, SQInteger idx);
|
||||
SQRESULT (*getmemberhandle)(HSQUIRRELVM v, SQInteger idx, HSQMEMBERHANDLE* handle);
|
||||
SQRESULT (*getbyhandle)(HSQUIRRELVM v, SQInteger idx, const HSQMEMBERHANDLE* handle);
|
||||
SQRESULT (*setbyhandle)(HSQUIRRELVM v, SQInteger idx, const HSQMEMBERHANDLE* handle);
|
||||
|
||||
/*missing object manipulation*/
|
||||
SQRESULT (*newmember)(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
|
||||
SQRESULT (*rawnewmember)(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
|
||||
|
||||
/*missing calls*/
|
||||
SQRESULT (*getcallee)(HSQUIRRELVM v);
|
||||
SQRESULT (*throwobject)(HSQUIRRELVM v);
|
||||
|
||||
/*missing raw object handling*/
|
||||
SQUnsignedInteger (*getrefcount)(HSQUIRRELVM v, HSQOBJECT* po);
|
||||
SQUserPointer (*objtouserpointer)(const HSQOBJECT* o);
|
||||
SQUnsignedInteger (*getvmrefcount)(HSQUIRRELVM v, const HSQOBJECT* po);
|
||||
|
||||
/*missing GC*/
|
||||
SQRESULT (*resurrectunreachable)(HSQUIRRELVM v);
|
||||
|
||||
/*missing debug*/
|
||||
void (*setnativedebughook)(HSQUIRRELVM v, SQDEBUGHOOK hook);
|
||||
} sq_api;
|
||||
typedef sq_api* HSQAPI;
|
||||
/// @endcond
|
||||
|
||||
@@ -151,7 +151,7 @@ private:
|
||||
/// \param size Number of bytes to read
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline SQInteger BytecodeReader(SQUserPointer user_data, SQUserPointer data, SQInteger size) {
|
||||
SQInteger BytecodeReader(SQUserPointer user_data, SQUserPointer data, SQInteger size) {
|
||||
Bytecode * bytecode = reinterpret_cast<Bytecode *>(user_data);
|
||||
return bytecode->ReadData(data, static_cast<size_t>(size));;
|
||||
}
|
||||
@@ -164,7 +164,7 @@ inline SQInteger BytecodeReader(SQUserPointer user_data, SQUserPointer data, SQI
|
||||
/// \param size Number of bytes to write
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline SQInteger BytecodeWriter(SQUserPointer user_data, SQUserPointer data, SQInteger size) {
|
||||
SQInteger BytecodeWriter(SQUserPointer user_data, SQUserPointer data, SQInteger size) {
|
||||
Bytecode * bytecode = reinterpret_cast<Bytecode *>(user_data);
|
||||
return bytecode->AppendData(data, static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
16
dependencies/squirrel/squirrel/CMakeLists.txt
vendored
Normal file
16
dependencies/squirrel/squirrel/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
set(SQUIRREL_SRC sqapi.cpp
|
||||
sqbaselib.cpp
|
||||
sqclass.cpp
|
||||
sqcompiler.cpp
|
||||
sqdebug.cpp
|
||||
sqfuncstate.cpp
|
||||
sqlexer.cpp
|
||||
sqmem.cpp
|
||||
sqobject.cpp
|
||||
sqstate.cpp
|
||||
sqtable.cpp
|
||||
sqvm.cpp)
|
||||
|
||||
add_library(squirrel_static STATIC ${SQUIRREL_SRC})
|
||||
|
||||
target_include_directories(squirrel_static PRIVATE "../include")
|
||||
1602
dependencies/squirrel/squirrel/sqapi.cpp
vendored
Normal file
1602
dependencies/squirrel/squirrel/sqapi.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
94
dependencies/squirrel/squirrel/sqarray.h
vendored
Normal file
94
dependencies/squirrel/squirrel/sqarray.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQARRAY_H_
|
||||
#define _SQARRAY_H_
|
||||
|
||||
struct SQArray : public CHAINABLE_OBJ
|
||||
{
|
||||
private:
|
||||
SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
|
||||
~SQArray()
|
||||
{
|
||||
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
|
||||
}
|
||||
public:
|
||||
static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){
|
||||
SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));
|
||||
new (newarray) SQArray(ss,nInitialSize);
|
||||
return newarray;
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
void Mark(SQCollectable **chain);
|
||||
SQObjectType GetType() {return OT_ARRAY;}
|
||||
#endif
|
||||
void Finalize(){
|
||||
_values.resize(0);
|
||||
}
|
||||
bool Get(const SQInteger nidx,SQObjectPtr &val)
|
||||
{
|
||||
if(nidx>=0 && nidx<(SQInteger)_values.size()){
|
||||
SQObjectPtr &o = _values[nidx];
|
||||
val = _realval(o);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
bool Set(const SQInteger nidx,const SQObjectPtr &val)
|
||||
{
|
||||
if(nidx>=0 && nidx<(SQInteger)_values.size()){
|
||||
_values[nidx]=val;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)
|
||||
{
|
||||
SQUnsignedInteger idx=TranslateIndex(refpos);
|
||||
while(idx<_values.size()){
|
||||
//first found
|
||||
outkey=(SQInteger)idx;
|
||||
SQObjectPtr &o = _values[idx];
|
||||
outval = _realval(o);
|
||||
//return idx for the next iteration
|
||||
return ++idx;
|
||||
}
|
||||
//nothing to iterate anymore
|
||||
return -1;
|
||||
}
|
||||
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 _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);
|
||||
SQObjectPtr &Top(){return _values.top();}
|
||||
void Pop(){_values.pop_back(); ShrinkIfNeeded(); }
|
||||
bool Insert(SQInteger idx,const SQObject &val){
|
||||
if(idx < 0 || idx > (SQInteger)_values.size())
|
||||
return false;
|
||||
_values.insert(idx,val);
|
||||
return true;
|
||||
}
|
||||
void ShrinkIfNeeded() {
|
||||
if(_values.size() <= _values.capacity()>>2) //shrink the array
|
||||
_values.shrinktofit();
|
||||
}
|
||||
bool Remove(SQInteger idx){
|
||||
if(idx < 0 || idx >= (SQInteger)_values.size())
|
||||
return false;
|
||||
_values.remove(idx);
|
||||
ShrinkIfNeeded();
|
||||
return true;
|
||||
}
|
||||
void Release()
|
||||
{
|
||||
sq_delete(this,SQArray);
|
||||
}
|
||||
|
||||
SQObjectPtrVec _values;
|
||||
};
|
||||
#endif //_SQARRAY_H_
|
||||
1266
dependencies/squirrel/squirrel/sqbaselib.cpp
vendored
Normal file
1266
dependencies/squirrel/squirrel/sqbaselib.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
210
dependencies/squirrel/squirrel/sqclass.cpp
vendored
Normal file
210
dependencies/squirrel/squirrel/sqclass.cpp
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#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;
|
||||
_locked = false;
|
||||
_constructoridx = -1;
|
||||
if(_base) {
|
||||
_constructoridx = _base->_constructoridx;
|
||||
_udsize = _base->_udsize;
|
||||
_defaultvalues.copy(base->_defaultvalues);
|
||||
_methods.copy(base->_methods);
|
||||
_COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
|
||||
__ObjAddRef(_base);
|
||||
}
|
||||
_members = base?base->_members->Clone() : SQTable::Create(ss,0);
|
||||
__ObjAddRef(_members);
|
||||
|
||||
INIT_CHAIN();
|
||||
ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
|
||||
}
|
||||
|
||||
void SQClass::Finalize() {
|
||||
_attributes.Null();
|
||||
_NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
|
||||
_methods.resize(0);
|
||||
_NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
|
||||
__ObjRelease(_members);
|
||||
if(_base) {
|
||||
__ObjRelease(_base);
|
||||
}
|
||||
}
|
||||
|
||||
SQClass::~SQClass()
|
||||
{
|
||||
REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
|
||||
Finalize();
|
||||
}
|
||||
|
||||
bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
|
||||
{
|
||||
SQObjectPtr temp;
|
||||
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(belongs_to_static_table) {
|
||||
SQInteger mmidx;
|
||||
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 = theval;
|
||||
_members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
|
||||
_methods.push_back(m);
|
||||
}
|
||||
else {
|
||||
_methods[_member_idx(temp)].val = theval;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
SQClassMember m;
|
||||
m.val = val;
|
||||
_members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
|
||||
_defaultvalues.push_back(m);
|
||||
return true;
|
||||
}
|
||||
|
||||
SQInstance *SQClass::CreateInstance()
|
||||
{
|
||||
if(!_locked) Lock();
|
||||
return SQInstance::Create(_opt_ss(this),this);
|
||||
}
|
||||
|
||||
SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
|
||||
{
|
||||
SQObjectPtr oval;
|
||||
SQInteger idx = _members->Next(false,refpos,outkey,oval);
|
||||
if(idx != -1) {
|
||||
if(_ismethod(oval)) {
|
||||
outval = _methods[_member_idx(oval)].val;
|
||||
}
|
||||
else {
|
||||
SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
|
||||
outval = _realval(o);
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
|
||||
{
|
||||
SQObjectPtr idx;
|
||||
if(_members->Get(key,idx)) {
|
||||
if(_isfield(idx))
|
||||
_defaultvalues[_member_idx(idx)].attrs = val;
|
||||
else
|
||||
_methods[_member_idx(idx)].attrs = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
|
||||
{
|
||||
SQObjectPtr idx;
|
||||
if(_members->Get(key,idx)) {
|
||||
outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void SQInstance::Init(SQSharedState *ss)
|
||||
{
|
||||
_userpointer = NULL;
|
||||
_hook = NULL;
|
||||
__ObjAddRef(_class);
|
||||
_delegate = _class->_members;
|
||||
INIT_CHAIN();
|
||||
ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
|
||||
}
|
||||
|
||||
SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
|
||||
{
|
||||
_memsize = memsize;
|
||||
_class = c;
|
||||
SQUnsignedInteger nvalues = _class->_defaultvalues.size();
|
||||
for(SQUnsignedInteger n = 0; n < nvalues; n++) {
|
||||
new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
|
||||
}
|
||||
Init(ss);
|
||||
}
|
||||
|
||||
SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
|
||||
{
|
||||
_memsize = memsize;
|
||||
_class = i->_class;
|
||||
SQUnsignedInteger nvalues = _class->_defaultvalues.size();
|
||||
for(SQUnsignedInteger n = 0; n < nvalues; n++) {
|
||||
new (&_values[n]) SQObjectPtr(i->_values[n]);
|
||||
}
|
||||
Init(ss);
|
||||
}
|
||||
|
||||
void SQInstance::Finalize()
|
||||
{
|
||||
SQUnsignedInteger nvalues = _class->_defaultvalues.size();
|
||||
__ObjRelease(_class);
|
||||
_NULL_SQOBJECT_VECTOR(_values,nvalues);
|
||||
}
|
||||
|
||||
SQInstance::~SQInstance()
|
||||
{
|
||||
REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
|
||||
if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
|
||||
}
|
||||
|
||||
bool SQInstance::GetMetaMethod(SQVM SQ_UNUSED_ARG(*v),SQMetaMethod mm,SQObjectPtr &res)
|
||||
{
|
||||
if(type(_class->_metamethods[mm]) != OT_NULL) {
|
||||
res = _class->_metamethods[mm];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SQInstance::InstanceOf(SQClass *trg)
|
||||
{
|
||||
SQClass *parent = _class;
|
||||
while(parent != NULL) {
|
||||
if(parent == trg)
|
||||
return true;
|
||||
parent = parent->_base;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
162
dependencies/squirrel/squirrel/sqclass.h
vendored
Normal file
162
dependencies/squirrel/squirrel/sqclass.h
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQCLASS_H_
|
||||
#define _SQCLASS_H_
|
||||
|
||||
struct SQInstance;
|
||||
|
||||
struct SQClassMember {
|
||||
SQObjectPtr val;
|
||||
SQObjectPtr attrs;
|
||||
void Null() {
|
||||
val.Null();
|
||||
attrs.Null();
|
||||
}
|
||||
};
|
||||
|
||||
typedef sqvector<SQClassMember> SQClassMemberVec;
|
||||
|
||||
#define MEMBER_TYPE_METHOD 0x01000000
|
||||
#define MEMBER_TYPE_FIELD 0x02000000
|
||||
|
||||
#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)
|
||||
#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)
|
||||
#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))
|
||||
#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))
|
||||
#define _member_type(o) (_integer(o)&0xFF000000)
|
||||
#define _member_idx(o) (_integer(o)&0x00FFFFFF)
|
||||
|
||||
struct SQClass : public CHAINABLE_OBJ
|
||||
{
|
||||
SQClass(SQSharedState *ss,SQClass *base);
|
||||
public:
|
||||
static SQClass* Create(SQSharedState *ss,SQClass *base) {
|
||||
SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));
|
||||
new (newclass) SQClass(ss, base);
|
||||
return newclass;
|
||||
}
|
||||
~SQClass();
|
||||
bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);
|
||||
bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
|
||||
if(_members->Get(key,val)) {
|
||||
if(_isfield(val)) {
|
||||
SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;
|
||||
val = _realval(o);
|
||||
}
|
||||
else {
|
||||
val = _methods[_member_idx(val)].val;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
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(); }
|
||||
void Release() {
|
||||
if (_hook) { _hook(_typetag,0);}
|
||||
sq_delete(this, SQClass);
|
||||
}
|
||||
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();
|
||||
SQTable *_members;
|
||||
SQClass *_base;
|
||||
SQClassMemberVec _defaultvalues;
|
||||
SQClassMemberVec _methods;
|
||||
SQObjectPtr _metamethods[MT_LAST];
|
||||
SQObjectPtr _attributes;
|
||||
SQUserPointer _typetag;
|
||||
SQRELEASEHOOK _hook;
|
||||
bool _locked;
|
||||
SQInteger _constructoridx;
|
||||
SQInteger _udsize;
|
||||
};
|
||||
|
||||
#define calcinstancesize(_theclass_) \
|
||||
(_theclass_->_udsize + sq_aligning(sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))
|
||||
|
||||
struct SQInstance : public SQDelegable
|
||||
{
|
||||
void Init(SQSharedState *ss);
|
||||
SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);
|
||||
SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);
|
||||
public:
|
||||
static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
|
||||
|
||||
SQInteger size = calcinstancesize(theclass);
|
||||
SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
|
||||
new (newinst) SQInstance(ss, theclass,size);
|
||||
if(theclass->_udsize) {
|
||||
newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
|
||||
}
|
||||
return newinst;
|
||||
}
|
||||
SQInstance *Clone(SQSharedState *ss)
|
||||
{
|
||||
SQInteger size = calcinstancesize(_class);
|
||||
SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
|
||||
new (newinst) SQInstance(ss, this,size);
|
||||
if(_class->_udsize) {
|
||||
newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
|
||||
}
|
||||
return newinst;
|
||||
}
|
||||
~SQInstance();
|
||||
bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
|
||||
if(_class->_members->Get(key,val)) {
|
||||
if(_isfield(val)) {
|
||||
SQObjectPtr &o = _values[_member_idx(val)];
|
||||
val = _realval(o);
|
||||
}
|
||||
else {
|
||||
val = _class->_methods[_member_idx(val)].val;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {
|
||||
SQObjectPtr idx;
|
||||
if(_class->_members->Get(key,idx) && _isfield(idx)) {
|
||||
_values[_member_idx(idx)] = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Release() {
|
||||
_uiRef++;
|
||||
if (_hook) { _hook(_userpointer,0);}
|
||||
_uiRef--;
|
||||
if(_uiRef > 0) return;
|
||||
SQInteger size = _memsize;
|
||||
this->~SQInstance();
|
||||
SQ_FREE(this, size);
|
||||
}
|
||||
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);
|
||||
|
||||
SQClass *_class;
|
||||
SQUserPointer _userpointer;
|
||||
SQRELEASEHOOK _hook;
|
||||
SQInteger _memsize;
|
||||
SQObjectPtr _values[1];
|
||||
};
|
||||
|
||||
#endif //_SQCLASS_H_
|
||||
201
dependencies/squirrel/squirrel/sqclosure.h
vendored
Normal file
201
dependencies/squirrel/squirrel/sqclosure.h
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQCLOSURE_H_
|
||||
#define _SQCLOSURE_H_
|
||||
|
||||
|
||||
#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; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL; _root=NULL;}
|
||||
public:
|
||||
static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func,SQWeakRef *root){
|
||||
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];
|
||||
nc->_root = root;
|
||||
__ObjAddRef(nc->_root);
|
||||
_CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues);
|
||||
_CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams);
|
||||
return nc;
|
||||
}
|
||||
void Release(){
|
||||
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);
|
||||
}
|
||||
void SetRoot(SQWeakRef *r)
|
||||
{
|
||||
__ObjRelease(_root);
|
||||
_root = r;
|
||||
__ObjAddRef(_root);
|
||||
}
|
||||
SQClosure *Clone()
|
||||
{
|
||||
SQFunctionProto *f = _function;
|
||||
SQClosure * ret = SQClosure::Create(_opt_ss(this),f,_root);
|
||||
ret->_env = _env;
|
||||
if(ret->_env) __ObjAddRef(ret->_env);
|
||||
_COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues);
|
||||
_COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams);
|
||||
return ret;
|
||||
}
|
||||
~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(){
|
||||
SQFunctionProto *f = _function;
|
||||
_NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues);
|
||||
_NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams);
|
||||
}
|
||||
SQObjectType GetType() {return OT_CLOSURE;}
|
||||
#endif
|
||||
SQWeakRef *_env;
|
||||
SQWeakRef *_root;
|
||||
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
|
||||
{
|
||||
enum SQGeneratorState{eRunning,eSuspended,eDead};
|
||||
private:
|
||||
SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
|
||||
public:
|
||||
static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){
|
||||
SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));
|
||||
new (nc) SQGenerator(ss,closure);
|
||||
return nc;
|
||||
}
|
||||
~SQGenerator()
|
||||
{
|
||||
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
|
||||
}
|
||||
void Kill(){
|
||||
_state=eDead;
|
||||
_stack.resize(0);
|
||||
_closure.Null();}
|
||||
void Release(){
|
||||
sq_delete(this,SQGenerator);
|
||||
}
|
||||
|
||||
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();}
|
||||
SQObjectType GetType() {return OT_GENERATOR;}
|
||||
#endif
|
||||
SQObjectPtr _closure;
|
||||
SQObjectPtrVec _stack;
|
||||
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); _env = NULL;}
|
||||
public:
|
||||
static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters)
|
||||
{
|
||||
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,_noutervalues);
|
||||
ret->_env = _env;
|
||||
if(ret->_env) __ObjAddRef(ret->_env);
|
||||
ret->_name = _name;
|
||||
_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(){
|
||||
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() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); }
|
||||
SQObjectType GetType() {return OT_NATIVECLOSURE;}
|
||||
#endif
|
||||
SQInteger _nparamscheck;
|
||||
SQIntVec _typecheck;
|
||||
SQObjectPtr *_outervalues;
|
||||
SQUnsignedInteger _noutervalues;
|
||||
SQWeakRef *_env;
|
||||
SQFUNCTION _function;
|
||||
SQObjectPtr _name;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //_SQCLOSURE_H_
|
||||
1578
dependencies/squirrel/squirrel/sqcompiler.cpp
vendored
Normal file
1578
dependencies/squirrel/squirrel/sqcompiler.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
78
dependencies/squirrel/squirrel/sqcompiler.h
vendored
Normal file
78
dependencies/squirrel/squirrel/sqcompiler.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQCOMPILER_H_
|
||||
#define _SQCOMPILER_H_
|
||||
|
||||
struct SQVM;
|
||||
|
||||
#define TK_IDENTIFIER 258
|
||||
#define TK_STRING_LITERAL 259
|
||||
#define TK_INTEGER 260
|
||||
#define TK_FLOAT 261
|
||||
#define TK_BASE 262
|
||||
#define TK_DELETE 263
|
||||
#define TK_EQ 264
|
||||
#define TK_NE 265
|
||||
#define TK_LE 266
|
||||
#define TK_GE 267
|
||||
#define TK_SWITCH 268
|
||||
#define TK_ARROW 269
|
||||
#define TK_AND 270
|
||||
#define TK_OR 271
|
||||
#define TK_IF 272
|
||||
#define TK_ELSE 273
|
||||
#define TK_WHILE 274
|
||||
#define TK_BREAK 275
|
||||
#define TK_FOR 276
|
||||
#define TK_DO 277
|
||||
#define TK_NULL 278
|
||||
#define TK_FOREACH 279
|
||||
#define TK_IN 280
|
||||
#define TK_NEWSLOT 281
|
||||
#define TK_MODULO 282
|
||||
#define TK_LOCAL 283
|
||||
#define TK_CLONE 284
|
||||
#define TK_FUNCTION 285
|
||||
#define TK_RETURN 286
|
||||
#define TK_TYPEOF 287
|
||||
#define TK_UMINUS 288
|
||||
#define TK_PLUSEQ 289
|
||||
#define TK_MINUSEQ 290
|
||||
#define TK_CONTINUE 291
|
||||
#define TK_YIELD 292
|
||||
#define TK_TRY 293
|
||||
#define TK_CATCH 294
|
||||
#define TK_THROW 295
|
||||
#define TK_SHIFTL 296
|
||||
#define TK_SHIFTR 297
|
||||
#define TK_RESUME 298
|
||||
#define TK_DOUBLE_COLON 299
|
||||
#define TK_CASE 300
|
||||
#define TK_DEFAULT 301
|
||||
#define TK_THIS 302
|
||||
#define TK_PLUSPLUS 303
|
||||
#define TK_MINUSMINUS 304
|
||||
#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___LINE__ 313
|
||||
#define TK___FILE__ 314
|
||||
#define TK_TRUE 315
|
||||
#define TK_FALSE 316
|
||||
#define TK_MULEQ 317
|
||||
#define TK_DIVEQ 318
|
||||
#define TK_MODEQ 319
|
||||
#define TK_ATTR_OPEN 320
|
||||
#define TK_ATTR_CLOSE 321
|
||||
#define TK_STATIC 322
|
||||
#define TK_ENUM 323
|
||||
#define TK_CONST 324
|
||||
|
||||
|
||||
|
||||
typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s);
|
||||
bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);
|
||||
#endif //_SQCOMPILER_H_
|
||||
118
dependencies/squirrel/squirrel/sqdebug.cpp
vendored
Normal file
118
dependencies/squirrel/squirrel/sqdebug.cpp
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#include <stdarg.h>
|
||||
#include "sqvm.h"
|
||||
#include "sqfuncproto.h"
|
||||
#include "sqclosure.h"
|
||||
#include "sqstring.h"
|
||||
|
||||
SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi)
|
||||
{
|
||||
SQInteger cssize = v->_callsstacksize;
|
||||
if (cssize > level) {
|
||||
SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
|
||||
if(sq_isclosure(ci._closure)) {
|
||||
SQClosure *c = _closure(ci._closure);
|
||||
SQFunctionProto *proto = c->_function;
|
||||
fi->funcid = proto;
|
||||
fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown");
|
||||
fi->source = type(proto->_sourcename) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown");
|
||||
fi->line = proto->_lineinfos[0]._line;
|
||||
return SQ_OK;
|
||||
}
|
||||
}
|
||||
return sq_throwerror(v,_SC("the object is not a closure"));
|
||||
}
|
||||
|
||||
SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
|
||||
{
|
||||
SQInteger cssize = v->_callsstacksize;
|
||||
if (cssize > level) {
|
||||
memset(si, 0, sizeof(SQStackInfos));
|
||||
SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
|
||||
switch (type(ci._closure)) {
|
||||
case OT_CLOSURE:{
|
||||
SQFunctionProto *func = _closure(ci._closure)->_function;
|
||||
if (type(func->_name) == OT_STRING)
|
||||
si->funcname = _stringval(func->_name);
|
||||
if (type(func->_sourcename) == OT_STRING)
|
||||
si->source = _stringval(func->_sourcename);
|
||||
si->line = func->GetLine(ci._ip);
|
||||
}
|
||||
break;
|
||||
case OT_NATIVECLOSURE:
|
||||
si->source = _SC("NATIVE");
|
||||
si->funcname = _SC("unknown");
|
||||
if(type(_nativeclosure(ci._closure)->_name) == OT_STRING)
|
||||
si->funcname = _stringval(_nativeclosure(ci._closure)->_name);
|
||||
si->line = -1;
|
||||
break;
|
||||
default: break; //shutup compiler
|
||||
}
|
||||
return SQ_OK;
|
||||
}
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
void SQVM::Raise_Error(const SQChar *s, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, s);
|
||||
SQInteger buffersize = (SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2);
|
||||
scvsprintf(_sp(sq_rsl(buffersize)),buffersize, s, vl);
|
||||
va_end(vl);
|
||||
_lasterror = SQString::Create(_ss(this),_spval,-1);
|
||||
}
|
||||
|
||||
void SQVM::Raise_Error(const SQObjectPtr &desc)
|
||||
{
|
||||
_lasterror = desc;
|
||||
}
|
||||
|
||||
SQString *SQVM::PrintObjVal(const SQObjectPtr &o)
|
||||
{
|
||||
switch(type(o)) {
|
||||
case OT_STRING: return _string(o);
|
||||
case OT_INTEGER:
|
||||
scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR), _PRINT_INT_FMT, _integer(o));
|
||||
return SQString::Create(_ss(this), _spval);
|
||||
break;
|
||||
case OT_FLOAT:
|
||||
scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)), sq_rsl(NUMBER_MAX_CHAR), _SC("%.14g"), _float(o));
|
||||
return SQString::Create(_ss(this), _spval);
|
||||
break;
|
||||
default:
|
||||
return SQString::Create(_ss(this), GetTypeName(o));
|
||||
}
|
||||
}
|
||||
|
||||
void SQVM::Raise_IdxError(const SQObjectPtr &o)
|
||||
{
|
||||
SQObjectPtr oval = PrintObjVal(o);
|
||||
Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));
|
||||
}
|
||||
|
||||
void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)
|
||||
{
|
||||
SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);
|
||||
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;
|
||||
for(SQInteger i=0; i<16; i++)
|
||||
{
|
||||
SQInteger mask = 0x00000001 << i;
|
||||
if(typemask & (mask)) {
|
||||
if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes);
|
||||
found ++;
|
||||
StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);
|
||||
}
|
||||
}
|
||||
Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));
|
||||
}
|
||||
154
dependencies/squirrel/squirrel/sqfuncproto.h
vendored
Normal file
154
dependencies/squirrel/squirrel/sqfuncproto.h
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQFUNCTION_H_
|
||||
#define _SQFUNCTION_H_
|
||||
|
||||
#include "sqopcodes.h"
|
||||
|
||||
enum SQOuterType {
|
||||
otLOCAL = 0,
|
||||
otOUTER = 1
|
||||
};
|
||||
|
||||
struct SQOuterVar
|
||||
{
|
||||
|
||||
SQOuterVar(){}
|
||||
SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
|
||||
{
|
||||
_name = name;
|
||||
_src=src;
|
||||
_type=t;
|
||||
}
|
||||
SQOuterVar(const SQOuterVar &ov)
|
||||
{
|
||||
_type=ov._type;
|
||||
_src=ov._src;
|
||||
_name=ov._name;
|
||||
}
|
||||
SQOuterType _type;
|
||||
SQObjectPtr _name;
|
||||
SQObjectPtr _src;
|
||||
};
|
||||
|
||||
struct SQLocalVarInfo
|
||||
{
|
||||
SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){}
|
||||
SQLocalVarInfo(const SQLocalVarInfo &lvi)
|
||||
{
|
||||
_name=lvi._name;
|
||||
_start_op=lvi._start_op;
|
||||
_end_op=lvi._end_op;
|
||||
_pos=lvi._pos;
|
||||
}
|
||||
SQObjectPtr _name;
|
||||
SQUnsignedInteger _start_op;
|
||||
SQUnsignedInteger _end_op;
|
||||
SQUnsignedInteger _pos;
|
||||
};
|
||||
|
||||
struct SQLineInfo { SQInteger _line;SQInteger _op; };
|
||||
|
||||
typedef sqvector<SQOuterVar> SQOuterVarVec;
|
||||
typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
|
||||
typedef sqvector<SQLineInfo> SQLineInfoVec;
|
||||
|
||||
#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \
|
||||
+((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
|
||||
+(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \
|
||||
+(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
|
||||
+(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))
|
||||
|
||||
|
||||
struct SQFunctionProto : public CHAINABLE_OBJ
|
||||
{
|
||||
private:
|
||||
SQFunctionProto(SQSharedState *ss);
|
||||
~SQFunctionProto();
|
||||
|
||||
public:
|
||||
static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions,
|
||||
SQInteger nliterals,SQInteger nparameters,
|
||||
SQInteger nfunctions,SQInteger noutervalues,
|
||||
SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
|
||||
{
|
||||
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(ss);
|
||||
f->_ninstructions = ninstructions;
|
||||
f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];
|
||||
f->_nliterals = nliterals;
|
||||
f->_parameters = (SQObjectPtr*)&f->_literals[nliterals];
|
||||
f->_nparameters = nparameters;
|
||||
f->_functions = (SQObjectPtr*)&f->_parameters[nparameters];
|
||||
f->_nfunctions = nfunctions;
|
||||
f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];
|
||||
f->_noutervalues = noutervalues;
|
||||
f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];
|
||||
f->_nlineinfos = nlineinfos;
|
||||
f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
|
||||
f->_nlocalvarinfos = nlocalvarinfos;
|
||||
f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];
|
||||
f->_ndefaultparams = ndefaultparams;
|
||||
|
||||
_CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);
|
||||
_CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);
|
||||
_CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions);
|
||||
_CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);
|
||||
//_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
|
||||
_CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
|
||||
return f;
|
||||
}
|
||||
void Release(){
|
||||
_DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
|
||||
_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
|
||||
_DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
|
||||
_DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
|
||||
//_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
|
||||
_DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
|
||||
SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
|
||||
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;
|
||||
SQInteger _varparams;
|
||||
|
||||
SQInteger _nlocalvarinfos;
|
||||
SQLocalVarInfo *_localvarinfos;
|
||||
|
||||
SQInteger _nlineinfos;
|
||||
SQLineInfo *_lineinfos;
|
||||
|
||||
SQInteger _nliterals;
|
||||
SQObjectPtr *_literals;
|
||||
|
||||
SQInteger _nparameters;
|
||||
SQObjectPtr *_parameters;
|
||||
|
||||
SQInteger _nfunctions;
|
||||
SQObjectPtr *_functions;
|
||||
|
||||
SQInteger _noutervalues;
|
||||
SQOuterVar *_outervalues;
|
||||
|
||||
SQInteger _ndefaultparams;
|
||||
SQInteger *_defaultparams;
|
||||
|
||||
SQInteger _ninstructions;
|
||||
SQInstruction _instructions[1];
|
||||
};
|
||||
|
||||
#endif //_SQFUNCTION_H_
|
||||
653
dependencies/squirrel/squirrel/sqfuncstate.cpp
vendored
Normal file
653
dependencies/squirrel/squirrel/sqfuncstate.cpp
vendored
Normal file
@@ -0,0 +1,653 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#ifndef NO_COMPILER
|
||||
#include "sqcompiler.h"
|
||||
#include "sqstring.h"
|
||||
#include "sqfuncproto.h"
|
||||
#include "sqtable.h"
|
||||
#include "sqopcodes.h"
|
||||
#include "sqfuncstate.h"
|
||||
|
||||
#ifdef _DEBUG_DUMP
|
||||
SQInstructionDesc g_InstrDesc[]={
|
||||
{_SC("_OP_LINE")},
|
||||
{_SC("_OP_LOAD")},
|
||||
{_SC("_OP_LOADINT")},
|
||||
{_SC("_OP_LOADFLOAT")},
|
||||
{_SC("_OP_DLOAD")},
|
||||
{_SC("_OP_TAILCALL")},
|
||||
{_SC("_OP_CALL")},
|
||||
{_SC("_OP_PREPCALL")},
|
||||
{_SC("_OP_PREPCALLK")},
|
||||
{_SC("_OP_GETK")},
|
||||
{_SC("_OP_MOVE")},
|
||||
{_SC("_OP_NEWSLOT")},
|
||||
{_SC("_OP_DELETE")},
|
||||
{_SC("_OP_SET")},
|
||||
{_SC("_OP_GET")},
|
||||
{_SC("_OP_EQ")},
|
||||
{_SC("_OP_NE")},
|
||||
{_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_LOADROOT")},
|
||||
{_SC("_OP_LOADBOOL")},
|
||||
{_SC("_OP_DMOVE")},
|
||||
{_SC("_OP_JMP")},
|
||||
{_SC("_OP_JCMP")},
|
||||
{_SC("_OP_JZ")},
|
||||
{_SC("_OP_SETOUTER")},
|
||||
{_SC("_OP_GETOUTER")},
|
||||
{_SC("_OP_NEWOBJ")},
|
||||
{_SC("_OP_APPENDARRAY")},
|
||||
{_SC("_OP_COMPARITH")},
|
||||
{_SC("_OP_INC")},
|
||||
{_SC("_OP_INCL")},
|
||||
{_SC("_OP_PINC")},
|
||||
{_SC("_OP_PINCL")},
|
||||
{_SC("_OP_CMP")},
|
||||
{_SC("_OP_EXISTS")},
|
||||
{_SC("_OP_INSTANCEOF")},
|
||||
{_SC("_OP_AND")},
|
||||
{_SC("_OP_OR")},
|
||||
{_SC("_OP_NEG")},
|
||||
{_SC("_OP_NOT")},
|
||||
{_SC("_OP_BWNOT")},
|
||||
{_SC("_OP_CLOSURE")},
|
||||
{_SC("_OP_YIELD")},
|
||||
{_SC("_OP_RESUME")},
|
||||
{_SC("_OP_FOREACH")},
|
||||
{_SC("_OP_POSTFOREACH")},
|
||||
{_SC("_OP_CLONE")},
|
||||
{_SC("_OP_TYPEOF")},
|
||||
{_SC("_OP_PUSHTRAP")},
|
||||
{_SC("_OP_POPTRAP")},
|
||||
{_SC("_OP_THROW")},
|
||||
{_SC("_OP_NEWSLOTA")},
|
||||
{_SC("_OP_GETBASE")},
|
||||
{_SC("_OP_CLOSE")},
|
||||
};
|
||||
#endif
|
||||
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: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
|
||||
case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
|
||||
default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
|
||||
}
|
||||
}
|
||||
|
||||
SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
|
||||
{
|
||||
_nliterals = 0;
|
||||
_literals = SQTable::Create(ss,0);
|
||||
_strings = SQTable::Create(ss,0);
|
||||
_sharedstate = ss;
|
||||
_lastline = 0;
|
||||
_optimization = true;
|
||||
_parent = parent;
|
||||
_stacksize = 0;
|
||||
_traps = 0;
|
||||
_returnexp = 0;
|
||||
_varparams = false;
|
||||
_errfunc = efunc;
|
||||
_errtarget = ed;
|
||||
_bgenerator = false;
|
||||
_outers = 0;
|
||||
_ss = ss;
|
||||
|
||||
}
|
||||
|
||||
void SQFuncState::Error(const SQChar *err)
|
||||
{
|
||||
_errfunc(_errtarget,err);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_DUMP
|
||||
void SQFuncState::Dump(SQFunctionProto *func)
|
||||
{
|
||||
SQUnsignedInteger n=0,i;
|
||||
SQInteger si;
|
||||
scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
|
||||
scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
|
||||
scprintf(_SC("--------------------------------------------------------------------\n"));
|
||||
scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
|
||||
scprintf(_SC("-----LITERALS\n"));
|
||||
SQObjectPtr refidx,key,val;
|
||||
SQInteger idx;
|
||||
SQObjectPtrVec templiterals;
|
||||
templiterals.resize(_nliterals);
|
||||
while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
|
||||
refidx=idx;
|
||||
templiterals[_integer(val)]=key;
|
||||
}
|
||||
for(i=0;i<templiterals.size();i++){
|
||||
scprintf(_SC("[%d] "),n);
|
||||
DumpLiteral(templiterals[i]);
|
||||
scprintf(_SC("\n"));
|
||||
n++;
|
||||
}
|
||||
scprintf(_SC("-----PARAMS\n"));
|
||||
if(_varparams)
|
||||
scprintf(_SC("<<VARPARAMS>>\n"));
|
||||
n=0;
|
||||
for(i=0;i<_parameters.size();i++){
|
||||
scprintf(_SC("[%d] "),n);
|
||||
DumpLiteral(_parameters[i]);
|
||||
scprintf(_SC("\n"));
|
||||
n++;
|
||||
}
|
||||
scprintf(_SC("-----LOCALS\n"));
|
||||
for(si=0;si<func->_nlocalvarinfos;si++){
|
||||
SQLocalVarInfo lvi=func->_localvarinfos[si];
|
||||
scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
|
||||
n++;
|
||||
}
|
||||
scprintf(_SC("-----LINE INFO\n"));
|
||||
for(i=0;i<_lineinfos.size();i++){
|
||||
SQLineInfo li=_lineinfos[i];
|
||||
scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
|
||||
n++;
|
||||
}
|
||||
scprintf(_SC("-----dump\n"));
|
||||
n=0;
|
||||
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)
|
||||
scprintf(_SC("null"));
|
||||
else {
|
||||
SQInteger refidx;
|
||||
SQObjectPtr val,key,refo;
|
||||
while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
|
||||
refo = refidx;
|
||||
}
|
||||
DumpLiteral(key);
|
||||
}
|
||||
if(inst.op != _OP_DLOAD) {
|
||||
scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
|
||||
}
|
||||
else {
|
||||
scprintf(_SC(" %d "),inst._arg2);
|
||||
lidx = inst._arg3;
|
||||
if(lidx >= 0xFFFFFFFF)
|
||||
scprintf(_SC("null"));
|
||||
else {
|
||||
SQInteger refidx;
|
||||
SQObjectPtr val,key,refo;
|
||||
while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
|
||||
refo = refidx;
|
||||
}
|
||||
DumpLiteral(key);
|
||||
scprintf(_SC("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
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){
|
||||
scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
|
||||
}*/
|
||||
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"));
|
||||
scprintf(_SC("stack size[%d]\n"),func->_stacksize);
|
||||
scprintf(_SC("--------------------------------------------------------------------\n\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
|
||||
{
|
||||
return GetConstant(SQObjectPtr(cons));
|
||||
}
|
||||
|
||||
SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
|
||||
{
|
||||
return GetConstant(SQObjectPtr(cons));
|
||||
}
|
||||
|
||||
SQInteger SQFuncState::GetConstant(const SQObject &cons)
|
||||
{
|
||||
SQObjectPtr val;
|
||||
if(!_table(_literals)->Get(cons,val))
|
||||
{
|
||||
val = _nliterals;
|
||||
_table(_literals)->NewSlot(cons,val);
|
||||
_nliterals++;
|
||||
if(_nliterals > MAX_LITERALS) {
|
||||
val.Null();
|
||||
Error(_SC("internal compiler error: too many literals"));
|
||||
}
|
||||
}
|
||||
return _integer(val);
|
||||
}
|
||||
|
||||
void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
|
||||
{
|
||||
_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
|
||||
_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
|
||||
_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
|
||||
_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
|
||||
}
|
||||
|
||||
void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
|
||||
{
|
||||
switch(arg){
|
||||
case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
|
||||
case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
|
||||
case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
|
||||
case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
|
||||
};
|
||||
}
|
||||
|
||||
SQInteger SQFuncState::AllocStackPos()
|
||||
{
|
||||
SQInteger npos=_vlocals.size();
|
||||
_vlocals.push_back(SQLocalVarInfo());
|
||||
if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
|
||||
if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
|
||||
_stacksize=_vlocals.size();
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
SQInteger SQFuncState::PushTarget(SQInteger n)
|
||||
{
|
||||
if(n!=-1){
|
||||
_targetstack.push_back(n);
|
||||
return n;
|
||||
}
|
||||
n=AllocStackPos();
|
||||
_targetstack.push_back(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
SQInteger SQFuncState::GetUpTarget(SQInteger n){
|
||||
return _targetstack[((_targetstack.size()-1)-n)];
|
||||
}
|
||||
|
||||
SQInteger SQFuncState::TopTarget(){
|
||||
return _targetstack.back();
|
||||
}
|
||||
SQInteger SQFuncState::PopTarget()
|
||||
{
|
||||
SQUnsignedInteger npos=_targetstack.back();
|
||||
assert(npos < _vlocals.size());
|
||||
SQLocalVarInfo &t = _vlocals[npos];
|
||||
if(type(t._name)==OT_NULL){
|
||||
_vlocals.pop_back();
|
||||
}
|
||||
_targetstack.pop_back();
|
||||
return npos;
|
||||
}
|
||||
|
||||
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();
|
||||
if(type(lvi._name)!=OT_NULL){
|
||||
if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
|
||||
_outers--;
|
||||
}
|
||||
lvi._end_op = GetCurrentPos();
|
||||
_localvarinfos.push_back(lvi);
|
||||
}
|
||||
_vlocals.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
|
||||
{
|
||||
SQObjectPtr val;
|
||||
if(_table(_sharedstate->_consts)->Get(name,val)) {
|
||||
e = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
|
||||
{
|
||||
if(stkpos>=_vlocals.size())return false;
|
||||
else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
|
||||
{
|
||||
SQInteger pos=_vlocals.size();
|
||||
SQLocalVarInfo lvi;
|
||||
lvi._name=name;
|
||||
lvi._start_op=GetCurrentPos()+1;
|
||||
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){
|
||||
SQLocalVarInfo &lvi = _vlocals[locals-1];
|
||||
if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
|
||||
return locals-1;
|
||||
}
|
||||
locals--;
|
||||
}
|
||||
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();
|
||||
for(SQInteger i = 0; i<outers; i++) {
|
||||
if(_string(_outervalues[i]._name) == _string(name))
|
||||
return i;
|
||||
}
|
||||
SQInteger pos=-1;
|
||||
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 _outervalues.size() - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_parent->MarkLocalAsOuter(pos);
|
||||
_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
|
||||
return _outervalues.size() - 1;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SQFuncState::AddParameter(const SQObject &name)
|
||||
{
|
||||
PushLocalVariable(name);
|
||||
_parameters.push_back(name);
|
||||
}
|
||||
|
||||
void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
|
||||
{
|
||||
if(_lastline!=line || force){
|
||||
SQLineInfo li;
|
||||
li._line=line;li._op=(GetCurrentPos()+1);
|
||||
if(lineop)AddInstruction(_OP_LINE,0,line);
|
||||
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;
|
||||
}
|
||||
break;
|
||||
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:
|
||||
if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
|
||||
pi._arg1 = pi._arg1;
|
||||
pi._arg2 = (unsigned char)i._arg1;
|
||||
pi.op = _OP_GETK;
|
||||
pi._arg0 = i._arg0;
|
||||
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case _OP_PREPCALL:
|
||||
if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
|
||||
pi.op = _OP_PREPCALLK;
|
||||
pi._arg0 = i._arg0;
|
||||
pi._arg1 = pi._arg1;
|
||||
pi._arg2 = i._arg2;
|
||||
pi._arg3 = i._arg3;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
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 = (unsigned char)aat;
|
||||
pi._arg3 = MAX_FUNC_STACKSIZE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case _OP_MOVE:
|
||||
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)
|
||||
{
|
||||
pi.op = _OP_DMOVE;
|
||||
pi._arg2 = i._arg0;
|
||||
pi._arg3 = (unsigned char)i._arg1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case _OP_LOAD:
|
||||
if(pi.op == _OP_LOAD && i._arg1 < 256) {
|
||||
pi.op = _OP_DLOAD;
|
||||
pi._arg2 = i._arg0;
|
||||
pi._arg3 = (unsigned char)i._arg1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case _OP_EQ:case _OP_NE:
|
||||
if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
|
||||
{
|
||||
pi.op = i.op;
|
||||
pi._arg0 = i._arg0;
|
||||
pi._arg1 = pi._arg1;
|
||||
pi._arg2 = i._arg2;
|
||||
pi._arg3 = MAX_FUNC_STACKSIZE;
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case _OP_LINE:
|
||||
if(pi.op == _OP_LINE) {
|
||||
_instructions.pop_back();
|
||||
_lineinfos.pop_back();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
_optimization = true;
|
||||
_instructions.push_back(i);
|
||||
}
|
||||
|
||||
SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
|
||||
{
|
||||
SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
|
||||
_table(_strings)->NewSlot(ns,(SQInteger)1);
|
||||
return ns;
|
||||
}
|
||||
|
||||
SQObject SQFuncState::CreateTable()
|
||||
{
|
||||
SQObjectPtr nt(SQTable::Create(_sharedstate,0));
|
||||
_table(_strings)->NewSlot(nt,(SQInteger)1);
|
||||
return nt;
|
||||
}
|
||||
|
||||
SQFunctionProto *SQFuncState::BuildProto()
|
||||
{
|
||||
|
||||
SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),
|
||||
_nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
|
||||
_lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
|
||||
|
||||
SQObjectPtr refidx,key,val;
|
||||
SQInteger idx;
|
||||
|
||||
f->_stacksize = _stacksize;
|
||||
f->_sourcename = _sourcename;
|
||||
f->_bgenerator = _bgenerator;
|
||||
f->_name = _name;
|
||||
|
||||
while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
|
||||
f->_literals[_integer(val)]=key;
|
||||
refidx=idx;
|
||||
}
|
||||
|
||||
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 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));
|
||||
|
||||
f->_varparams = _varparams;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
|
||||
{
|
||||
SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
|
||||
new (child) SQFuncState(ss,this,_errfunc,_errtarget);
|
||||
_childstates.push_back(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
void SQFuncState::PopChildState()
|
||||
{
|
||||
SQFuncState *child = _childstates.back();
|
||||
sq_delete(child,SQFuncState);
|
||||
_childstates.pop_back();
|
||||
}
|
||||
|
||||
SQFuncState::~SQFuncState()
|
||||
{
|
||||
while(_childstates.size() > 0)
|
||||
{
|
||||
PopChildState();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
91
dependencies/squirrel/squirrel/sqfuncstate.h
vendored
Normal file
91
dependencies/squirrel/squirrel/sqfuncstate.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQFUNCSTATE_H_
|
||||
#define _SQFUNCSTATE_H_
|
||||
///////////////////////////////////
|
||||
#include "squtils.h"
|
||||
|
||||
struct SQFuncState
|
||||
{
|
||||
SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
|
||||
~SQFuncState();
|
||||
#ifdef _DEBUG_DUMP
|
||||
void Dump(SQFunctionProto *func);
|
||||
#endif
|
||||
void Error(const SQChar *err);
|
||||
SQFuncState *PushChildState(SQSharedState *ss);
|
||||
void PopChildState();
|
||||
void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
|
||||
void AddInstruction(SQInstruction &i);
|
||||
void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0);
|
||||
void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val);
|
||||
SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}
|
||||
void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}
|
||||
void SetStackSize(SQInteger n);
|
||||
SQInteger CountOuters(SQInteger stacksize);
|
||||
void SnoozeOpt(){_optimization=false;}
|
||||
void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }
|
||||
SQInteger GetDefaultParamCount() { return _defaultparams.size(); }
|
||||
SQInteger GetCurrentPos(){return _instructions.size()-1;}
|
||||
SQInteger GetNumericConstant(const SQInteger cons);
|
||||
SQInteger GetNumericConstant(const SQFloat cons);
|
||||
SQInteger PushLocalVariable(const SQObject &name);
|
||||
void AddParameter(const SQObject &name);
|
||||
//void AddOuterValue(const SQObject &name);
|
||||
SQInteger GetLocalVariable(const SQObject &name);
|
||||
void MarkLocalAsOuter(SQInteger pos);
|
||||
SQInteger GetOuterVariable(const SQObject &name);
|
||||
SQInteger GenerateCode();
|
||||
SQInteger GetStackSize();
|
||||
SQInteger CalcStackFrameSize();
|
||||
void AddLineInfos(SQInteger line,bool lineop,bool force=false);
|
||||
SQFunctionProto *BuildProto();
|
||||
SQInteger AllocStackPos();
|
||||
SQInteger PushTarget(SQInteger n=-1);
|
||||
SQInteger PopTarget();
|
||||
SQInteger TopTarget();
|
||||
SQInteger GetUpTarget(SQInteger n);
|
||||
void DiscardTarget();
|
||||
bool IsLocal(SQUnsignedInteger stkpos);
|
||||
SQObject CreateString(const SQChar *s,SQInteger len = -1);
|
||||
SQObject CreateTable();
|
||||
bool IsConstant(const SQObject &name,SQObject &e);
|
||||
SQInteger _returnexp;
|
||||
SQLocalVarInfoVec _vlocals;
|
||||
SQIntVec _targetstack;
|
||||
SQInteger _stacksize;
|
||||
bool _varparams;
|
||||
bool _bgenerator;
|
||||
SQIntVec _unresolvedbreaks;
|
||||
SQIntVec _unresolvedcontinues;
|
||||
SQObjectPtrVec _functions;
|
||||
SQObjectPtrVec _parameters;
|
||||
SQOuterVarVec _outervalues;
|
||||
SQInstructionVec _instructions;
|
||||
SQLocalVarInfoVec _localvarinfos;
|
||||
SQObjectPtr _literals;
|
||||
SQObjectPtr _strings;
|
||||
SQObjectPtr _name;
|
||||
SQObjectPtr _sourcename;
|
||||
SQInteger _nliterals;
|
||||
SQLineInfoVec _lineinfos;
|
||||
SQFuncState *_parent;
|
||||
SQIntVec _scope_blocks;
|
||||
SQIntVec _breaktargets;
|
||||
SQIntVec _continuetargets;
|
||||
SQIntVec _defaultparams;
|
||||
SQInteger _lastline;
|
||||
SQInteger _traps; //contains number of nested exception traps
|
||||
SQInteger _outers;
|
||||
bool _optimization;
|
||||
SQSharedState *_sharedstate;
|
||||
sqvector<SQFuncState*> _childstates;
|
||||
SQInteger GetConstant(const SQObject &cons);
|
||||
private:
|
||||
CompilerErrorFunc _errfunc;
|
||||
void *_errtarget;
|
||||
SQSharedState *_ss;
|
||||
};
|
||||
|
||||
|
||||
#endif //_SQFUNCSTATE_H_
|
||||
|
||||
561
dependencies/squirrel/squirrel/sqlexer.cpp
vendored
Normal file
561
dependencies/squirrel/squirrel/sqlexer.cpp
vendored
Normal file
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include "sqtable.h"
|
||||
#include "sqstring.h"
|
||||
#include "sqcompiler.h"
|
||||
#include "sqlexer.h"
|
||||
|
||||
#define CUR_CHAR (_currdata)
|
||||
#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}
|
||||
#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)
|
||||
#define NEXT() {Next();_currentcolumn++;}
|
||||
#define INIT_TEMP_STRING() { _longstr.resize(0);}
|
||||
#define APPEND_CHAR(c) { _longstr.push_back(c);}
|
||||
#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}
|
||||
#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))
|
||||
|
||||
SQLexer::SQLexer(){}
|
||||
SQLexer::~SQLexer()
|
||||
{
|
||||
_keywords->Release();
|
||||
}
|
||||
|
||||
void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed)
|
||||
{
|
||||
_errfunc = efunc;
|
||||
_errtarget = ed;
|
||||
_sharedstate = ss;
|
||||
_keywords = SQTable::Create(ss, 37);
|
||||
ADD_KEYWORD(while, TK_WHILE);
|
||||
ADD_KEYWORD(do, TK_DO);
|
||||
ADD_KEYWORD(if, TK_IF);
|
||||
ADD_KEYWORD(else, TK_ELSE);
|
||||
ADD_KEYWORD(break, TK_BREAK);
|
||||
ADD_KEYWORD(continue, TK_CONTINUE);
|
||||
ADD_KEYWORD(return, TK_RETURN);
|
||||
ADD_KEYWORD(null, TK_NULL);
|
||||
ADD_KEYWORD(function, TK_FUNCTION);
|
||||
ADD_KEYWORD(local, TK_LOCAL);
|
||||
ADD_KEYWORD(for, TK_FOR);
|
||||
ADD_KEYWORD(foreach, TK_FOREACH);
|
||||
ADD_KEYWORD(in, TK_IN);
|
||||
ADD_KEYWORD(typeof, TK_TYPEOF);
|
||||
ADD_KEYWORD(base, TK_BASE);
|
||||
ADD_KEYWORD(delete, TK_DELETE);
|
||||
ADD_KEYWORD(try, TK_TRY);
|
||||
ADD_KEYWORD(catch, TK_CATCH);
|
||||
ADD_KEYWORD(throw, TK_THROW);
|
||||
ADD_KEYWORD(clone, TK_CLONE);
|
||||
ADD_KEYWORD(yield, TK_YIELD);
|
||||
ADD_KEYWORD(resume, TK_RESUME);
|
||||
ADD_KEYWORD(switch, TK_SWITCH);
|
||||
ADD_KEYWORD(case, TK_CASE);
|
||||
ADD_KEYWORD(default, TK_DEFAULT);
|
||||
ADD_KEYWORD(this, TK_THIS);
|
||||
ADD_KEYWORD(class,TK_CLASS);
|
||||
ADD_KEYWORD(extends,TK_EXTENDS);
|
||||
ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
|
||||
ADD_KEYWORD(instanceof,TK_INSTANCEOF);
|
||||
ADD_KEYWORD(true,TK_TRUE);
|
||||
ADD_KEYWORD(false,TK_FALSE);
|
||||
ADD_KEYWORD(static,TK_STATIC);
|
||||
ADD_KEYWORD(enum,TK_ENUM);
|
||||
ADD_KEYWORD(const,TK_CONST);
|
||||
ADD_KEYWORD(__LINE__,TK___LINE__);
|
||||
ADD_KEYWORD(__FILE__,TK___FILE__);
|
||||
|
||||
_readf = rg;
|
||||
_up = up;
|
||||
_lasttokenline = _currentline = 1;
|
||||
_currentcolumn = 0;
|
||||
_prevtoken = -1;
|
||||
_reached_eof = SQFalse;
|
||||
Next();
|
||||
}
|
||||
|
||||
void SQLexer::Error(const SQChar *err)
|
||||
{
|
||||
_errfunc(_errtarget,err);
|
||||
}
|
||||
|
||||
void SQLexer::Next()
|
||||
{
|
||||
SQInteger t = _readf(_up);
|
||||
if(t > MAX_CHAR) Error(_SC("Invalid character"));
|
||||
if(t != 0) {
|
||||
_currdata = (LexChar)t;
|
||||
return;
|
||||
}
|
||||
_currdata = SQUIRREL_EOB;
|
||||
_reached_eof = SQTrue;
|
||||
}
|
||||
|
||||
const SQChar *SQLexer::Tok2Str(SQInteger tok)
|
||||
{
|
||||
SQObjectPtr itr, key, val;
|
||||
SQInteger nitr;
|
||||
while((nitr = _keywords->Next(false,itr, key, val)) != -1) {
|
||||
itr = (SQInteger)nitr;
|
||||
if(((SQInteger)_integer(val)) == tok)
|
||||
return _stringval(key);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SQLexer::LexBlockComment()
|
||||
{
|
||||
bool done = false;
|
||||
while(!done) {
|
||||
switch(CUR_CHAR) {
|
||||
case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
|
||||
case _SC('\n'): _currentline++; NEXT(); continue;
|
||||
case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));
|
||||
default: NEXT();
|
||||
}
|
||||
}
|
||||
}
|
||||
void SQLexer::LexLineComment()
|
||||
{
|
||||
do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
|
||||
}
|
||||
|
||||
SQInteger SQLexer::Lex()
|
||||
{
|
||||
_lasttokenline = _currentline;
|
||||
while(CUR_CHAR != SQUIRREL_EOB) {
|
||||
switch(CUR_CHAR){
|
||||
case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;
|
||||
case _SC('\n'):
|
||||
_currentline++;
|
||||
_prevtoken=_curtoken;
|
||||
_curtoken=_SC('\n');
|
||||
NEXT();
|
||||
_currentcolumn=1;
|
||||
continue;
|
||||
case _SC('#'): LexLineComment(); continue;
|
||||
case _SC('/'):
|
||||
NEXT();
|
||||
switch(CUR_CHAR){
|
||||
case _SC('*'):
|
||||
NEXT();
|
||||
LexBlockComment();
|
||||
continue;
|
||||
case _SC('/'):
|
||||
LexLineComment();
|
||||
continue;
|
||||
case _SC('='):
|
||||
NEXT();
|
||||
RETURN_TOKEN(TK_DIVEQ);
|
||||
continue;
|
||||
case _SC('>'):
|
||||
NEXT();
|
||||
RETURN_TOKEN(TK_ATTR_CLOSE);
|
||||
continue;
|
||||
default:
|
||||
RETURN_TOKEN('/');
|
||||
}
|
||||
case _SC('='):
|
||||
NEXT();
|
||||
if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }
|
||||
else { NEXT(); RETURN_TOKEN(TK_EQ); }
|
||||
case _SC('<'):
|
||||
NEXT();
|
||||
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();
|
||||
if(CUR_CHAR == _SC('>')){
|
||||
NEXT();
|
||||
RETURN_TOKEN(TK_USHIFTR);
|
||||
}
|
||||
RETURN_TOKEN(TK_SHIFTR);
|
||||
}
|
||||
else { RETURN_TOKEN('>') }
|
||||
case _SC('!'):
|
||||
NEXT();
|
||||
if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}
|
||||
else { NEXT(); RETURN_TOKEN(TK_NE); }
|
||||
case _SC('@'): {
|
||||
SQInteger stype;
|
||||
NEXT();
|
||||
if(CUR_CHAR != _SC('"')) {
|
||||
RETURN_TOKEN('@');
|
||||
}
|
||||
if((stype=ReadString('"',true))!=-1) {
|
||||
RETURN_TOKEN(stype);
|
||||
}
|
||||
Error(_SC("error parsing the string"));
|
||||
}
|
||||
case _SC('"'):
|
||||
case _SC('\''): {
|
||||
SQInteger stype;
|
||||
if((stype=ReadString(CUR_CHAR,false))!=-1){
|
||||
RETURN_TOKEN(stype);
|
||||
}
|
||||
Error(_SC("error parsing the string"));
|
||||
}
|
||||
case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):
|
||||
case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):
|
||||
{SQInteger ret = CUR_CHAR;
|
||||
NEXT(); RETURN_TOKEN(ret); }
|
||||
case _SC('.'):
|
||||
NEXT();
|
||||
if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
|
||||
NEXT();
|
||||
if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); }
|
||||
NEXT();
|
||||
RETURN_TOKEN(TK_VARPARAMS);
|
||||
case _SC('&'):
|
||||
NEXT();
|
||||
if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }
|
||||
else { NEXT(); RETURN_TOKEN(TK_AND); }
|
||||
case _SC('|'):
|
||||
NEXT();
|
||||
if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }
|
||||
else { NEXT(); RETURN_TOKEN(TK_OR); }
|
||||
case _SC(':'):
|
||||
NEXT();
|
||||
if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }
|
||||
else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }
|
||||
case _SC('*'):
|
||||
NEXT();
|
||||
if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}
|
||||
else RETURN_TOKEN('*');
|
||||
case _SC('%'):
|
||||
NEXT();
|
||||
if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}
|
||||
else RETURN_TOKEN('%');
|
||||
case _SC('-'):
|
||||
NEXT();
|
||||
if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}
|
||||
else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}
|
||||
else RETURN_TOKEN('-');
|
||||
case _SC('+'):
|
||||
NEXT();
|
||||
if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}
|
||||
else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}
|
||||
else RETURN_TOKEN('+');
|
||||
case SQUIRREL_EOB:
|
||||
return 0;
|
||||
default:{
|
||||
if (scisdigit(CUR_CHAR)) {
|
||||
SQInteger ret = ReadNumber();
|
||||
RETURN_TOKEN(ret);
|
||||
}
|
||||
else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
|
||||
SQInteger t = ReadID();
|
||||
RETURN_TOKEN(t);
|
||||
}
|
||||
else {
|
||||
SQInteger c = CUR_CHAR;
|
||||
if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));
|
||||
NEXT();
|
||||
RETURN_TOKEN(c);
|
||||
}
|
||||
RETURN_TOKEN(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SQInteger SQLexer::GetIDType(const SQChar *s,SQInteger len)
|
||||
{
|
||||
SQObjectPtr t;
|
||||
if(_keywords->GetStr(s,len, t)) {
|
||||
return SQInteger(_integer(t));
|
||||
}
|
||||
return TK_IDENTIFIER;
|
||||
}
|
||||
|
||||
#ifdef SQUNICODE
|
||||
#if WCHAR_SIZE == 2
|
||||
SQInteger SQLexer::AddUTF16(SQUnsignedInteger ch)
|
||||
{
|
||||
if (ch >= 0x10000)
|
||||
{
|
||||
SQUnsignedInteger code = (ch - 0x10000);
|
||||
APPEND_CHAR((SQChar)(0xD800 | (code >> 10)));
|
||||
APPEND_CHAR((SQChar)(0xDC00 | (code & 0x3FF)));
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
APPEND_CHAR((SQChar)ch);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
SQInteger SQLexer::AddUTF8(SQUnsignedInteger ch)
|
||||
{
|
||||
if (ch < 0x80) {
|
||||
APPEND_CHAR((char)ch);
|
||||
return 1;
|
||||
}
|
||||
if (ch < 0x800) {
|
||||
APPEND_CHAR((SQChar)((ch >> 6) | 0xC0));
|
||||
APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80));
|
||||
return 2;
|
||||
}
|
||||
if (ch < 0x10000) {
|
||||
APPEND_CHAR((SQChar)((ch >> 12) | 0xE0));
|
||||
APPEND_CHAR((SQChar)(((ch >> 6) & 0x3F) | 0x80));
|
||||
APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80));
|
||||
return 3;
|
||||
}
|
||||
if (ch < 0x110000) {
|
||||
APPEND_CHAR((SQChar)((ch >> 18) | 0xF0));
|
||||
APPEND_CHAR((SQChar)(((ch >> 12) & 0x3F) | 0x80));
|
||||
APPEND_CHAR((SQChar)(((ch >> 6) & 0x3F) | 0x80));
|
||||
APPEND_CHAR((SQChar)((ch & 0x3F) | 0x80));
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
SQInteger SQLexer::ProcessStringHexEscape(SQChar *dest, SQInteger maxdigits)
|
||||
{
|
||||
NEXT();
|
||||
if (!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected"));
|
||||
SQInteger n = 0;
|
||||
while (isxdigit(CUR_CHAR) && n < maxdigits) {
|
||||
dest[n] = CUR_CHAR;
|
||||
n++;
|
||||
NEXT();
|
||||
}
|
||||
dest[n] = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)
|
||||
{
|
||||
INIT_TEMP_STRING();
|
||||
NEXT();
|
||||
if(IS_EOB()) return -1;
|
||||
for(;;) {
|
||||
while(CUR_CHAR != ndelim) {
|
||||
SQInteger x = CUR_CHAR;
|
||||
switch (x) {
|
||||
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();
|
||||
_currentline++;
|
||||
break;
|
||||
case _SC('\\'):
|
||||
if(verbatim) {
|
||||
APPEND_CHAR('\\'); NEXT();
|
||||
}
|
||||
else {
|
||||
NEXT();
|
||||
switch(CUR_CHAR) {
|
||||
case _SC('x'): {
|
||||
const SQInteger maxdigits = sizeof(SQChar) * 2;
|
||||
SQChar temp[maxdigits + 1];
|
||||
ProcessStringHexEscape(temp, maxdigits);
|
||||
SQChar *stemp;
|
||||
APPEND_CHAR((SQChar)scstrtoul(temp, &stemp, 16));
|
||||
}
|
||||
break;
|
||||
case _SC('U'):
|
||||
case _SC('u'): {
|
||||
const SQInteger maxdigits = x == 'u' ? 4 : 8;
|
||||
SQChar temp[8 + 1];
|
||||
ProcessStringHexEscape(temp, maxdigits);
|
||||
SQChar *stemp;
|
||||
#ifdef SQUNICODE
|
||||
#if WCHAR_SIZE == 2
|
||||
AddUTF16(scstrtoul(temp, &stemp, 16));
|
||||
#else
|
||||
ADD_CHAR((SQChar)scstrtoul(temp, &stemp, 16));
|
||||
#endif
|
||||
#else
|
||||
AddUTF8(scstrtoul(temp, &stemp, 16));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;
|
||||
case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;
|
||||
case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;
|
||||
case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;
|
||||
case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;
|
||||
case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;
|
||||
case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;
|
||||
case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;
|
||||
case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;
|
||||
case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
|
||||
case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
|
||||
default:
|
||||
Error(_SC("unrecognised escaper char"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
}
|
||||
}
|
||||
NEXT();
|
||||
if(verbatim && CUR_CHAR == '"') { //double quotation
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
TERMINATE_BUFFER();
|
||||
SQInteger len = _longstr.size()-1;
|
||||
if(ndelim == _SC('\'')) {
|
||||
if(len == 0) Error(_SC("empty constant"));
|
||||
if(len > 1) Error(_SC("constant too long"));
|
||||
_nvalue = _longstr[0];
|
||||
return TK_INTEGER;
|
||||
}
|
||||
_svalue = &_longstr[0];
|
||||
return TK_STRING_LITERAL;
|
||||
}
|
||||
|
||||
void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)
|
||||
{
|
||||
*res = 0;
|
||||
while(*s != 0)
|
||||
{
|
||||
if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0');
|
||||
else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);
|
||||
else { assert(0); }
|
||||
}
|
||||
}
|
||||
|
||||
void LexInteger(const SQChar *s,SQUnsignedInteger *res)
|
||||
{
|
||||
*res = 0;
|
||||
while(*s != 0)
|
||||
{
|
||||
*res = (*res)*10+((*s++)-'0');
|
||||
}
|
||||
}
|
||||
|
||||
SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); }
|
||||
|
||||
void LexOctal(const SQChar *s,SQUnsignedInteger *res)
|
||||
{
|
||||
*res = 0;
|
||||
while(*s != 0)
|
||||
{
|
||||
if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');
|
||||
else { assert(0); }
|
||||
}
|
||||
}
|
||||
|
||||
SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }
|
||||
|
||||
|
||||
#define MAX_HEX_DIGITS (sizeof(SQInteger)*2)
|
||||
SQInteger SQLexer::ReadNumber()
|
||||
{
|
||||
#define TINT 1
|
||||
#define TFLOAT 2
|
||||
#define THEX 3
|
||||
#define TSCIENTIFIC 4
|
||||
#define TOCTAL 5
|
||||
SQInteger type = TINT, firstchar = CUR_CHAR;
|
||||
SQChar *sTemp;
|
||||
INIT_TEMP_STRING();
|
||||
NEXT();
|
||||
if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) {
|
||||
if(scisodigit(CUR_CHAR)) {
|
||||
type = TOCTAL;
|
||||
while(scisodigit(CUR_CHAR)) {
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
}
|
||||
if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number"));
|
||||
}
|
||||
else {
|
||||
NEXT();
|
||||
type = THEX;
|
||||
while(isxdigit(CUR_CHAR)) {
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
}
|
||||
if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
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)) {
|
||||
if(type != TFLOAT) Error(_SC("invalid numeric format"));
|
||||
type = TSCIENTIFIC;
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
if(CUR_CHAR == '+' || CUR_CHAR == '-'){
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
}
|
||||
if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected"));
|
||||
}
|
||||
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
}
|
||||
}
|
||||
TERMINATE_BUFFER();
|
||||
switch(type) {
|
||||
case TSCIENTIFIC:
|
||||
case TFLOAT:
|
||||
_fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);
|
||||
return TK_FLOAT;
|
||||
case TINT:
|
||||
LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
|
||||
return TK_INTEGER;
|
||||
case THEX:
|
||||
LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
|
||||
return TK_INTEGER;
|
||||
case TOCTAL:
|
||||
LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
|
||||
return TK_INTEGER;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SQInteger SQLexer::ReadID()
|
||||
{
|
||||
SQInteger res;
|
||||
INIT_TEMP_STRING();
|
||||
do {
|
||||
APPEND_CHAR(CUR_CHAR);
|
||||
NEXT();
|
||||
} while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));
|
||||
TERMINATE_BUFFER();
|
||||
res = GetIDType(&_longstr[0],_longstr.size() - 1);
|
||||
if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {
|
||||
_svalue = &_longstr[0];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
55
dependencies/squirrel/squirrel/sqlexer.h
vendored
Normal file
55
dependencies/squirrel/squirrel/sqlexer.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQLEXER_H_
|
||||
#define _SQLEXER_H_
|
||||
|
||||
#ifdef SQUNICODE
|
||||
typedef SQChar LexChar;
|
||||
#else
|
||||
typedef unsigned char LexChar;
|
||||
#endif
|
||||
|
||||
struct SQLexer
|
||||
{
|
||||
SQLexer();
|
||||
~SQLexer();
|
||||
void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed);
|
||||
void Error(const SQChar *err);
|
||||
SQInteger Lex();
|
||||
const SQChar *Tok2Str(SQInteger tok);
|
||||
private:
|
||||
SQInteger GetIDType(const SQChar *s,SQInteger len);
|
||||
SQInteger ReadString(SQInteger ndelim,bool verbatim);
|
||||
SQInteger ReadNumber();
|
||||
void LexBlockComment();
|
||||
void LexLineComment();
|
||||
SQInteger ReadID();
|
||||
void Next();
|
||||
#ifdef SQUNICODE
|
||||
#if WCHAR_SIZE == 2
|
||||
SQInteger AddUTF16(SQUnsignedInteger ch);
|
||||
#endif
|
||||
#else
|
||||
SQInteger AddUTF8(SQUnsignedInteger ch);
|
||||
#endif
|
||||
SQInteger ProcessStringHexEscape(SQChar *dest, SQInteger maxdigits);
|
||||
SQInteger _curtoken;
|
||||
SQTable *_keywords;
|
||||
SQBool _reached_eof;
|
||||
public:
|
||||
SQInteger _prevtoken;
|
||||
SQInteger _currentline;
|
||||
SQInteger _lasttokenline;
|
||||
SQInteger _currentcolumn;
|
||||
const SQChar *_svalue;
|
||||
SQInteger _nvalue;
|
||||
SQFloat _fvalue;
|
||||
SQLEXREADFUNC _readf;
|
||||
SQUserPointer _up;
|
||||
LexChar _currdata;
|
||||
SQSharedState *_sharedstate;
|
||||
sqvector<SQChar> _longstr;
|
||||
CompilerErrorFunc _errfunc;
|
||||
void *_errtarget;
|
||||
};
|
||||
|
||||
#endif
|
||||
11
dependencies/squirrel/squirrel/sqmem.cpp
vendored
Normal file
11
dependencies/squirrel/squirrel/sqmem.cpp
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#ifndef SQ_EXCLUDE_DEFAULT_MEMFUNCTIONS
|
||||
void *sq_vm_malloc(SQUnsignedInteger size){ return malloc(size); }
|
||||
|
||||
void *sq_vm_realloc(void *p, SQUnsignedInteger SQ_UNUSED_ARG(oldsize), SQUnsignedInteger size){ return realloc(p, size); }
|
||||
|
||||
void sq_vm_free(void *p, SQUnsignedInteger SQ_UNUSED_ARG(size)){ free(p); }
|
||||
#endif
|
||||
677
dependencies/squirrel/squirrel/sqobject.cpp
vendored
Normal file
677
dependencies/squirrel/squirrel/sqobject.cpp
vendored
Normal file
@@ -0,0 +1,677 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#include "sqvm.h"
|
||||
#include "sqstring.h"
|
||||
#include "sqarray.h"
|
||||
#include "sqtable.h"
|
||||
#include "squserdata.h"
|
||||
#include "sqfuncproto.h"
|
||||
#include "sqclass.h"
|
||||
#include "sqclosure.h"
|
||||
|
||||
|
||||
const SQChar *IdType2Name(SQObjectType type)
|
||||
{
|
||||
switch(_RAW_TYPE(type))
|
||||
{
|
||||
case _RT_NULL:return _SC("null");
|
||||
case _RT_INTEGER:return _SC("integer");
|
||||
case _RT_FLOAT:return _SC("float");
|
||||
case _RT_BOOL:return _SC("bool");
|
||||
case _RT_STRING:return _SC("string");
|
||||
case _RT_TABLE:return _SC("table");
|
||||
case _RT_ARRAY:return _SC("array");
|
||||
case _RT_GENERATOR:return _SC("generator");
|
||||
case _RT_CLOSURE:
|
||||
case _RT_NATIVECLOSURE:
|
||||
return _SC("function");
|
||||
case _RT_USERDATA:
|
||||
case _RT_USERPOINTER:
|
||||
return _SC("userdata");
|
||||
case _RT_THREAD: return _SC("thread");
|
||||
case _RT_FUNCPROTO: return _SC("function");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const SQChar *GetTypeName(const SQObjectPtr &obj1)
|
||||
{
|
||||
return IdType2Name(type(obj1));
|
||||
}
|
||||
|
||||
SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
|
||||
{
|
||||
SQString *str=ADD_STRING(ss,s,len);
|
||||
return str;
|
||||
}
|
||||
|
||||
void SQString::Release()
|
||||
{
|
||||
REMOVE_STRING(_sharedstate,this);
|
||||
}
|
||||
|
||||
SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
|
||||
{
|
||||
SQInteger idx = (SQInteger)TranslateIndex(refpos);
|
||||
while(idx < _len){
|
||||
outkey = (SQInteger)idx;
|
||||
outval = (SQInteger)((SQUnsignedInteger)_val[idx]);
|
||||
//return idx for the next iteration
|
||||
return ++idx;
|
||||
}
|
||||
//nothing to iterate anymore
|
||||
return -1;
|
||||
}
|
||||
|
||||
SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx)
|
||||
{
|
||||
switch(type(idx)){
|
||||
case OT_NULL:
|
||||
return 0;
|
||||
case OT_INTEGER:
|
||||
return (SQUnsignedInteger)_integer(idx);
|
||||
default: assert(0); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type)
|
||||
{
|
||||
if(!_weakref) {
|
||||
sq_new(_weakref,SQWeakRef);
|
||||
#if defined(SQUSEDOUBLE) && !defined(_SQ64)
|
||||
_weakref->_obj._unVal.raw = 0; //clean the whole union on 32 bits with double
|
||||
#endif
|
||||
_weakref->_obj._type = type;
|
||||
_weakref->_obj._unVal.pRefCounted = this;
|
||||
}
|
||||
return _weakref;
|
||||
}
|
||||
|
||||
SQRefCounted::~SQRefCounted()
|
||||
{
|
||||
if(_weakref) {
|
||||
_weakref->_obj._type = OT_NULL;
|
||||
_weakref->_obj._unVal.pRefCounted = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SQWeakRef::Release() {
|
||||
if(ISREFCOUNTED(_obj._type)) {
|
||||
_obj._unVal.pRefCounted->_weakref = NULL;
|
||||
}
|
||||
sq_delete(this,SQWeakRef);
|
||||
}
|
||||
|
||||
bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) {
|
||||
if(_delegate) {
|
||||
return _delegate->Get((*_ss(v)->_metamethods)[mm],res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SQDelegable::SetDelegate(SQTable *mt)
|
||||
{
|
||||
SQTable *temp = mt;
|
||||
if(temp == this) return false;
|
||||
while (temp) {
|
||||
if (temp->_delegate == this) return false; //cycle detected
|
||||
temp = temp->_delegate;
|
||||
}
|
||||
if (mt) __ObjAddRef(mt);
|
||||
__ObjRelease(_delegate);
|
||||
_delegate = mt;
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
_stack.resize(size);
|
||||
SQObject _this = v->_stack[v->_stackbase];
|
||||
_stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;
|
||||
for(SQInteger n =1; n<target; n++) {
|
||||
_stack._vals[n] = v->_stack[v->_stackbase+n];
|
||||
}
|
||||
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());
|
||||
v->_etraps.pop_back();
|
||||
// store relative stack base and size in case of resume to other _top
|
||||
SQExceptionTrap &et = _etraps.back();
|
||||
et._stackbase -= v->_stackbase;
|
||||
et._stacksize -= v->_stackbase;
|
||||
}
|
||||
_state=eSuspended;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest)
|
||||
{
|
||||
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 size = _stack.size();
|
||||
SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]);
|
||||
assert(target>=0 && target<=255);
|
||||
SQInteger newbase = v->_top;
|
||||
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();
|
||||
SQExceptionTrap &et = v->_etraps.back();
|
||||
// restore absolute stack base and size
|
||||
et._stackbase += newbase;
|
||||
et._stacksize += newbase;
|
||||
}
|
||||
SQObject _this = _stack._vals[0];
|
||||
v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;
|
||||
|
||||
for(SQInteger n = 1; n<size; n++) {
|
||||
v->_stack[v->_stackbase+n] = _stack._vals[n];
|
||||
_stack._vals[n].Null();
|
||||
}
|
||||
|
||||
_state=eRunning;
|
||||
if (v->_debughook)
|
||||
v->CallDebugHook(_SC('c'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SQArray::Extend(const SQArray *a){
|
||||
SQInteger xlen;
|
||||
if((xlen=a->Size()))
|
||||
for(SQInteger i=0;i<xlen;i++)
|
||||
Append(a->_values[i]);
|
||||
}
|
||||
|
||||
const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)
|
||||
{
|
||||
SQUnsignedInteger nvars=_nlocalvarinfos;
|
||||
const SQChar *res=NULL;
|
||||
if(nvars>=nseq){
|
||||
for(SQUnsignedInteger i=0;i<nvars;i++){
|
||||
if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
|
||||
{
|
||||
if(nseq==0){
|
||||
vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
|
||||
res=_stringval(_localvarinfos[i]._name);
|
||||
break;
|
||||
}
|
||||
nseq--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
SQInteger SQFunctionProto::GetLine(SQInstruction *curr)
|
||||
{
|
||||
SQInteger op = (SQInteger)(curr-_instructions);
|
||||
SQInteger line=_lineinfos[0]._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;
|
||||
}
|
||||
}
|
||||
|
||||
while(mid > 0 && _lineinfos[mid]._op >= op) mid--;
|
||||
|
||||
line = _lineinfos[mid]._line;
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
SQClosure::~SQClosure()
|
||||
{
|
||||
__ObjRelease(_root);
|
||||
__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)
|
||||
{
|
||||
if(write(up,dest,size) != size) {
|
||||
v->Raise_Error(_SC("io error (write function failure)"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)
|
||||
{
|
||||
if(size && read(up,dest,size) != size) {
|
||||
v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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,SQUnsignedInteger32 tag)
|
||||
{
|
||||
SQUnsignedInteger32 t;
|
||||
_CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
|
||||
if(t != tag){
|
||||
v->Raise_Error(_SC("invalid or corrupted closure stream"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
|
||||
{
|
||||
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)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,_stringval(o),sq_rsl(_string(o)->_len)));
|
||||
break;
|
||||
case OT_BOOL:
|
||||
case OT_INTEGER:
|
||||
_CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
|
||||
case OT_FLOAT:
|
||||
_CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;
|
||||
case OT_NULL:
|
||||
break;
|
||||
default:
|
||||
v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
|
||||
{
|
||||
SQUnsignedInteger32 _type;
|
||||
_CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
|
||||
SQObjectType t = (SQObjectType)_type;
|
||||
switch(t){
|
||||
case OT_STRING:{
|
||||
SQInteger len;
|
||||
_CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));
|
||||
_CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(sq_rsl(len)),sq_rsl(len)));
|
||||
o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);
|
||||
}
|
||||
break;
|
||||
case OT_INTEGER:{
|
||||
SQInteger i;
|
||||
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;
|
||||
}
|
||||
case OT_BOOL:{
|
||||
SQInteger i;
|
||||
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;
|
||||
}
|
||||
case OT_FLOAT:{
|
||||
SQFloat f;
|
||||
_CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;
|
||||
}
|
||||
case OT_NULL:
|
||||
o.Null();
|
||||
break;
|
||||
default:
|
||||
v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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(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;
|
||||
}
|
||||
|
||||
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));
|
||||
ret = SQClosure::Create(_ss(v),_funcproto(func),_table(v->_roottable)->GetWeakRef(OT_TABLE));
|
||||
//FIXME: load an root for this closure
|
||||
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;
|
||||
SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
|
||||
SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
|
||||
SQInteger ndefaultparams = _ndefaultparams;
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(WriteObject(v,up,write,_sourcename));
|
||||
_CHECK_IO(WriteObject(v,up,write,_name));
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
for(i=0;i<nliterals;i++){
|
||||
_CHECK_IO(WriteObject(v,up,write,_literals[i]));
|
||||
}
|
||||
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
for(i=0;i<nparameters;i++){
|
||||
_CHECK_IO(WriteObject(v,up,write,_parameters[i]));
|
||||
}
|
||||
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
for(i=0;i<noutervalues;i++){
|
||||
_CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));
|
||||
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
|
||||
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
|
||||
}
|
||||
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
for(i=0;i<nlocalvarinfos;i++){
|
||||
SQLocalVarInfo &lvi=_localvarinfos[i];
|
||||
_CHECK_IO(WriteObject(v,up,write,lvi._name));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(SQUnsignedInteger)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));
|
||||
}
|
||||
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));
|
||||
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(SQInteger)*ndefaultparams));
|
||||
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));
|
||||
|
||||
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
|
||||
for(i=0;i<nfunctions;i++){
|
||||
_CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
|
||||
}
|
||||
_CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
|
||||
_CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
|
||||
{
|
||||
SQInteger i, nliterals,nparameters;
|
||||
SQInteger noutervalues ,nlocalvarinfos ;
|
||||
SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
|
||||
SQObjectPtr sourcename, name;
|
||||
SQObjectPtr o;
|
||||
_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)));
|
||||
_CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
|
||||
_CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
|
||||
_CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
|
||||
_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(_opt_ss(v),ninstructions,nliterals,nparameters,
|
||||
nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
|
||||
SQObjectPtr proto = f; //gets a ref in case of failure
|
||||
f->_sourcename = sourcename;
|
||||
f->_name = name;
|
||||
|
||||
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
|
||||
for(i = 0;i < nliterals; i++){
|
||||
_CHECK_IO(ReadObject(v, up, read, o));
|
||||
f->_literals[i] = o;
|
||||
}
|
||||
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
|
||||
for(i = 0; i < nparameters; i++){
|
||||
_CHECK_IO(ReadObject(v, up, read, o));
|
||||
f->_parameters[i] = o;
|
||||
}
|
||||
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
|
||||
for(i = 0; i < noutervalues; i++){
|
||||
SQUnsignedInteger type;
|
||||
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(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
|
||||
for(i = 0; i < nlocalvarinfos; i++){
|
||||
SQLocalVarInfo lvi;
|
||||
_CHECK_IO(ReadObject(v, up, read, lvi._name));
|
||||
_CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger)));
|
||||
_CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger)));
|
||||
_CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger)));
|
||||
f->_localvarinfos[i] = lvi;
|
||||
}
|
||||
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));
|
||||
|
||||
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams));
|
||||
|
||||
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
_CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));
|
||||
|
||||
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
|
||||
for(i = 0; i < nfunctions; i++){
|
||||
_CHECK_IO(_funcproto(o)->Load(v, up, read, o));
|
||||
f->_functions[i] = o;
|
||||
}
|
||||
_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;
|
||||
}
|
||||
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
|
||||
#define START_MARK() if(!(_uiRef&MARK_FLAG)){ \
|
||||
_uiRef|=MARK_FLAG;
|
||||
|
||||
#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \
|
||||
AddToChain(chain, this); }
|
||||
|
||||
void SQVM::Mark(SQCollectable **chain)
|
||||
{
|
||||
START_MARK()
|
||||
SQSharedState::MarkObject(_lasterror,chain);
|
||||
SQSharedState::MarkObject(_errorhandler,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(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);
|
||||
END_MARK()
|
||||
}
|
||||
|
||||
void SQArray::Mark(SQCollectable **chain)
|
||||
{
|
||||
START_MARK()
|
||||
SQInteger len = _values.size();
|
||||
for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);
|
||||
END_MARK()
|
||||
}
|
||||
void SQTable::Mark(SQCollectable **chain)
|
||||
{
|
||||
START_MARK()
|
||||
if(_delegate) _delegate->Mark(chain);
|
||||
SQInteger len = _numofnodes;
|
||||
for(SQInteger i = 0; i < len; i++){
|
||||
SQSharedState::MarkObject(_nodes[i].key, chain);
|
||||
SQSharedState::MarkObject(_nodes[i].val, chain);
|
||||
}
|
||||
END_MARK()
|
||||
}
|
||||
|
||||
void SQClass::Mark(SQCollectable **chain)
|
||||
{
|
||||
START_MARK()
|
||||
_members->Mark(chain);
|
||||
if(_base) _base->Mark(chain);
|
||||
SQSharedState::MarkObject(_attributes, chain);
|
||||
for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) {
|
||||
SQSharedState::MarkObject(_defaultvalues[i].val, chain);
|
||||
SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);
|
||||
}
|
||||
for(SQUnsignedInteger j =0; j< _methods.size(); j++) {
|
||||
SQSharedState::MarkObject(_methods[j].val, chain);
|
||||
SQSharedState::MarkObject(_methods[j].attrs, chain);
|
||||
}
|
||||
for(SQUnsignedInteger k =0; k< MT_LAST; k++) {
|
||||
SQSharedState::MarkObject(_metamethods[k], chain);
|
||||
}
|
||||
END_MARK()
|
||||
}
|
||||
|
||||
void SQInstance::Mark(SQCollectable **chain)
|
||||
{
|
||||
START_MARK()
|
||||
_class->Mark(chain);
|
||||
SQUnsignedInteger nvalues = _class->_defaultvalues.size();
|
||||
for(SQUnsignedInteger i =0; i< nvalues; i++) {
|
||||
SQSharedState::MarkObject(_values[i], chain);
|
||||
}
|
||||
END_MARK()
|
||||
}
|
||||
|
||||
void SQGenerator::Mark(SQCollectable **chain)
|
||||
{
|
||||
START_MARK()
|
||||
for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], 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()
|
||||
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 < _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()
|
||||
}
|
||||
|
||||
void SQUserData::Mark(SQCollectable **chain){
|
||||
START_MARK()
|
||||
if(_delegate) _delegate->Mark(chain);
|
||||
END_MARK()
|
||||
}
|
||||
|
||||
void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
|
||||
|
||||
#endif
|
||||
|
||||
354
dependencies/squirrel/squirrel/sqobject.h
vendored
Normal file
354
dependencies/squirrel/squirrel/sqobject.h
vendored
Normal file
@@ -0,0 +1,354 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQOBJECT_H_
|
||||
#define _SQOBJECT_H_
|
||||
|
||||
#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'))
|
||||
|
||||
struct SQSharedState;
|
||||
|
||||
enum SQMetaMethod{
|
||||
MT_ADD=0,
|
||||
MT_SUB=1,
|
||||
MT_MUL=2,
|
||||
MT_DIV=3,
|
||||
MT_UNM=4,
|
||||
MT_MODULO=5,
|
||||
MT_SET=6,
|
||||
MT_GET=7,
|
||||
MT_TYPEOF=8,
|
||||
MT_NEXTI=9,
|
||||
MT_CMP=10,
|
||||
MT_CALL=11,
|
||||
MT_CLONED=12,
|
||||
MT_NEWSLOT=13,
|
||||
MT_DELSLOT=14,
|
||||
MT_TOSTRING=15,
|
||||
MT_NEWMEMBER=16,
|
||||
MT_INHERITED=17,
|
||||
MT_LAST = 18
|
||||
};
|
||||
|
||||
#define MM_ADD _SC("_add")
|
||||
#define MM_SUB _SC("_sub")
|
||||
#define MM_MUL _SC("_mul")
|
||||
#define MM_DIV _SC("_div")
|
||||
#define MM_UNM _SC("_unm")
|
||||
#define MM_MODULO _SC("_modulo")
|
||||
#define MM_SET _SC("_set")
|
||||
#define MM_GET _SC("_get")
|
||||
#define MM_TYPEOF _SC("_typeof")
|
||||
#define MM_NEXTI _SC("_nexti")
|
||||
#define MM_CMP _SC("_cmp")
|
||||
#define MM_CALL _SC("_call")
|
||||
#define MM_CLONED _SC("_cloned")
|
||||
#define MM_NEWSLOT _SC("_newslot")
|
||||
#define MM_DELSLOT _SC("_delslot")
|
||||
#define MM_TOSTRING _SC("_tostring")
|
||||
#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);
|
||||
virtual void Release()=0;
|
||||
|
||||
};
|
||||
|
||||
struct SQWeakRef : SQRefCounted
|
||||
{
|
||||
void Release();
|
||||
SQObject _obj;
|
||||
};
|
||||
|
||||
#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)
|
||||
|
||||
struct SQObjectPtr;
|
||||
|
||||
#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \
|
||||
{ \
|
||||
unval.pRefCounted->_uiRef++; \
|
||||
}
|
||||
|
||||
#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0)) \
|
||||
{ \
|
||||
unval.pRefCounted->Release(); \
|
||||
}
|
||||
|
||||
#define __ObjRelease(obj) { \
|
||||
if((obj)) { \
|
||||
(obj)->_uiRef--; \
|
||||
if((obj)->_uiRef == 0) \
|
||||
(obj)->Release(); \
|
||||
(obj) = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define __ObjAddRef(obj) { \
|
||||
(obj)->_uiRef++; \
|
||||
}
|
||||
|
||||
#define type(obj) ((obj)._type)
|
||||
#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)
|
||||
#define raw_type(obj) _RAW_TYPE((obj)._type)
|
||||
|
||||
#define _integer(obj) ((obj)._unVal.nInteger)
|
||||
#define _float(obj) ((obj)._unVal.fFloat)
|
||||
#define _string(obj) ((obj)._unVal.pString)
|
||||
#define _table(obj) ((obj)._unVal.pTable)
|
||||
#define _array(obj) ((obj)._unVal.pArray)
|
||||
#define _closure(obj) ((obj)._unVal.pClosure)
|
||||
#define _generator(obj) ((obj)._unVal.pGenerator)
|
||||
#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)
|
||||
#define _userdata(obj) ((obj)._unVal.pUserData)
|
||||
#define _userpointer(obj) ((obj)._unVal.pUserPointer)
|
||||
#define _thread(obj) ((obj)._unVal.pThread)
|
||||
#define _funcproto(obj) ((obj)._unVal.pFunctionProto)
|
||||
#define _class(obj) ((obj)._unVal.pClass)
|
||||
#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) ((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))
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
#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()
|
||||
{
|
||||
SQ_OBJECT_RAWINIT()
|
||||
_type=OT_NULL;
|
||||
_unVal.pUserPointer=NULL;
|
||||
}
|
||||
SQObjectPtr(const SQObjectPtr &o)
|
||||
{
|
||||
_type = o._type;
|
||||
_unVal = o._unVal;
|
||||
__AddRef(_type,_unVal);
|
||||
}
|
||||
SQObjectPtr(const SQObject &o)
|
||||
{
|
||||
_type = o._type;
|
||||
_unVal = o._unVal;
|
||||
__AddRef(_type,_unVal);
|
||||
}
|
||||
_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;
|
||||
}
|
||||
inline SQObjectPtr& operator=(bool b)
|
||||
{
|
||||
__Release(_type,_unVal);
|
||||
SQ_OBJECT_RAWINIT()
|
||||
_type = OT_BOOL;
|
||||
_unVal.nInteger = b?1:0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SQObjectPtr()
|
||||
{
|
||||
__Release(_type,_unVal);
|
||||
}
|
||||
|
||||
inline SQObjectPtr& operator=(const SQObjectPtr& obj)
|
||||
{
|
||||
SQObjectType tOldType;
|
||||
SQObjectValue unOldVal;
|
||||
tOldType=_type;
|
||||
unOldVal=_unVal;
|
||||
_unVal = obj._unVal;
|
||||
_type = obj._type;
|
||||
__AddRef(_type,_unVal);
|
||||
__Release(tOldType,unOldVal);
|
||||
return *this;
|
||||
}
|
||||
inline SQObjectPtr& operator=(const SQObject& obj)
|
||||
{
|
||||
SQObjectType tOldType;
|
||||
SQObjectValue unOldVal;
|
||||
tOldType=_type;
|
||||
unOldVal=_unVal;
|
||||
_unVal = obj._unVal;
|
||||
_type = obj._type;
|
||||
__AddRef(_type,_unVal);
|
||||
__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;
|
||||
SQObjectValue unOldVal = a._unVal;
|
||||
a._type = b._type;
|
||||
a._unVal = b._unVal;
|
||||
b._type = tOldType;
|
||||
b._unVal = unOldVal;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
#define MARK_FLAG 0x80000000
|
||||
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();
|
||||
virtual void Finalize()=0;
|
||||
static void AddToChain(SQCollectable **chain,SQCollectable *c);
|
||||
static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);
|
||||
};
|
||||
|
||||
|
||||
#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
|
||||
#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
|
||||
#define CHAINABLE_OBJ SQCollectable
|
||||
#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
|
||||
#else
|
||||
|
||||
#define ADD_TO_CHAIN(chain,obj) ((void)0)
|
||||
#define REMOVE_FROM_CHAIN(chain,obj) ((void)0)
|
||||
#define CHAINABLE_OBJ SQRefCounted
|
||||
#define INIT_CHAIN() ((void)0)
|
||||
#endif
|
||||
|
||||
struct SQDelegable : public CHAINABLE_OBJ {
|
||||
bool SetDelegate(SQTable *m);
|
||||
virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
|
||||
SQTable *_delegate;
|
||||
};
|
||||
|
||||
SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
|
||||
typedef sqvector<SQObjectPtr> SQObjectPtrVec;
|
||||
typedef sqvector<SQInteger> SQIntVec;
|
||||
const SQChar *GetTypeName(const SQObjectPtr &obj1);
|
||||
const SQChar *IdType2Name(SQObjectType type);
|
||||
|
||||
|
||||
|
||||
#endif //_SQOBJECT_H_
|
||||
132
dependencies/squirrel/squirrel/sqopcodes.h
vendored
Normal file
132
dependencies/squirrel/squirrel/sqopcodes.h
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQOPCODES_H_
|
||||
#define _SQOPCODES_H_
|
||||
|
||||
#define MAX_FUNC_STACKSIZE 0xFF
|
||||
#define MAX_LITERALS ((SQInteger)0x7FFFFFFF)
|
||||
|
||||
enum BitWiseOP {
|
||||
BW_AND = 0,
|
||||
BW_OR = 2,
|
||||
BW_XOR = 3,
|
||||
BW_SHIFTL = 4,
|
||||
BW_SHIFTR = 5,
|
||||
BW_USHIFTR = 6
|
||||
};
|
||||
|
||||
enum CmpOP {
|
||||
CMP_G = 0,
|
||||
CMP_GE = 2,
|
||||
CMP_L = 3,
|
||||
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,
|
||||
_OP_LOAD= 0x01,
|
||||
_OP_LOADINT= 0x02,
|
||||
_OP_LOADFLOAT= 0x03,
|
||||
_OP_DLOAD= 0x04,
|
||||
_OP_TAILCALL= 0x05,
|
||||
_OP_CALL= 0x06,
|
||||
_OP_PREPCALL= 0x07,
|
||||
_OP_PREPCALLK= 0x08,
|
||||
_OP_GETK= 0x09,
|
||||
_OP_MOVE= 0x0A,
|
||||
_OP_NEWSLOT= 0x0B,
|
||||
_OP_DELETE= 0x0C,
|
||||
_OP_SET= 0x0D,
|
||||
_OP_GET= 0x0E,
|
||||
_OP_EQ= 0x0F,
|
||||
_OP_NE= 0x10,
|
||||
_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,
|
||||
_OP_PINCL= 0x27,
|
||||
_OP_CMP= 0x28,
|
||||
_OP_EXISTS= 0x29,
|
||||
_OP_INSTANCEOF= 0x2A,
|
||||
_OP_AND= 0x2B,
|
||||
_OP_OR= 0x2C,
|
||||
_OP_NEG= 0x2D,
|
||||
_OP_NOT= 0x2E,
|
||||
_OP_BWNOT= 0x2F,
|
||||
_OP_CLOSURE= 0x30,
|
||||
_OP_YIELD= 0x31,
|
||||
_OP_RESUME= 0x32,
|
||||
_OP_FOREACH= 0x33,
|
||||
_OP_POSTFOREACH= 0x34,
|
||||
_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 {
|
||||
const SQChar *name;
|
||||
};
|
||||
|
||||
struct SQInstruction
|
||||
{
|
||||
SQInstruction(){};
|
||||
SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0)
|
||||
{ op = (unsigned char)_op;
|
||||
_arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1;
|
||||
_arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3;
|
||||
}
|
||||
|
||||
|
||||
SQInt32 _arg1;
|
||||
unsigned char op;
|
||||
unsigned char _arg0;
|
||||
unsigned char _arg2;
|
||||
unsigned char _arg3;
|
||||
};
|
||||
|
||||
#include "squtils.h"
|
||||
typedef sqvector<SQInstruction> SQInstructionVec;
|
||||
|
||||
#define NEW_SLOT_ATTRIBUTES_FLAG 0x01
|
||||
#define NEW_SLOT_STATIC_FLAG 0x02
|
||||
|
||||
#endif // _SQOPCODES_H_
|
||||
20
dependencies/squirrel/squirrel/sqpcheader.h
vendored
Normal file
20
dependencies/squirrel/squirrel/sqpcheader.h
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQPCHEADER_H_
|
||||
#define _SQPCHEADER_H_
|
||||
|
||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <new>
|
||||
//squirrel stuff
|
||||
#include <squirrel.h>
|
||||
#include "sqobject.h"
|
||||
#include "sqstate.h"
|
||||
|
||||
#endif //_SQPCHEADER_H_
|
||||
657
dependencies/squirrel/squirrel/sqstate.cpp
vendored
Normal file
657
dependencies/squirrel/squirrel/sqstate.cpp
vendored
Normal file
@@ -0,0 +1,657 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#include "sqopcodes.h"
|
||||
#include "sqvm.h"
|
||||
#include "sqfuncproto.h"
|
||||
#include "sqclosure.h"
|
||||
#include "sqstring.h"
|
||||
#include "sqtable.h"
|
||||
#include "sqarray.h"
|
||||
#include "squserdata.h"
|
||||
#include "sqclass.h"
|
||||
|
||||
//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;
|
||||
_foreignptr = NULL;
|
||||
_releasehook = NULL;
|
||||
}
|
||||
|
||||
#define newsysstring(s) { \
|
||||
_systemstrings->push_back(SQString::Create(this,s)); \
|
||||
}
|
||||
|
||||
#define newmetamethod(s) { \
|
||||
_metamethods->push_back(SQString::Create(this,s)); \
|
||||
_table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
|
||||
}
|
||||
|
||||
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;
|
||||
case 'f': mask |= _RT_FLOAT; break;
|
||||
case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
|
||||
case 's': mask |= _RT_STRING; break;
|
||||
case 't': mask |= _RT_TABLE; break;
|
||||
case 'a': mask |= _RT_ARRAY; break;
|
||||
case 'u': mask |= _RT_USERDATA; break;
|
||||
case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
|
||||
case 'b': mask |= _RT_BOOL; break;
|
||||
case 'g': mask |= _RT_GENERATOR; break;
|
||||
case 'p': mask |= _RT_USERPOINTER; break;
|
||||
case 'v': mask |= _RT_THREAD; break;
|
||||
case 'x': mask |= _RT_INSTANCE; break;
|
||||
case 'y': mask |= _RT_CLASS; break;
|
||||
case 'r': mask |= _RT_WEAKREF; break;
|
||||
case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
|
||||
case ' ': i++; continue; //ignores spaces
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
if(typemask[i] == '|') {
|
||||
i++;
|
||||
if(typemask[i] == 0)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
res.push_back(mask);
|
||||
mask = 0;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SQTable *CreateDefaultDelegate(SQSharedState *ss,const SQRegFunction *funcz)
|
||||
{
|
||||
SQInteger i=0;
|
||||
SQTable *t=SQTable::Create(ss,0);
|
||||
while(funcz[i].name!=0){
|
||||
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))
|
||||
return NULL;
|
||||
t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
|
||||
i++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void SQSharedState::Init()
|
||||
{
|
||||
_scratchpad=NULL;
|
||||
_scratchpadsize=0;
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
_gc_chain=NULL;
|
||||
#endif
|
||||
_stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable));
|
||||
new (_stringtable) SQStringTable(this);
|
||||
sq_new(_metamethods,SQObjectPtrVec);
|
||||
sq_new(_systemstrings,SQObjectPtrVec);
|
||||
sq_new(_types,SQObjectPtrVec);
|
||||
_metamethodsmap = SQTable::Create(this,MT_LAST-1);
|
||||
//adding type strings to avoid memory trashing
|
||||
//types names
|
||||
newsysstring(_SC("null"));
|
||||
newsysstring(_SC("table"));
|
||||
newsysstring(_SC("array"));
|
||||
newsysstring(_SC("closure"));
|
||||
newsysstring(_SC("string"));
|
||||
newsysstring(_SC("userdata"));
|
||||
newsysstring(_SC("integer"));
|
||||
newsysstring(_SC("float"));
|
||||
newsysstring(_SC("userpointer"));
|
||||
newsysstring(_SC("function"));
|
||||
newsysstring(_SC("generator"));
|
||||
newsysstring(_SC("thread"));
|
||||
newsysstring(_SC("class"));
|
||||
newsysstring(_SC("instance"));
|
||||
newsysstring(_SC("bool"));
|
||||
//meta methods
|
||||
newmetamethod(MM_ADD);
|
||||
newmetamethod(MM_SUB);
|
||||
newmetamethod(MM_MUL);
|
||||
newmetamethod(MM_DIV);
|
||||
newmetamethod(MM_UNM);
|
||||
newmetamethod(MM_MODULO);
|
||||
newmetamethod(MM_SET);
|
||||
newmetamethod(MM_GET);
|
||||
newmetamethod(MM_TYPEOF);
|
||||
newmetamethod(MM_NEXTI);
|
||||
newmetamethod(MM_CMP);
|
||||
newmetamethod(MM_CALL);
|
||||
newmetamethod(MM_CLONED);
|
||||
newmetamethod(MM_NEWSLOT);
|
||||
newmetamethod(MM_DELSLOT);
|
||||
newmetamethod(MM_TOSTRING);
|
||||
newmetamethod(MM_NEWMEMBER);
|
||||
newmetamethod(MM_INHERITED);
|
||||
|
||||
_constructoridx = SQString::Create(this,_SC("constructor"));
|
||||
_registry = SQTable::Create(this,0);
|
||||
_consts = SQTable::Create(this,0);
|
||||
_table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);
|
||||
_array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);
|
||||
_string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);
|
||||
_number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);
|
||||
_closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);
|
||||
_generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz);
|
||||
_thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz);
|
||||
_class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz);
|
||||
_instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz);
|
||||
_weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
|
||||
|
||||
}
|
||||
|
||||
SQSharedState::~SQSharedState()
|
||||
{
|
||||
if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; }
|
||||
_constructoridx.Null();
|
||||
_table(_registry)->Finalize();
|
||||
_table(_consts)->Finalize();
|
||||
_table(_metamethodsmap)->Finalize();
|
||||
_registry.Null();
|
||||
_consts.Null();
|
||||
_metamethodsmap.Null();
|
||||
while(!_systemstrings->empty()) {
|
||||
_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();
|
||||
_refs_table.Finalize();
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
SQCollectable *t = _gc_chain;
|
||||
SQCollectable *nx = NULL;
|
||||
if(t) {
|
||||
t->_uiRef++;
|
||||
while(t) {
|
||||
t->Finalize();
|
||||
nx = t->_next;
|
||||
if(nx) nx->_uiRef++;
|
||||
if(--t->_uiRef == 0)
|
||||
t->Release();
|
||||
t = nx;
|
||||
}
|
||||
}
|
||||
assert(_gc_chain==NULL); //just to proove a theory
|
||||
while(_gc_chain){
|
||||
_gc_chain->_uiRef++;
|
||||
_gc_chain->Release();
|
||||
}
|
||||
#endif
|
||||
|
||||
sq_delete(_types,SQObjectPtrVec);
|
||||
sq_delete(_systemstrings,SQObjectPtrVec);
|
||||
sq_delete(_metamethods,SQObjectPtrVec);
|
||||
sq_delete(_stringtable,SQStringTable);
|
||||
if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
|
||||
}
|
||||
|
||||
|
||||
SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
|
||||
{
|
||||
if(type(name) != OT_STRING)
|
||||
return -1;
|
||||
SQObjectPtr ret;
|
||||
if(_table(_metamethodsmap)->Get(name,ret)) {
|
||||
return _integer(ret);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
|
||||
void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
|
||||
{
|
||||
switch(type(o)){
|
||||
case OT_TABLE:_table(o)->Mark(chain);break;
|
||||
case OT_ARRAY:_array(o)->Mark(chain);break;
|
||||
case OT_USERDATA:_userdata(o)->Mark(chain);break;
|
||||
case OT_CLOSURE:_closure(o)->Mark(chain);break;
|
||||
case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
|
||||
case OT_GENERATOR:_generator(o)->Mark(chain);break;
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
void SQSharedState::RunMark(SQVM SQ_UNUSED_ARG(*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;
|
||||
|
||||
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;
|
||||
if(t) {
|
||||
t->_uiRef++;
|
||||
while(t) {
|
||||
t->Finalize();
|
||||
nx = t->_next;
|
||||
if(nx) nx->_uiRef++;
|
||||
if(--t->_uiRef == 0)
|
||||
t->Release();
|
||||
t = nx;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
t = tchain;
|
||||
while(t) {
|
||||
t->UnMark();
|
||||
t = t->_next;
|
||||
}
|
||||
_gc_chain = tchain;
|
||||
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
|
||||
{
|
||||
c->_prev = NULL;
|
||||
c->_next = *chain;
|
||||
if(*chain) (*chain)->_prev = c;
|
||||
*chain = c;
|
||||
}
|
||||
|
||||
void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
|
||||
{
|
||||
if(c->_prev) c->_prev->_next = c->_next;
|
||||
else *chain = c->_next;
|
||||
if(c->_next)
|
||||
c->_next->_prev = c->_prev;
|
||||
c->_next = NULL;
|
||||
c->_prev = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
SQChar* SQSharedState::GetScratchPad(SQInteger size)
|
||||
{
|
||||
SQInteger newsize;
|
||||
if(size>0) {
|
||||
if(_scratchpadsize < size) {
|
||||
newsize = size + (size>>1);
|
||||
_scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
|
||||
_scratchpadsize = newsize;
|
||||
|
||||
}else if(_scratchpadsize >= (size<<5)) {
|
||||
newsize = _scratchpadsize >> 1;
|
||||
_scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
|
||||
_scratchpadsize = newsize;
|
||||
}
|
||||
}
|
||||
return _scratchpad;
|
||||
}
|
||||
|
||||
RefTable::RefTable()
|
||||
{
|
||||
AllocNodes(4);
|
||||
}
|
||||
|
||||
void RefTable::Finalize()
|
||||
{
|
||||
RefNode *nodes = _nodes;
|
||||
for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
|
||||
nodes->obj.Null();
|
||||
nodes++;
|
||||
}
|
||||
}
|
||||
|
||||
RefTable::~RefTable()
|
||||
{
|
||||
SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
|
||||
}
|
||||
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
void RefTable::Mark(SQCollectable **chain)
|
||||
{
|
||||
RefNode *nodes = (RefNode *)_nodes;
|
||||
for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
|
||||
if(type(nodes->obj) != OT_NULL) {
|
||||
SQSharedState::MarkObject(nodes->obj,chain);
|
||||
}
|
||||
nodes++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void RefTable::AddRef(SQObject &obj)
|
||||
{
|
||||
SQHash mainpos;
|
||||
RefNode *prev;
|
||||
RefNode *ref = Get(obj,mainpos,&prev,true);
|
||||
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;
|
||||
RefNode *prev;
|
||||
RefNode *ref = Get(obj,mainpos,&prev,false);
|
||||
if(ref) {
|
||||
if(--ref->refs == 0) {
|
||||
SQObjectPtr o = ref->obj;
|
||||
if(prev) {
|
||||
prev->next = ref->next;
|
||||
}
|
||||
else {
|
||||
_buckets[mainpos] = ref->next;
|
||||
}
|
||||
ref->next = _freelist;
|
||||
_freelist = ref;
|
||||
_slotused--;
|
||||
ref->obj.Null();
|
||||
//<<FIXME>>test for shrink?
|
||||
return SQTrue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
return SQFalse;
|
||||
}
|
||||
|
||||
void RefTable::Resize(SQUnsignedInteger size)
|
||||
{
|
||||
RefNode **oldbucks = _buckets;
|
||||
RefNode *t = _nodes;
|
||||
SQUnsignedInteger oldnumofslots = _numofslots;
|
||||
AllocNodes(size);
|
||||
//rehash
|
||||
SQUnsignedInteger nfound = 0;
|
||||
for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
|
||||
if(type(t->obj) != OT_NULL) {
|
||||
//add back;
|
||||
assert(t->refs != 0);
|
||||
RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
|
||||
nn->refs = t->refs;
|
||||
t->obj.Null();
|
||||
nfound++;
|
||||
}
|
||||
t++;
|
||||
}
|
||||
assert(nfound == oldnumofslots);
|
||||
SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
|
||||
}
|
||||
|
||||
RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
|
||||
{
|
||||
RefNode *t = _buckets[mainpos];
|
||||
RefNode *newnode = _freelist;
|
||||
newnode->obj = obj;
|
||||
_buckets[mainpos] = newnode;
|
||||
_freelist = _freelist->next;
|
||||
newnode->next = t;
|
||||
assert(newnode->refs == 0);
|
||||
_slotused++;
|
||||
return newnode;
|
||||
}
|
||||
|
||||
RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
|
||||
{
|
||||
RefNode *ref;
|
||||
mainpos = ::HashObj(obj)&(_numofslots-1);
|
||||
*prev = NULL;
|
||||
for (ref = _buckets[mainpos]; ref; ) {
|
||||
if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
|
||||
break;
|
||||
*prev = ref;
|
||||
ref = ref->next;
|
||||
}
|
||||
if(ref == NULL && add) {
|
||||
if(_numofslots == _slotused) {
|
||||
assert(_freelist == 0);
|
||||
Resize(_numofslots*2);
|
||||
mainpos = ::HashObj(obj)&(_numofslots-1);
|
||||
}
|
||||
ref = Add(mainpos,obj);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
void RefTable::AllocNodes(SQUnsignedInteger size)
|
||||
{
|
||||
RefNode **bucks;
|
||||
RefNode *nodes;
|
||||
bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));
|
||||
nodes = (RefNode *)&bucks[size];
|
||||
RefNode *temp = nodes;
|
||||
SQUnsignedInteger n;
|
||||
for(n = 0; n < size - 1; n++) {
|
||||
bucks[n] = NULL;
|
||||
temp->refs = 0;
|
||||
new (&temp->obj) SQObjectPtr;
|
||||
temp->next = temp+1;
|
||||
temp++;
|
||||
}
|
||||
bucks[n] = NULL;
|
||||
temp->refs = 0;
|
||||
new (&temp->obj) SQObjectPtr;
|
||||
temp->next = NULL;
|
||||
_freelist = nodes;
|
||||
_nodes = nodes;
|
||||
_buckets = bucks;
|
||||
_slotused = 0;
|
||||
_numofslots = size;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//SQStringTable
|
||||
/*
|
||||
* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
|
||||
* http://www.lua.org/copyright.html#4
|
||||
* http://www.lua.org/source/4.0.1/src_lstring.c.html
|
||||
*/
|
||||
|
||||
SQStringTable::SQStringTable(SQSharedState *ss)
|
||||
{
|
||||
_sharedstate = ss;
|
||||
AllocNodes(4);
|
||||
_slotused = 0;
|
||||
}
|
||||
|
||||
SQStringTable::~SQStringTable()
|
||||
{
|
||||
SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
|
||||
_strings = NULL;
|
||||
}
|
||||
|
||||
void SQStringTable::AllocNodes(SQInteger size)
|
||||
{
|
||||
_numofslots = size;
|
||||
_strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
|
||||
memset(_strings,0,sizeof(SQString*)*_numofslots);
|
||||
}
|
||||
|
||||
SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
|
||||
{
|
||||
if(len<0)
|
||||
len = (SQInteger)scstrlen(news);
|
||||
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,sq_rsl(len))))
|
||||
return s; //found
|
||||
}
|
||||
|
||||
SQString *t = (SQString *)SQ_MALLOC(sq_rsl(len)+sizeof(SQString));
|
||||
new (t) SQString;
|
||||
t->_sharedstate = _sharedstate;
|
||||
memcpy(t->_val,news,sq_rsl(len));
|
||||
t->_val[len] = _SC('\0');
|
||||
t->_len = len;
|
||||
t->_hash = newhash;
|
||||
t->_next = _strings[h];
|
||||
_strings[h] = t;
|
||||
_slotused++;
|
||||
if (_slotused > _numofslots) /* too crowded? */
|
||||
Resize(_numofslots*2);
|
||||
return t;
|
||||
}
|
||||
|
||||
void SQStringTable::Resize(SQInteger size)
|
||||
{
|
||||
SQInteger oldsize=_numofslots;
|
||||
SQString **oldtable=_strings;
|
||||
AllocNodes(size);
|
||||
for (SQInteger i=0; i<oldsize; i++){
|
||||
SQString *p = oldtable[i];
|
||||
while(p){
|
||||
SQString *next = p->_next;
|
||||
SQHash h = p->_hash&(_numofslots-1);
|
||||
p->_next = _strings[h];
|
||||
_strings[h] = p;
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
SQ_FREE(oldtable,oldsize*sizeof(SQString*));
|
||||
}
|
||||
|
||||
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)
|
||||
prev->_next = s->_next;
|
||||
else
|
||||
_strings[h] = s->_next;
|
||||
_slotused--;
|
||||
SQInteger slen = s->_len;
|
||||
s->~SQString();
|
||||
SQ_FREE(s,sizeof(SQString) + sq_rsl(slen));
|
||||
return;
|
||||
}
|
||||
prev = s;
|
||||
s = s->_next;
|
||||
}
|
||||
assert(0);//if this fail something is wrong
|
||||
}
|
||||
136
dependencies/squirrel/squirrel/sqstate.h
vendored
Normal file
136
dependencies/squirrel/squirrel/sqstate.h
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQSTATE_H_
|
||||
#define _SQSTATE_H_
|
||||
|
||||
#include "squtils.h"
|
||||
#include "sqobject.h"
|
||||
struct SQString;
|
||||
struct SQTable;
|
||||
//max number of character for a printed number
|
||||
#define NUMBER_MAX_CHAR 50
|
||||
|
||||
struct SQStringTable
|
||||
{
|
||||
SQStringTable(SQSharedState*ss);
|
||||
~SQStringTable();
|
||||
SQString *Add(const SQChar *,SQInteger len);
|
||||
void Remove(SQString *);
|
||||
private:
|
||||
void Resize(SQInteger size);
|
||||
void AllocNodes(SQInteger size);
|
||||
SQString **_strings;
|
||||
SQUnsignedInteger _numofslots;
|
||||
SQUnsignedInteger _slotused;
|
||||
SQSharedState *_sharedstate;
|
||||
};
|
||||
|
||||
struct RefTable {
|
||||
struct RefNode {
|
||||
SQObjectPtr obj;
|
||||
SQUnsignedInteger refs;
|
||||
struct RefNode *next;
|
||||
};
|
||||
RefTable();
|
||||
~RefTable();
|
||||
void AddRef(SQObject &obj);
|
||||
SQBool Release(SQObject &obj);
|
||||
SQUnsignedInteger GetRefCount(SQObject &obj);
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
void Mark(SQCollectable **chain);
|
||||
#endif
|
||||
void Finalize();
|
||||
private:
|
||||
RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add);
|
||||
RefNode *Add(SQHash mainpos,SQObject &obj);
|
||||
void Resize(SQUnsignedInteger size);
|
||||
void AllocNodes(SQUnsignedInteger size);
|
||||
SQUnsignedInteger _numofslots;
|
||||
SQUnsignedInteger _slotused;
|
||||
RefNode *_nodes;
|
||||
RefNode *_freelist;
|
||||
RefNode **_buckets;
|
||||
};
|
||||
|
||||
#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len)
|
||||
#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr)
|
||||
|
||||
struct SQObjectPtr;
|
||||
|
||||
struct SQSharedState
|
||||
{
|
||||
SQSharedState();
|
||||
~SQSharedState();
|
||||
void Init();
|
||||
public:
|
||||
SQChar* GetScratchPad(SQInteger size);
|
||||
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;
|
||||
SQObjectPtr _metamethodsmap;
|
||||
SQObjectPtrVec *_systemstrings;
|
||||
SQObjectPtrVec *_types;
|
||||
SQStringTable *_stringtable;
|
||||
RefTable _refs_table;
|
||||
SQObjectPtr _registry;
|
||||
SQObjectPtr _consts;
|
||||
SQObjectPtr _constructoridx;
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
SQCollectable *_gc_chain;
|
||||
#endif
|
||||
SQObjectPtr _root_vm;
|
||||
SQObjectPtr _table_default_delegate;
|
||||
static const SQRegFunction _table_default_delegate_funcz[];
|
||||
SQObjectPtr _array_default_delegate;
|
||||
static const SQRegFunction _array_default_delegate_funcz[];
|
||||
SQObjectPtr _string_default_delegate;
|
||||
static const SQRegFunction _string_default_delegate_funcz[];
|
||||
SQObjectPtr _number_default_delegate;
|
||||
static const SQRegFunction _number_default_delegate_funcz[];
|
||||
SQObjectPtr _generator_default_delegate;
|
||||
static const SQRegFunction _generator_default_delegate_funcz[];
|
||||
SQObjectPtr _closure_default_delegate;
|
||||
static const SQRegFunction _closure_default_delegate_funcz[];
|
||||
SQObjectPtr _thread_default_delegate;
|
||||
static const SQRegFunction _thread_default_delegate_funcz[];
|
||||
SQObjectPtr _class_default_delegate;
|
||||
static const SQRegFunction _class_default_delegate_funcz[];
|
||||
SQObjectPtr _instance_default_delegate;
|
||||
static const SQRegFunction _instance_default_delegate_funcz[];
|
||||
SQObjectPtr _weakref_default_delegate;
|
||||
static const SQRegFunction _weakref_default_delegate_funcz[];
|
||||
|
||||
SQCOMPILERERROR _compilererrorhandler;
|
||||
SQPRINTFUNCTION _printfunc;
|
||||
SQPRINTFUNCTION _errorfunc;
|
||||
bool _debuginfo;
|
||||
bool _notifyallexceptions;
|
||||
SQUserPointer _foreignptr;
|
||||
SQRELEASEHOOK _releasehook;
|
||||
private:
|
||||
SQChar *_scratchpad;
|
||||
SQInteger _scratchpadsize;
|
||||
};
|
||||
|
||||
#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)
|
||||
|
||||
bool CompileTypemask(SQIntVec &res,const SQChar *typemask);
|
||||
|
||||
|
||||
#endif //_SQSTATE_H_
|
||||
31
dependencies/squirrel/squirrel/sqstring.h
vendored
Normal file
31
dependencies/squirrel/squirrel/sqstring.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQSTRING_H_
|
||||
#define _SQSTRING_H_
|
||||
|
||||
inline SQHash _hashstr (const SQChar *s, size_t l)
|
||||
{
|
||||
SQHash h = (SQHash)l; /* seed */
|
||||
size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */
|
||||
for (; l>=step; l-=step)
|
||||
h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++));
|
||||
return h;
|
||||
}
|
||||
|
||||
struct SQString : public SQRefCounted
|
||||
{
|
||||
SQString(){}
|
||||
~SQString(){}
|
||||
public:
|
||||
static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 );
|
||||
SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
|
||||
void Release();
|
||||
SQSharedState *_sharedstate;
|
||||
SQString *_next; //chain for the string table
|
||||
SQInteger _len;
|
||||
SQHash _hash;
|
||||
SQChar _val[1];
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //_SQSTRING_H_
|
||||
221
dependencies/squirrel/squirrel/sqtable.cpp
vendored
Normal file
221
dependencies/squirrel/squirrel/sqtable.cpp
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
see copyright notice in squirrel.h
|
||||
*/
|
||||
#include "sqpcheader.h"
|
||||
#include "sqvm.h"
|
||||
#include "sqtable.h"
|
||||
#include "sqfuncproto.h"
|
||||
#include "sqclosure.h"
|
||||
|
||||
SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize)
|
||||
{
|
||||
SQInteger pow2size=MINPOWER2;
|
||||
while(nInitialSize>pow2size)pow2size=pow2size<<1;
|
||||
AllocNodes(pow2size);
|
||||
_usednodes = 0;
|
||||
_delegate = NULL;
|
||||
INIT_CHAIN();
|
||||
ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);
|
||||
}
|
||||
|
||||
void SQTable::Remove(const SQObjectPtr &key)
|
||||
{
|
||||
|
||||
_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
|
||||
if (n) {
|
||||
n->val.Null();
|
||||
n->key.Null();
|
||||
_usednodes--;
|
||||
Rehash(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SQTable::AllocNodes(SQInteger nSize)
|
||||
{
|
||||
_HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);
|
||||
for(SQInteger i=0;i<nSize;i++){
|
||||
_HashNode &n = nodes[i];
|
||||
new (&n) _HashNode;
|
||||
n.next=NULL;
|
||||
}
|
||||
_numofnodes=nSize;
|
||||
_nodes=nodes;
|
||||
_firstfree=&_nodes[_numofnodes-1];
|
||||
}
|
||||
|
||||
void SQTable::Rehash(bool force)
|
||||
{
|
||||
SQInteger oldsize=_numofnodes;
|
||||
//prevent problems with the integer division
|
||||
if(oldsize<4)oldsize=4;
|
||||
_HashNode *nold=_nodes;
|
||||
SQInteger nelems=CountUsed();
|
||||
if (nelems >= oldsize-oldsize/4) /* using more than 3/4? */
|
||||
AllocNodes(oldsize*2);
|
||||
else if (nelems <= oldsize/4 && /* less than 1/4? */
|
||||
oldsize > MINPOWER2)
|
||||
AllocNodes(oldsize/2);
|
||||
else if(force)
|
||||
AllocNodes(oldsize);
|
||||
else
|
||||
return;
|
||||
_usednodes = 0;
|
||||
for (SQInteger i=0; i<oldsize; i++) {
|
||||
_HashNode *old = nold+i;
|
||||
if (type(old->key) != OT_NULL)
|
||||
NewSlot(old->key,old->val);
|
||||
}
|
||||
for(SQInteger k=0;k<oldsize;k++)
|
||||
nold[k].~_HashNode();
|
||||
SQ_FREE(nold,oldsize*sizeof(_HashNode));
|
||||
}
|
||||
|
||||
SQTable *SQTable::Clone()
|
||||
{
|
||||
SQTable *nt=Create(_opt_ss(this),_numofnodes);
|
||||
#ifdef _FAST_CLONE
|
||||
_HashNode *basesrc = _nodes;
|
||||
_HashNode *basedst = nt->_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;
|
||||
}
|
||||
|
||||
bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
|
||||
{
|
||||
if(type(key) == OT_NULL)
|
||||
return false;
|
||||
_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
|
||||
if (n) {
|
||||
val = _realval(n->val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
|
||||
{
|
||||
assert(type(key) != OT_NULL);
|
||||
SQHash h = HashObj(key) & (_numofnodes - 1);
|
||||
_HashNode *n = _Get(key, h);
|
||||
if (n) {
|
||||
n->val = val;
|
||||
return false;
|
||||
}
|
||||
_HashNode *mp = &_nodes[h];
|
||||
n = mp;
|
||||
|
||||
|
||||
//key not found I'll insert it
|
||||
//main pos is not free
|
||||
|
||||
if(type(mp->key) != OT_NULL) {
|
||||
n = _firstfree; /* get a free place */
|
||||
SQHash mph = HashObj(mp->key) & (_numofnodes - 1);
|
||||
_HashNode *othern; /* main position of colliding node */
|
||||
|
||||
if (mp > n && (othern = &_nodes[mph]) != mp){
|
||||
/* yes; move colliding node into free position */
|
||||
while (othern->next != mp){
|
||||
assert(othern->next != NULL);
|
||||
othern = othern->next; /* find previous */
|
||||
}
|
||||
othern->next = n; /* redo the chain with `n' in place of `mp' */
|
||||
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->next = NULL; /* now `mp' is free */
|
||||
}
|
||||
else{
|
||||
/* new node will go into free position */
|
||||
n->next = mp->next; /* chain new position */
|
||||
mp->next = n;
|
||||
mp = n;
|
||||
}
|
||||
}
|
||||
mp->key = key;
|
||||
|
||||
for (;;) { /* correct `firstfree' */
|
||||
if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) {
|
||||
mp->val = val;
|
||||
_usednodes++;
|
||||
return true; /* OK; table still has a free place */
|
||||
}
|
||||
else if (_firstfree == _nodes) break; /* cannot decrement from here */
|
||||
else (_firstfree)--;
|
||||
}
|
||||
Rehash(true);
|
||||
return NewSlot(key, val);
|
||||
}
|
||||
|
||||
SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
|
||||
{
|
||||
SQInteger idx = (SQInteger)TranslateIndex(refpos);
|
||||
while (idx < _numofnodes) {
|
||||
if(type(_nodes[idx].key) != OT_NULL) {
|
||||
//first found
|
||||
_HashNode &n = _nodes[idx];
|
||||
outkey = n.key;
|
||||
outval = getweakrefs?(SQObject)n.val:_realval(n.val);
|
||||
//return idx for the next iteration
|
||||
return ++idx;
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
//nothing to iterate anymore
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
|
||||
{
|
||||
_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
|
||||
if (n) {
|
||||
n->val = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SQTable::_ClearNodes()
|
||||
{
|
||||
for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); }
|
||||
}
|
||||
|
||||
void SQTable::Finalize()
|
||||
{
|
||||
_ClearNodes();
|
||||
SetDelegate(NULL);
|
||||
}
|
||||
|
||||
void SQTable::Clear()
|
||||
{
|
||||
_ClearNodes();
|
||||
_usednodes = 0;
|
||||
Rehash(true);
|
||||
}
|
||||
110
dependencies/squirrel/squirrel/sqtable.h
vendored
Normal file
110
dependencies/squirrel/squirrel/sqtable.h
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQTABLE_H_
|
||||
#define _SQTABLE_H_
|
||||
/*
|
||||
* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
|
||||
* http://www.lua.org/copyright.html#4
|
||||
* http://www.lua.org/source/4.0.1/src_ltable.c.html
|
||||
*/
|
||||
|
||||
#include "sqstring.h"
|
||||
|
||||
|
||||
#define hashptr(p) ((SQHash)(((SQInteger)p) >> 3))
|
||||
|
||||
inline SQHash HashObj(const SQObjectPtr &key)
|
||||
{
|
||||
switch(type(key)) {
|
||||
case OT_STRING: return _string(key)->_hash;
|
||||
case OT_FLOAT: return (SQHash)((SQInteger)_float(key));
|
||||
case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key));
|
||||
default: return hashptr(key._unVal.pRefCounted);
|
||||
}
|
||||
}
|
||||
|
||||
struct SQTable : public SQDelegable
|
||||
{
|
||||
private:
|
||||
struct _HashNode
|
||||
{
|
||||
_HashNode() { next = NULL; }
|
||||
SQObjectPtr val;
|
||||
SQObjectPtr key;
|
||||
_HashNode *next;
|
||||
};
|
||||
_HashNode *_firstfree;
|
||||
_HashNode *_nodes;
|
||||
SQInteger _numofnodes;
|
||||
SQInteger _usednodes;
|
||||
|
||||
///////////////////////////
|
||||
void AllocNodes(SQInteger nSize);
|
||||
void Rehash(bool force);
|
||||
SQTable(SQSharedState *ss, SQInteger nInitialSize);
|
||||
void _ClearNodes();
|
||||
public:
|
||||
static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
|
||||
{
|
||||
SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
|
||||
new (newtable) SQTable(ss, nInitialSize);
|
||||
newtable->_delegate = NULL;
|
||||
return newtable;
|
||||
}
|
||||
void Finalize();
|
||||
SQTable *Clone();
|
||||
~SQTable()
|
||||
{
|
||||
SetDelegate(NULL);
|
||||
REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
|
||||
for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
|
||||
SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
void Mark(SQCollectable **chain);
|
||||
SQObjectType GetType() {return OT_TABLE;}
|
||||
#endif
|
||||
inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
|
||||
{
|
||||
_HashNode *n = &_nodes[hash];
|
||||
do{
|
||||
if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
|
||||
return n;
|
||||
}
|
||||
}while((n = n->next));
|
||||
return NULL;
|
||||
}
|
||||
//for compiler use
|
||||
inline bool GetStr(const SQChar* key,SQInteger keylen,SQObjectPtr &val)
|
||||
{
|
||||
SQHash hash = _hashstr(key,keylen);
|
||||
_HashNode *n = &_nodes[hash & (_numofnodes - 1)];
|
||||
_HashNode *res = NULL;
|
||||
do{
|
||||
if(type(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){
|
||||
res = n;
|
||||
break;
|
||||
}
|
||||
}while((n = n->next));
|
||||
if (res) {
|
||||
val = _realval(res->val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Get(const SQObjectPtr &key,SQObjectPtr &val);
|
||||
void Remove(const SQObjectPtr &key);
|
||||
bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
|
||||
//returns true if a new slot has been created false if it was already present
|
||||
bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
|
||||
SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
|
||||
|
||||
SQInteger CountUsed(){ return _usednodes;}
|
||||
void Clear();
|
||||
void Release()
|
||||
{
|
||||
sq_delete(this, SQTable);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //_SQTABLE_H_
|
||||
40
dependencies/squirrel/squirrel/squserdata.h
vendored
Normal file
40
dependencies/squirrel/squirrel/squserdata.h
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQUSERDATA_H_
|
||||
#define _SQUSERDATA_H_
|
||||
|
||||
struct SQUserData : SQDelegable
|
||||
{
|
||||
SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); }
|
||||
~SQUserData()
|
||||
{
|
||||
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this);
|
||||
SetDelegate(NULL);
|
||||
}
|
||||
static SQUserData* Create(SQSharedState *ss, SQInteger size)
|
||||
{
|
||||
SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size);
|
||||
new (ud) SQUserData(ss);
|
||||
ud->_size = size;
|
||||
ud->_typetag = 0;
|
||||
return ud;
|
||||
}
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
void Mark(SQCollectable **chain);
|
||||
void Finalize(){SetDelegate(NULL);}
|
||||
SQObjectType GetType(){ return OT_USERDATA;}
|
||||
#endif
|
||||
void Release() {
|
||||
if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size);
|
||||
SQInteger tsize = _size;
|
||||
this->~SQUserData();
|
||||
SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize);
|
||||
}
|
||||
|
||||
|
||||
SQInteger _size;
|
||||
SQRELEASEHOOK _hook;
|
||||
SQUserPointer _typetag;
|
||||
//SQChar _val[1];
|
||||
};
|
||||
|
||||
#endif //_SQUSERDATA_H_
|
||||
116
dependencies/squirrel/squirrel/squtils.h
vendored
Normal file
116
dependencies/squirrel/squirrel/squtils.h
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQUTILS_H_
|
||||
#define _SQUTILS_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));}
|
||||
#define SQ_MALLOC(__size) sq_vm_malloc((__size));
|
||||
#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<typename T> class sqvector
|
||||
{
|
||||
public:
|
||||
sqvector()
|
||||
{
|
||||
_vals = NULL;
|
||||
_size = 0;
|
||||
_allocated = 0;
|
||||
}
|
||||
sqvector(const sqvector<T>& v)
|
||||
{
|
||||
copy(v);
|
||||
}
|
||||
void copy(const sqvector<T>& v)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
_size = v._size;
|
||||
}
|
||||
~sqvector()
|
||||
{
|
||||
if(_allocated) {
|
||||
for(SQUnsignedInteger i = 0; i < _size; i++)
|
||||
_vals[i].~T();
|
||||
SQ_FREE(_vals, (_allocated * sizeof(T)));
|
||||
}
|
||||
}
|
||||
void reserve(SQUnsignedInteger newsize) { _realloc(newsize); }
|
||||
void resize(SQUnsignedInteger newsize, const T& fill = T())
|
||||
{
|
||||
if(newsize > _allocated)
|
||||
_realloc(newsize);
|
||||
if(newsize > _size) {
|
||||
while(_size < newsize) {
|
||||
new ((void *)&_vals[_size]) T(fill);
|
||||
_size++;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(SQUnsignedInteger i = newsize; i < _size; i++) {
|
||||
_vals[i].~T();
|
||||
}
|
||||
_size = newsize;
|
||||
}
|
||||
}
|
||||
void shrinktofit() { if(_size > 4) { _realloc(_size); } }
|
||||
T& top() const { return _vals[_size - 1]; }
|
||||
inline SQUnsignedInteger size() const { return _size; }
|
||||
bool empty() const { return (_size <= 0); }
|
||||
inline T &push_back(const T& val = T())
|
||||
{
|
||||
if(_allocated <= _size)
|
||||
_realloc(_size * 2);
|
||||
return *(new ((void *)&_vals[_size++]) T(val));
|
||||
}
|
||||
inline void pop_back()
|
||||
{
|
||||
_size--; _vals[_size].~T();
|
||||
}
|
||||
void insert(SQUnsignedInteger idx, const T& val)
|
||||
{
|
||||
resize(_size + 1);
|
||||
for(SQUnsignedInteger i = _size - 1; i > idx; i--) {
|
||||
_vals[i] = _vals[i - 1];
|
||||
}
|
||||
_vals[idx] = val;
|
||||
}
|
||||
void remove(SQUnsignedInteger idx)
|
||||
{
|
||||
_vals[idx].~T();
|
||||
if(idx < (_size - 1)) {
|
||||
memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));
|
||||
}
|
||||
_size--;
|
||||
}
|
||||
SQUnsignedInteger capacity() { return _allocated; }
|
||||
inline T &back() const { return _vals[_size - 1]; }
|
||||
inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; }
|
||||
T* _vals;
|
||||
private:
|
||||
void _realloc(SQUnsignedInteger newsize)
|
||||
{
|
||||
newsize = (newsize > 0)?newsize:4;
|
||||
_vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));
|
||||
_allocated = newsize;
|
||||
}
|
||||
SQUnsignedInteger _size;
|
||||
SQUnsignedInteger _allocated;
|
||||
};
|
||||
|
||||
#endif //_SQUTILS_H_
|
||||
1748
dependencies/squirrel/squirrel/sqvm.cpp
vendored
Normal file
1748
dependencies/squirrel/squirrel/sqvm.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
214
dependencies/squirrel/squirrel/sqvm.h
vendored
Normal file
214
dependencies/squirrel/squirrel/sqvm.h
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
/* see copyright notice in squirrel.h */
|
||||
#ifndef _SQVM_H_
|
||||
#define _SQVM_H_
|
||||
|
||||
#include "sqopcodes.h"
|
||||
#include "sqobject.h"
|
||||
#define MAX_NATIVE_CALLS 100
|
||||
#define MIN_STACK_OVERHEAD 15
|
||||
|
||||
#define SQ_SUSPEND_FLAG -666
|
||||
#define DONT_FALL_BACK 666
|
||||
//#define EXISTS_FALL_BACK -1
|
||||
|
||||
#define GET_FLAG_RAW 0x00000001
|
||||
#define GET_FLAG_DO_NOT_RAISE_ERROR 0x00000002
|
||||
//base lib
|
||||
void sq_base_register(HSQUIRRELVM v);
|
||||
|
||||
struct SQExceptionTrap{
|
||||
SQExceptionTrap() {}
|
||||
SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
|
||||
SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }
|
||||
SQInteger _stackbase;
|
||||
SQInteger _stacksize;
|
||||
SQInstruction *_ip;
|
||||
SQInteger _extarget;
|
||||
};
|
||||
|
||||
#define _INLINE
|
||||
|
||||
#define STK(a) _stack._vals[_stackbase+(a)]
|
||||
#define TARGET _stack._vals[_stackbase+arg0]
|
||||
|
||||
typedef sqvector<SQExceptionTrap> ExceptionsTraps;
|
||||
|
||||
struct SQVM : public CHAINABLE_OBJ
|
||||
{
|
||||
struct CallInfo{
|
||||
//CallInfo() { _generator = NULL;}
|
||||
SQInstruction *_ip;
|
||||
SQObjectPtr *_literals;
|
||||
SQObjectPtr _closure;
|
||||
SQGenerator *_generator;
|
||||
SQInt32 _etraps;
|
||||
SQInt32 _prevstkbase;
|
||||
SQInt32 _prevtop;
|
||||
SQInt32 _target;
|
||||
SQInt32 _ncalls;
|
||||
SQBool _root;
|
||||
};
|
||||
|
||||
typedef sqvector<CallInfo> CallInfoVec;
|
||||
public:
|
||||
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 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 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);
|
||||
//call a generic closure pure SQUIRREL or NATIVE
|
||||
bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror);
|
||||
SQRESULT Suspend();
|
||||
|
||||
void CallDebugHook(SQInteger type,SQInteger forcedline=0);
|
||||
void CallErrorHandler(SQObjectPtr &e);
|
||||
bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, 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);
|
||||
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(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 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
|
||||
_INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
|
||||
_INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
|
||||
_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 CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
|
||||
//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);
|
||||
//_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,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() {
|
||||
SQInteger newsize = _alloccallsstacksize*2;
|
||||
_callstackdata.resize(newsize);
|
||||
_callsstack = &_callstackdata[0];
|
||||
_alloccallsstacksize = newsize;
|
||||
}
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
SQInteger _top;
|
||||
SQInteger _stackbase;
|
||||
SQOuter *_openouters;
|
||||
SQObjectPtr _roottable;
|
||||
SQObjectPtr _lasterror;
|
||||
SQObjectPtr _errorhandler;
|
||||
|
||||
bool _debughook;
|
||||
SQDEBUGHOOK _debughook_native;
|
||||
SQObjectPtr _debughook_closure;
|
||||
|
||||
SQObjectPtr temp_reg;
|
||||
|
||||
|
||||
CallInfo* _callsstack;
|
||||
SQInteger _callsstacksize;
|
||||
SQInteger _alloccallsstacksize;
|
||||
sqvector<CallInfo> _callstackdata;
|
||||
|
||||
ExceptionsTraps _etraps;
|
||||
CallInfo *ci;
|
||||
SQUserPointer _foreignptr;
|
||||
//VMs sharing the same state
|
||||
SQSharedState *_sharedstate;
|
||||
SQInteger _nnativecalls;
|
||||
SQInteger _nmetamethodscall;
|
||||
SQRELEASEHOOK _releasehook;
|
||||
//suspend infos
|
||||
SQBool _suspended;
|
||||
SQBool _suspended_root;
|
||||
SQInteger _suspended_target;
|
||||
SQInteger _suspended_traps;
|
||||
};
|
||||
|
||||
struct AutoDec{
|
||||
AutoDec(SQInteger *n) { _n = n; }
|
||||
~AutoDec() { (*_n)--; }
|
||||
SQInteger *_n;
|
||||
};
|
||||
|
||||
inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
|
||||
|
||||
#define _ss(_vm_) (_vm_)->_sharedstate
|
||||
|
||||
#ifndef NO_GARBAGE_COLLECTOR
|
||||
#define _opt_ss(_vm_) (_vm_)->_sharedstate
|
||||
#else
|
||||
#define _opt_ss(_vm_) NULL
|
||||
#endif
|
||||
|
||||
#define PUSH_CALLINFO(v,nci){ \
|
||||
SQInteger css = v->_callsstacksize; \
|
||||
if(css == v->_alloccallsstacksize) { \
|
||||
v->GrowCallStack(); \
|
||||
} \
|
||||
v->ci = &v->_callsstack[css]; \
|
||||
*(v->ci) = nci; \
|
||||
v->_callsstacksize++; \
|
||||
}
|
||||
|
||||
#define POP_CALLINFO(v){ \
|
||||
SQInteger css = --v->_callsstacksize; \
|
||||
v->ci->_closure.Null(); \
|
||||
v->ci = css?&v->_callsstack[css-1]:NULL; \
|
||||
}
|
||||
#endif //_SQVM_H_
|
||||
Reference in New Issue
Block a user