[DEV] rework Class ClassMethode

This commit is contained in:
Edouard DUPIN 2018-06-28 21:13:26 +02:00
parent f882c9fedc
commit 394cc68950
19 changed files with 338 additions and 285 deletions

View File

@ -31,7 +31,9 @@ def configure(target, my_module):
'rabbit/sqbaselib.cpp', 'rabbit/sqbaselib.cpp',
'rabbit/sqapi.cpp', 'rabbit/sqapi.cpp',
'rabbit/sqlexer.cpp', 'rabbit/sqlexer.cpp',
'rabbit/sqclass.cpp', 'rabbit/Class.cpp',
'rabbit/ClassMember.cpp',
'rabbit/Instance.cpp',
'rabbit/AutoDec.cpp', 'rabbit/AutoDec.cpp',
'rabbit/VirtualMachine.cpp', 'rabbit/VirtualMachine.cpp',
'rabbit/sqtable.cpp', 'rabbit/sqtable.cpp',
@ -62,7 +64,9 @@ def configure(target, my_module):
'etk-base', 'etk-base',
]) ])
my_module.add_header_file([ my_module.add_header_file([
'rabbit/sqclass.hpp', 'rabbit/Class.hpp',
'rabbit/ClassMember.hpp',
'rabbit/Instance.hpp',
'rabbit/AutoDec.hpp', 'rabbit/AutoDec.hpp',
'rabbit/VirtualMachine.hpp', 'rabbit/VirtualMachine.hpp',
'rabbit/sqstate.hpp', 'rabbit/sqstate.hpp',

View File

@ -5,17 +5,11 @@
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved * @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file) * @license MPL-2 (see license file)
*/ */
#include <rabbit/sqpcheader.hpp> #include <rabbit/Class.hpp>
#include <rabbit/VirtualMachine.hpp> #include <rabbit/Instance.hpp>
#include <rabbit/sqtable.hpp>
#include <rabbit/sqclass.hpp>
#include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclosure.hpp>
#include <rabbit/MetaMethod.hpp>
SQClass::SQClass(SQSharedState *ss,SQClass *base) rabbit::Class::Class(SQSharedState *ss,rabbit::Class *base) {
{
_base = base; _base = base;
_typetag = 0; _typetag = 0;
_hook = NULL; _hook = NULL;
@ -34,7 +28,7 @@ SQClass::SQClass(SQSharedState *ss,SQClass *base)
__ObjaddRef(_members); __ObjaddRef(_members);
} }
void SQClass::finalize() { void rabbit::Class::finalize() {
_attributes.Null(); _attributes.Null();
_NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size()); _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
_methods.resize(0); _methods.resize(0);
@ -45,21 +39,21 @@ void SQClass::finalize() {
} }
} }
SQClass::~SQClass() rabbit::Class::~Class() {
{
finalize(); finalize();
} }
bool SQClass::newSlot(SQSharedState *ss,const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val,bool bstatic) bool rabbit::Class::newSlot(SQSharedState *ss,const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val,bool bstatic) {
{
rabbit::ObjectPtr temp; rabbit::ObjectPtr temp;
bool belongs_to_static_table = sq_type(val) == rabbit::OT_CLOSURE bool belongs_to_static_table = sq_type(val) == rabbit::OT_CLOSURE
|| sq_type(val) == rabbit::OT_NATIVECLOSURE || sq_type(val) == rabbit::OT_NATIVECLOSURE
|| bstatic; || bstatic;
if(_locked && !belongs_to_static_table) if(_locked && !belongs_to_static_table) {
return false; //the class already has an instance so cannot be modified //the class already has an instance so cannot be modified
if(_members->get(key,temp) && _isfield(temp)) //overrides the default value return false;
{ }
//overrides the default value
if(_members->get(key,temp) && _isfield(temp)) {
_defaultvalues[_member_idx(temp)].val = val; _defaultvalues[_member_idx(temp)].val = val;
return true; return true;
} }
@ -69,8 +63,7 @@ bool SQClass::newSlot(SQSharedState *ss,const rabbit::ObjectPtr &key,const rabbi
|| sq_type(val) == rabbit::OT_NATIVECLOSURE ) || sq_type(val) == rabbit::OT_NATIVECLOSURE )
&& (mmidx = ss->getMetaMethodIdxByName(key)) != -1) { && (mmidx = ss->getMetaMethodIdxByName(key)) != -1) {
_metamethods[mmidx] = val; _metamethods[mmidx] = val;
} } else {
else {
rabbit::ObjectPtr theval = val; rabbit::ObjectPtr theval = val;
if(_base && sq_type(val) == rabbit::OT_CLOSURE) { if(_base && sq_type(val) == rabbit::OT_CLOSURE) {
theval = _closure(val)->clone(); theval = _closure(val)->clone();
@ -83,39 +76,37 @@ bool SQClass::newSlot(SQSharedState *ss,const rabbit::ObjectPtr &key,const rabbi
if(isconstructor) { if(isconstructor) {
_constructoridx = (int64_t)_methods.size(); _constructoridx = (int64_t)_methods.size();
} }
SQClassMember m; rabbit::ClassMember m;
m.val = theval; m.val = theval;
_members->newSlot(key,rabbit::ObjectPtr(_make_method_idx(_methods.size()))); _members->newSlot(key,rabbit::ObjectPtr(_make_method_idx(_methods.size())));
_methods.pushBack(m); _methods.pushBack(m);
} } else {
else {
_methods[_member_idx(temp)].val = theval; _methods[_member_idx(temp)].val = theval;
} }
} }
return true; return true;
} }
SQClassMember m; rabbit::ClassMember m;
m.val = val; m.val = val;
_members->newSlot(key,rabbit::ObjectPtr(_make_field_idx(_defaultvalues.size()))); _members->newSlot(key,rabbit::ObjectPtr(_make_field_idx(_defaultvalues.size())));
_defaultvalues.pushBack(m); _defaultvalues.pushBack(m);
return true; return true;
} }
SQInstance *SQClass::createInstance() rabbit::Instance *rabbit::Class::createInstance() {
{ if(!_locked) {
if(!_locked) lock(); lock();
return SQInstance::create(NULL,this); }
return rabbit::Instance::create(NULL,this);
} }
int64_t SQClass::next(const rabbit::ObjectPtr &refpos, rabbit::ObjectPtr &outkey, rabbit::ObjectPtr &outval) int64_t rabbit::Class::next(const rabbit::ObjectPtr &refpos, rabbit::ObjectPtr &outkey, rabbit::ObjectPtr &outval) {
{
rabbit::ObjectPtr oval; rabbit::ObjectPtr oval;
int64_t idx = _members->next(false,refpos,outkey,oval); int64_t idx = _members->next(false,refpos,outkey,oval);
if(idx != -1) { if(idx != -1) {
if(_ismethod(oval)) { if(_ismethod(oval)) {
outval = _methods[_member_idx(oval)].val; outval = _methods[_member_idx(oval)].val;
} } else {
else {
rabbit::ObjectPtr &o = _defaultvalues[_member_idx(oval)].val; rabbit::ObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
outval = _realval(o); outval = _realval(o);
} }
@ -123,21 +114,20 @@ int64_t SQClass::next(const rabbit::ObjectPtr &refpos, rabbit::ObjectPtr &outkey
return idx; return idx;
} }
bool SQClass::setAttributes(const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val) bool rabbit::Class::setAttributes(const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val) {
{
rabbit::ObjectPtr idx; rabbit::ObjectPtr idx;
if(_members->get(key,idx)) { if(_members->get(key,idx)) {
if(_isfield(idx)) if(_isfield(idx)) {
_defaultvalues[_member_idx(idx)].attrs = val; _defaultvalues[_member_idx(idx)].attrs = val;
else } else {
_methods[_member_idx(idx)].attrs = val; _methods[_member_idx(idx)].attrs = val;
}
return true; return true;
} }
return false; return false;
} }
bool SQClass::getAttributes(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &outval) bool rabbit::Class::getAttributes(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &outval) {
{
rabbit::ObjectPtr idx; rabbit::ObjectPtr idx;
if(_members->get(key,idx)) { if(_members->get(key,idx)) {
outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs); outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
@ -146,65 +136,4 @@ bool SQClass::getAttributes(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &outv
return false; return false;
} }
///////////////////////////////////////////////////////////////////////
void SQInstance::init(SQSharedState *ss)
{
_userpointer = NULL;
_hook = NULL;
__ObjaddRef(_class);
_delegate = _class->_members;
}
SQInstance::SQInstance(SQSharedState *ss, SQClass *c, int64_t memsize)
{
_memsize = memsize;
_class = c;
uint64_t nvalues = _class->_defaultvalues.size();
for(uint64_t n = 0; n < nvalues; n++) {
new (&_values[n]) rabbit::ObjectPtr(_class->_defaultvalues[n].val);
}
init(ss);
}
SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, int64_t memsize)
{
_memsize = memsize;
_class = i->_class;
uint64_t nvalues = _class->_defaultvalues.size();
for(uint64_t n = 0; n < nvalues; n++) {
new (&_values[n]) rabbit::ObjectPtr(i->_values[n]);
}
init(ss);
}
void SQInstance::finalize()
{
uint64_t nvalues = _class->_defaultvalues.size();
__Objrelease(_class);
_NULL_SQOBJECT_VECTOR(_values,nvalues);
}
SQInstance::~SQInstance()
{
if(_class){ finalize(); } //if _class is null it was already finalized by the GC
}
bool SQInstance::getMetaMethod(rabbit::VirtualMachine* SQ_UNUSED_ARG(v),rabbit::MetaMethod mm,rabbit::ObjectPtr &res)
{
if(sq_type(_class->_metamethods[mm]) != rabbit::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;
}

75
rabbit/Class.hpp Normal file
View File

@ -0,0 +1,75 @@
/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <rabbit/sqpcheader.hpp>
#include <rabbit/VirtualMachine.hpp>
#include <rabbit/sqtable.hpp>
#include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclosure.hpp>
#include <rabbit/MetaMethod.hpp>
#include <rabbit/ClassMember.hpp>
namespace rabbit {
class Class : public rabbit::RefCounted {
public:
Class(SQSharedState *ss,rabbit::Class *base);
public:
static Class* create(SQSharedState *ss, Class *base) {
rabbit::Class *newclass = (Class *)SQ_MALLOC(sizeof(Class));
new (newclass) Class(ss, base);
return newclass;
}
~Class();
bool newSlot(SQSharedState *ss, const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val,bool bstatic);
bool get(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &val) {
if(_members->get(key,val)) {
if(_isfield(val)) {
rabbit::ObjectPtr &o = _defaultvalues[_member_idx(val)].val;
val = _realval(o);
} else {
val = _methods[_member_idx(val)].val;
}
return true;
}
return false;
}
bool getConstructor(rabbit::ObjectPtr &ctor) {
if(_constructoridx != -1) {
ctor = _methods[_constructoridx].val;
return true;
}
return false;
}
bool setAttributes(const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val);
bool getAttributes(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &outval);
void lock() { _locked = true; if(_base) _base->lock(); }
void release() {
if (_hook) { _hook(_typetag,0);}
sq_delete(this, Class);
}
void finalize();
int64_t next(const rabbit::ObjectPtr &refpos, rabbit::ObjectPtr &outkey, rabbit::ObjectPtr &outval);
rabbit::Instance *createInstance();
SQTable *_members;
rabbit::Class *_base;
etk::Vector<rabbit::ClassMember> _defaultvalues;
etk::Vector<rabbit::ClassMember> _methods;
rabbit::ObjectPtr _metamethods[rabbit::MT_LAST];
rabbit::ObjectPtr _attributes;
rabbit::UserPointer _typetag;
SQRELEASEHOOK _hook;
bool _locked;
int64_t _constructoridx;
int64_t _udsize;
};
#define calcinstancesize(_theclass_) \
(_theclass_->_udsize + sq_aligning(sizeof(rabbit::Instance) + (sizeof(rabbit::ObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))
}

9
rabbit/ClassMember.cpp Normal file
View File

@ -0,0 +1,9 @@
/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <rabbit/ClassMember.hpp>

37
rabbit/ClassMember.hpp Normal file
View File

@ -0,0 +1,37 @@
/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <rabbit/sqconfig.hpp>
#include <rabbit/ObjectPtr.hpp>
#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) ((int64_t)(MEMBER_TYPE_METHOD|i))
#define _make_field_idx(i) ((int64_t)(MEMBER_TYPE_FIELD|i))
#define _member_type(o) (_integer(o)&0xFF000000)
#define _member_idx(o) (_integer(o)&0x00FFFFFF)
namespace rabbit {
class ClassMember {
public:
rabbit::ObjectPtr val;
rabbit::ObjectPtr attrs;
void Null() {
val.Null();
attrs.Null();
}
};
}

66
rabbit/Instance.cpp Normal file
View File

@ -0,0 +1,66 @@
/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <rabbit/Instance.hpp>
void rabbit::Instance::init(SQSharedState *ss) {
_userpointer = NULL;
_hook = NULL;
__ObjaddRef(_class);
_delegate = _class->_members;
}
rabbit::Instance::Instance(SQSharedState *ss, rabbit::Class *c, int64_t memsize) {
_memsize = memsize;
_class = c;
uint64_t nvalues = _class->_defaultvalues.size();
for(uint64_t n = 0; n < nvalues; n++) {
new (&_values[n]) rabbit::ObjectPtr(_class->_defaultvalues[n].val);
}
init(ss);
}
rabbit::Instance::Instance(SQSharedState *ss, rabbit::Instance *i, int64_t memsize) {
_memsize = memsize;
_class = i->_class;
uint64_t nvalues = _class->_defaultvalues.size();
for(uint64_t n = 0; n < nvalues; n++) {
new (&_values[n]) rabbit::ObjectPtr(i->_values[n]);
}
init(ss);
}
void rabbit::Instance::finalize() {
uint64_t nvalues = _class->_defaultvalues.size();
__Objrelease(_class);
_NULL_SQOBJECT_VECTOR(_values,nvalues);
}
rabbit::Instance::~Instance() {
if(_class){
finalize();
}
}
bool rabbit::Instance::getMetaMethod(rabbit::VirtualMachine* SQ_UNUSED_ARG(v),rabbit::MetaMethod mm,rabbit::ObjectPtr &res) {
if(sq_type(_class->_metamethods[mm]) != rabbit::OT_NULL) {
res = _class->_metamethods[mm];
return true;
}
return false;
}
bool rabbit::Instance::instanceOf(rabbit::Class *trg) {
rabbit::Class *parent = _class;
while(parent != NULL) {
if(parent == trg) {
return true;
}
parent = parent->_base;
}
return false;
}

87
rabbit/Instance.hpp Normal file
View File

@ -0,0 +1,87 @@
/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <rabbit/sqpcheader.hpp>
#include <rabbit/VirtualMachine.hpp>
#include <rabbit/sqtable.hpp>
#include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclosure.hpp>
#include <rabbit/MetaMethod.hpp>
namespace rabbit {
class Instance : public rabbit::Delegable {
public:
void init(SQSharedState *ss);
Instance(SQSharedState *ss, rabbit::Class *c, int64_t memsize);
Instance(SQSharedState *ss, Instance *c, int64_t memsize);
public:
static Instance* create(SQSharedState *ss,rabbit::Class *theclass) {
int64_t size = calcinstancesize(theclass);
Instance *newinst = (Instance *)SQ_MALLOC(size);
new (newinst) Instance(ss, theclass,size);
if(theclass->_udsize) {
newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
}
return newinst;
}
Instance *clone(SQSharedState *ss)
{
int64_t size = calcinstancesize(_class);
Instance *newinst = (Instance *)SQ_MALLOC(size);
new (newinst) Instance(ss, this,size);
if(_class->_udsize) {
newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
}
return newinst;
}
~Instance();
bool get(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &val) {
if(_class->_members->get(key,val)) {
if(_isfield(val)) {
rabbit::ObjectPtr &o = _values[_member_idx(val)];
val = _realval(o);
}
else {
val = _class->_methods[_member_idx(val)].val;
}
return true;
}
return false;
}
bool set(const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val) {
rabbit::ObjectPtr 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;
int64_t size = _memsize;
this->~Instance();
SQ_FREE(this, size);
}
void finalize();
bool instanceOf(rabbit::Class *trg);
bool getMetaMethod(rabbit::VirtualMachine *v,rabbit::MetaMethod mm,rabbit::ObjectPtr &res);
rabbit::Class *_class;
rabbit::UserPointer _userpointer;
SQRELEASEHOOK _hook;
int64_t _memsize;
rabbit::ObjectPtr _values[1];
};
}

View File

@ -50,8 +50,8 @@
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_TABLE, SQTable, pTable) RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_TABLE, SQTable, pTable)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLASS, SQClass, pClass) RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLASS, rabbit::Class, pClass)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_INSTANCE, SQInstance, pInstance) RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_INSTANCE, rabbit::Instance, pInstance)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_ARRAY, rabbit::Array, pArray) RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_ARRAY, rabbit::Array, pArray)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLOSURE, SQClosure, pClosure) RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLOSURE, SQClosure, pClosure)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure) RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure)

View File

@ -34,8 +34,8 @@ namespace rabbit {
ObjectPtr(const Object& _obj); ObjectPtr(const Object& _obj);
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_TABLE, SQTable, pTable) RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_TABLE, SQTable, pTable)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLASS, SQClass, pClass) RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLASS, rabbit::Class, pClass)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_INSTANCE, SQInstance, pInstance) RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_INSTANCE, rabbit::Instance, pInstance)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_ARRAY, rabbit::Array, pArray) RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_ARRAY, rabbit::Array, pArray)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLOSURE, SQClosure, pClosure) RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLOSURE, SQClosure, pClosure)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure) RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure)

View File

@ -23,9 +23,9 @@ namespace rabbit {
int64_t nInteger; int64_t nInteger;
float_t fFloat; float_t fFloat;
struct SQFunctionProto *pFunctionProto; struct SQFunctionProto *pFunctionProto;
struct SQClass *pClass;
struct SQInstance *pInstance;
rabbit::Class *pClass;
rabbit::Instance *pInstance;
rabbit::Delegable *pDelegable; rabbit::Delegable *pDelegable;
rabbit::UserPointer pUserPointer; rabbit::UserPointer pUserPointer;
rabbit::WeakRef* pWeakRef; rabbit::WeakRef* pWeakRef;

View File

@ -16,7 +16,8 @@
#include <rabbit/sqtable.hpp> #include <rabbit/sqtable.hpp>
#include <rabbit/UserData.hpp> #include <rabbit/UserData.hpp>
#include <rabbit/Array.hpp> #include <rabbit/Array.hpp>
#include <rabbit/sqclass.hpp> #include <rabbit/Instance.hpp>
#define TOP() (_stack[_top-1]) #define TOP() (_stack[_top-1])
#define TARGET _stack[_stackbase+arg0] #define TARGET _stack[_stackbase+arg0]
@ -616,7 +617,7 @@ bool rabbit::VirtualMachine::CLOSURE_OP(rabbit::ObjectPtr &target, SQFunctionPro
bool rabbit::VirtualMachine::CLASS_OP(rabbit::ObjectPtr &target,int64_t baseclass,int64_t attributes) bool rabbit::VirtualMachine::CLASS_OP(rabbit::ObjectPtr &target,int64_t baseclass,int64_t attributes)
{ {
SQClass *base = NULL; rabbit::Class *base = NULL;
rabbit::ObjectPtr attrs; rabbit::ObjectPtr attrs;
if(baseclass != -1) { if(baseclass != -1) {
if(sq_type(_stack[_stackbase+baseclass]) != rabbit::OT_CLASS) { raise_error(_SC("trying to inherit from a %s"),getTypeName(_stack[_stackbase+baseclass])); return false; } if(sq_type(_stack[_stackbase+baseclass]) != rabbit::OT_CLASS) { raise_error(_SC("trying to inherit from a %s"),getTypeName(_stack[_stackbase+baseclass])); return false; }
@ -625,7 +626,7 @@ bool rabbit::VirtualMachine::CLASS_OP(rabbit::ObjectPtr &target,int64_t baseclas
if(attributes != MAX_FUNC_STACKSIZE) { if(attributes != MAX_FUNC_STACKSIZE) {
attrs = _stack[_stackbase+attributes]; attrs = _stack[_stackbase+attributes];
} }
target = SQClass::create(_get_shared_state(this),base); target = rabbit::Class::create(_get_shared_state(this),base);
if(sq_type(_class(target)->_metamethods[MT_INHERITED]) != rabbit::OT_NULL) { if(sq_type(_class(target)->_metamethods[MT_INHERITED]) != rabbit::OT_NULL) {
int nparams = 2; int nparams = 2;
rabbit::ObjectPtr ret; rabbit::ObjectPtr ret;
@ -1103,7 +1104,7 @@ exception_trap:
assert(0); assert(0);
} }
bool rabbit::VirtualMachine::createClassInstance(SQClass *theclass, rabbit::ObjectPtr &inst, rabbit::ObjectPtr &constructor) bool rabbit::VirtualMachine::createClassInstance(rabbit::Class *theclass, rabbit::ObjectPtr &inst, rabbit::ObjectPtr &constructor)
{ {
inst = theclass->createInstance(); inst = theclass->createInstance();
if(!theclass->getConstructor(constructor)) { if(!theclass->getConstructor(constructor)) {
@ -1455,7 +1456,7 @@ bool rabbit::VirtualMachine::newSlotA(const rabbit::ObjectPtr &self,const rabbit
raise_error(_SC("object must be a class")); raise_error(_SC("object must be a class"));
return false; return false;
} }
SQClass *c = _class(self); rabbit::Class *c = _class(self);
if(!raw) { if(!raw) {
rabbit::ObjectPtr &mm = c->_metamethods[MT_NEWMEMBER]; rabbit::ObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];
if(sq_type(mm) != rabbit::OT_NULL ) { if(sq_type(mm) != rabbit::OT_NULL ) {

View File

@ -67,7 +67,7 @@ namespace rabbit {
bool tailcall(SQClosure *closure, int64_t firstparam, int64_t nparams); bool tailcall(SQClosure *closure, int64_t firstparam, int64_t nparams);
//starts a RABBIT call in the same "Execution loop" //starts a RABBIT call in the same "Execution loop"
bool startcall(SQClosure *closure, int64_t target, int64_t nargs, int64_t stackbase, bool tailcall); bool startcall(SQClosure *closure, int64_t target, int64_t nargs, int64_t stackbase, bool tailcall);
bool createClassInstance(SQClass *theclass, rabbit::ObjectPtr &inst, rabbit::ObjectPtr &constructor); bool createClassInstance(rabbit::Class *theclass, rabbit::ObjectPtr &inst, rabbit::ObjectPtr &constructor);
//call a generic closure pure RABBIT or NATIVE //call a generic closure pure RABBIT or NATIVE
bool call(rabbit::ObjectPtr &closure, int64_t nparams, int64_t stackbase, rabbit::ObjectPtr &outres,rabbit::Bool raiseerror); bool call(rabbit::ObjectPtr &closure, int64_t nparams, int64_t stackbase, rabbit::ObjectPtr &outres,rabbit::Bool raiseerror);
rabbit::Result Suspend(); rabbit::Result Suspend();

View File

@ -15,7 +15,8 @@
#include <rabbit/UserData.hpp> #include <rabbit/UserData.hpp>
#include <rabbit/sqcompiler.hpp> #include <rabbit/sqcompiler.hpp>
#include <rabbit/sqfuncstate.hpp> #include <rabbit/sqfuncstate.hpp>
#include <rabbit/sqclass.hpp> #include <rabbit/Instance.hpp>
#include <rabbit/MemberHandle.hpp> #include <rabbit/MemberHandle.hpp>
static bool sq_aux_gettypedarg(rabbit::VirtualMachine* v,int64_t idx,rabbit::ObjectType type,rabbit::ObjectPtr **o) static bool sq_aux_gettypedarg(rabbit::VirtualMachine* v,int64_t idx,rabbit::ObjectType type,rabbit::ObjectPtr **o)
@ -283,14 +284,14 @@ void sq_newarray(rabbit::VirtualMachine* v,int64_t size)
rabbit::Result sq_newclass(rabbit::VirtualMachine* v,rabbit::Bool hasbase) rabbit::Result sq_newclass(rabbit::VirtualMachine* v,rabbit::Bool hasbase)
{ {
SQClass *baseclass = NULL; rabbit::Class *baseclass = NULL;
if(hasbase) { if(hasbase) {
rabbit::ObjectPtr &base = stack_get(v,-1); rabbit::ObjectPtr &base = stack_get(v,-1);
if(sq_type(base) != rabbit::OT_CLASS) if(sq_type(base) != rabbit::OT_CLASS)
return sq_throwerror(v,_SC("invalid base type")); return sq_throwerror(v,_SC("invalid base type"));
baseclass = _class(base); baseclass = _class(base);
} }
SQClass *newclass = SQClass::create(_get_shared_state(v), baseclass); rabbit::Class *newclass = rabbit::Class::create(_get_shared_state(v), baseclass);
if(baseclass) v->pop(); if(baseclass) v->pop();
v->push(newclass); v->push(newclass);
return SQ_OK; return SQ_OK;
@ -820,7 +821,7 @@ rabbit::Result sq_getinstanceup(rabbit::VirtualMachine* v, int64_t idx, rabbit::
if(sq_type(o) != rabbit::OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); if(sq_type(o) != rabbit::OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
(*p) = _instance(o)->_userpointer; (*p) = _instance(o)->_userpointer;
if(typetag != 0) { if(typetag != 0) {
SQClass *cl = _instance(o)->_class; rabbit::Class *cl = _instance(o)->_class;
do{ do{
if(cl->_typetag == typetag) if(cl->_typetag == typetag)
return SQ_OK; return SQ_OK;
@ -1460,9 +1461,9 @@ rabbit::Result _getmemberbyhandle(rabbit::VirtualMachine* v,rabbit::ObjectPtr &s
{ {
switch(sq_type(self)) { switch(sq_type(self)) {
case rabbit::OT_INSTANCE: { case rabbit::OT_INSTANCE: {
SQInstance *i = _instance(self); rabbit::Instance *i = _instance(self);
if(handle->_static) { if(handle->_static) {
SQClass *c = i->_class; rabbit::Class *c = i->_class;
val = &c->_methods[handle->_index].val; val = &c->_methods[handle->_index].val;
} }
else { else {
@ -1472,7 +1473,7 @@ rabbit::Result _getmemberbyhandle(rabbit::VirtualMachine* v,rabbit::ObjectPtr &s
} }
break; break;
case rabbit::OT_CLASS: { case rabbit::OT_CLASS: {
SQClass *c = _class(self); rabbit::Class *c = _class(self);
if(handle->_static) { if(handle->_static) {
val = &c->_methods[handle->_index].val; val = &c->_methods[handle->_index].val;
} }

View File

@ -12,7 +12,7 @@
#include <rabbit/Array.hpp> #include <rabbit/Array.hpp>
#include <rabbit/sqfuncproto.hpp> #include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclosure.hpp> #include <rabbit/sqclosure.hpp>
#include <rabbit/sqclass.hpp>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>

View File

@ -1,158 +0,0 @@
/**
* @author Alberto DEMICHELIS
* @author Edouard DUPIN
* @copyright 2018, Edouard DUPIN, all right reserved
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
struct SQInstance;
struct SQClassMember {
rabbit::ObjectPtr val;
rabbit::ObjectPtr attrs;
void Null() {
val.Null();
attrs.Null();
}
};
typedef etk::Vector<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) ((int64_t)(MEMBER_TYPE_METHOD|i))
#define _make_field_idx(i) ((int64_t)(MEMBER_TYPE_FIELD|i))
#define _member_type(o) (_integer(o)&0xFF000000)
#define _member_idx(o) (_integer(o)&0x00FFFFFF)
struct SQClass : public rabbit::RefCounted
{
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 rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val,bool bstatic);
bool get(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &val) {
if(_members->get(key,val)) {
if(_isfield(val)) {
rabbit::ObjectPtr &o = _defaultvalues[_member_idx(val)].val;
val = _realval(o);
}
else {
val = _methods[_member_idx(val)].val;
}
return true;
}
return false;
}
bool getConstructor(rabbit::ObjectPtr &ctor)
{
if(_constructoridx != -1) {
ctor = _methods[_constructoridx].val;
return true;
}
return false;
}
bool setAttributes(const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val);
bool getAttributes(const rabbit::ObjectPtr &key,rabbit::ObjectPtr &outval);
void lock() { _locked = true; if(_base) _base->lock(); }
void release() {
if (_hook) { _hook(_typetag,0);}
sq_delete(this, SQClass);
}
void finalize();
int64_t next(const rabbit::ObjectPtr &refpos, rabbit::ObjectPtr &outkey, rabbit::ObjectPtr &outval);
SQInstance *createInstance();
SQTable *_members;
SQClass *_base;
SQClassMemberVec _defaultvalues;
SQClassMemberVec _methods;
rabbit::ObjectPtr _metamethods[rabbit::MT_LAST];
rabbit::ObjectPtr _attributes;
rabbit::UserPointer _typetag;
SQRELEASEHOOK _hook;
bool _locked;
int64_t _constructoridx;
int64_t _udsize;
};
#define calcinstancesize(_theclass_) \
(_theclass_->_udsize + sq_aligning(sizeof(SQInstance) + (sizeof(rabbit::ObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))
struct SQInstance : public rabbit::Delegable
{
void init(SQSharedState *ss);
SQInstance(SQSharedState *ss, SQClass *c, int64_t memsize);
SQInstance(SQSharedState *ss, SQInstance *c, int64_t memsize);
public:
static SQInstance* create(SQSharedState *ss,SQClass *theclass) {
int64_t 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)
{
int64_t 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 rabbit::ObjectPtr &key,rabbit::ObjectPtr &val) {
if(_class->_members->get(key,val)) {
if(_isfield(val)) {
rabbit::ObjectPtr &o = _values[_member_idx(val)];
val = _realval(o);
}
else {
val = _class->_methods[_member_idx(val)].val;
}
return true;
}
return false;
}
bool set(const rabbit::ObjectPtr &key,const rabbit::ObjectPtr &val) {
rabbit::ObjectPtr 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;
int64_t size = _memsize;
this->~SQInstance();
SQ_FREE(this, size);
}
void finalize();
bool instanceOf(SQClass *trg);
bool getMetaMethod(rabbit::VirtualMachine *v,rabbit::MetaMethod mm,rabbit::ObjectPtr &res);
SQClass *_class;
rabbit::UserPointer _userpointer;
SQRELEASEHOOK _hook;
int64_t _memsize;
rabbit::ObjectPtr _values[1];
};

View File

@ -7,10 +7,12 @@
*/ */
#pragma once #pragma once
#include <rabbit/Class.hpp>
#include <rabbit/sqconfig.hpp>
#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(rabbit::ObjectPtr)) + (func->_ndefaultparams*sizeof(rabbit::ObjectPtr))) #define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(rabbit::ObjectPtr)) + (func->_ndefaultparams*sizeof(rabbit::ObjectPtr)))
struct SQFunctionProto; struct SQFunctionProto;
struct SQClass;
struct SQClosure : public rabbit::RefCounted struct SQClosure : public rabbit::RefCounted
{ {
private: private:
@ -64,7 +66,7 @@ public:
static bool load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret); static bool load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret);
rabbit::WeakRef *_env; rabbit::WeakRef *_env;
rabbit::WeakRef *_root; rabbit::WeakRef *_root;
SQClass *_base; rabbit::Class *_base;
SQFunctionProto *_function; SQFunctionProto *_function;
rabbit::ObjectPtr *_outervalues; rabbit::ObjectPtr *_outervalues;
rabbit::ObjectPtr *_defaultparams; rabbit::ObjectPtr *_defaultparams;

View File

@ -131,8 +131,6 @@ struct SQClosure;
struct SQGenerator; struct SQGenerator;
struct SQNativeClosure; struct SQNativeClosure;
struct SQFunctionProto; struct SQFunctionProto;
struct SQClass;
struct SQInstance;
struct SQOuter; struct SQOuter;
struct SQSharedState; struct SQSharedState;
namespace rabbit { namespace rabbit {
@ -145,4 +143,6 @@ namespace rabbit {
class FunctionInfo; class FunctionInfo;
class StackInfos; class StackInfos;
class MemberHandle; class MemberHandle;
class Instance;
class Class;
} }

View File

@ -12,7 +12,7 @@
#include <rabbit/sqtable.hpp> #include <rabbit/sqtable.hpp>
#include <rabbit/UserData.hpp> #include <rabbit/UserData.hpp>
#include <rabbit/sqfuncproto.hpp> #include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclass.hpp>
#include <rabbit/sqclosure.hpp> #include <rabbit/sqclosure.hpp>
SQString *SQString::create(SQSharedState *ss,const rabbit::Char *s,int64_t len) SQString *SQString::create(SQSharedState *ss,const rabbit::Char *s,int64_t len)

View File

@ -14,7 +14,7 @@
#include <rabbit/sqtable.hpp> #include <rabbit/sqtable.hpp>
#include <rabbit/Array.hpp> #include <rabbit/Array.hpp>
#include <rabbit/UserData.hpp> #include <rabbit/UserData.hpp>
#include <rabbit/sqclass.hpp>
SQSharedState::SQSharedState() SQSharedState::SQSharedState()
{ {