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

View File

@ -5,17 +5,11 @@
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <rabbit/sqpcheader.hpp>
#include <rabbit/VirtualMachine.hpp>
#include <rabbit/sqtable.hpp>
#include <rabbit/sqclass.hpp>
#include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclosure.hpp>
#include <rabbit/MetaMethod.hpp>
#include <rabbit/Class.hpp>
#include <rabbit/Instance.hpp>
SQClass::SQClass(SQSharedState *ss,SQClass *base)
{
rabbit::Class::Class(SQSharedState *ss,rabbit::Class *base) {
_base = base;
_typetag = 0;
_hook = NULL;
@ -34,7 +28,7 @@ SQClass::SQClass(SQSharedState *ss,SQClass *base)
__ObjaddRef(_members);
}
void SQClass::finalize() {
void rabbit::Class::finalize() {
_attributes.Null();
_NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
_methods.resize(0);
@ -45,21 +39,21 @@ void SQClass::finalize() {
}
}
SQClass::~SQClass()
{
rabbit::Class::~Class() {
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;
bool belongs_to_static_table = sq_type(val) == rabbit::OT_CLOSURE
|| sq_type(val) == rabbit::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
{
if(_locked && !belongs_to_static_table) {
//the class already has an instance so cannot be modified
return false;
}
//overrides the default value
if(_members->get(key,temp) && _isfield(temp)) {
_defaultvalues[_member_idx(temp)].val = val;
return true;
}
@ -69,8 +63,7 @@ bool SQClass::newSlot(SQSharedState *ss,const rabbit::ObjectPtr &key,const rabbi
|| sq_type(val) == rabbit::OT_NATIVECLOSURE )
&& (mmidx = ss->getMetaMethodIdxByName(key)) != -1) {
_metamethods[mmidx] = val;
}
else {
} else {
rabbit::ObjectPtr theval = val;
if(_base && sq_type(val) == rabbit::OT_CLOSURE) {
theval = _closure(val)->clone();
@ -83,39 +76,37 @@ bool SQClass::newSlot(SQSharedState *ss,const rabbit::ObjectPtr &key,const rabbi
if(isconstructor) {
_constructoridx = (int64_t)_methods.size();
}
SQClassMember m;
rabbit::ClassMember m;
m.val = theval;
_members->newSlot(key,rabbit::ObjectPtr(_make_method_idx(_methods.size())));
_methods.pushBack(m);
}
else {
} else {
_methods[_member_idx(temp)].val = theval;
}
}
return true;
}
SQClassMember m;
rabbit::ClassMember m;
m.val = val;
_members->newSlot(key,rabbit::ObjectPtr(_make_field_idx(_defaultvalues.size())));
_defaultvalues.pushBack(m);
return true;
}
SQInstance *SQClass::createInstance()
{
if(!_locked) lock();
return SQInstance::create(NULL,this);
rabbit::Instance *rabbit::Class::createInstance() {
if(!_locked) {
lock();
}
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;
int64_t idx = _members->next(false,refpos,outkey,oval);
if(idx != -1) {
if(_ismethod(oval)) {
outval = _methods[_member_idx(oval)].val;
}
else {
} else {
rabbit::ObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
outval = _realval(o);
}
@ -123,21 +114,20 @@ int64_t SQClass::next(const rabbit::ObjectPtr &refpos, rabbit::ObjectPtr &outkey
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;
if(_members->get(key,idx)) {
if(_isfield(idx))
if(_isfield(idx)) {
_defaultvalues[_member_idx(idx)].attrs = val;
else
} else {
_methods[_member_idx(idx)].attrs = val;
}
return true;
}
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;
if(_members->get(key,idx)) {
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;
}
///////////////////////////////////////////////////////////////////////
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_CLASS, SQClass, pClass)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_INSTANCE, SQInstance, pInstance)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLASS, rabbit::Class, pClass)
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_CLOSURE, SQClosure, pClosure)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure)

View File

@ -34,8 +34,8 @@ namespace rabbit {
ObjectPtr(const Object& _obj);
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_INSTANCE, SQInstance, pInstance)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLASS, rabbit::Class, pClass)
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_CLOSURE, SQClosure, pClosure)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure)

View File

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

View File

@ -16,7 +16,8 @@
#include <rabbit/sqtable.hpp>
#include <rabbit/UserData.hpp>
#include <rabbit/Array.hpp>
#include <rabbit/sqclass.hpp>
#include <rabbit/Instance.hpp>
#define TOP() (_stack[_top-1])
#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)
{
SQClass *base = NULL;
rabbit::Class *base = NULL;
rabbit::ObjectPtr attrs;
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; }
@ -625,7 +626,7 @@ bool rabbit::VirtualMachine::CLASS_OP(rabbit::ObjectPtr &target,int64_t baseclas
if(attributes != MAX_FUNC_STACKSIZE) {
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) {
int nparams = 2;
rabbit::ObjectPtr ret;
@ -1103,7 +1104,7 @@ exception_trap:
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();
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"));
return false;
}
SQClass *c = _class(self);
rabbit::Class *c = _class(self);
if(!raw) {
rabbit::ObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];
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);
//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 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
bool call(rabbit::ObjectPtr &closure, int64_t nparams, int64_t stackbase, rabbit::ObjectPtr &outres,rabbit::Bool raiseerror);
rabbit::Result Suspend();

View File

@ -15,7 +15,8 @@
#include <rabbit/UserData.hpp>
#include <rabbit/sqcompiler.hpp>
#include <rabbit/sqfuncstate.hpp>
#include <rabbit/sqclass.hpp>
#include <rabbit/Instance.hpp>
#include <rabbit/MemberHandle.hpp>
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)
{
SQClass *baseclass = NULL;
rabbit::Class *baseclass = NULL;
if(hasbase) {
rabbit::ObjectPtr &base = stack_get(v,-1);
if(sq_type(base) != rabbit::OT_CLASS)
return sq_throwerror(v,_SC("invalid base type"));
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();
v->push(newclass);
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"));
(*p) = _instance(o)->_userpointer;
if(typetag != 0) {
SQClass *cl = _instance(o)->_class;
rabbit::Class *cl = _instance(o)->_class;
do{
if(cl->_typetag == typetag)
return SQ_OK;
@ -1460,9 +1461,9 @@ rabbit::Result _getmemberbyhandle(rabbit::VirtualMachine* v,rabbit::ObjectPtr &s
{
switch(sq_type(self)) {
case rabbit::OT_INSTANCE: {
SQInstance *i = _instance(self);
rabbit::Instance *i = _instance(self);
if(handle->_static) {
SQClass *c = i->_class;
rabbit::Class *c = i->_class;
val = &c->_methods[handle->_index].val;
}
else {
@ -1472,7 +1473,7 @@ rabbit::Result _getmemberbyhandle(rabbit::VirtualMachine* v,rabbit::ObjectPtr &s
}
break;
case rabbit::OT_CLASS: {
SQClass *c = _class(self);
rabbit::Class *c = _class(self);
if(handle->_static) {
val = &c->_methods[handle->_index].val;
}

View File

@ -12,7 +12,7 @@
#include <rabbit/Array.hpp>
#include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclosure.hpp>
#include <rabbit/sqclass.hpp>
#include <stdlib.h>
#include <stdarg.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
#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)))
struct SQFunctionProto;
struct SQClass;
struct SQClosure : public rabbit::RefCounted
{
private:
@ -64,7 +66,7 @@ public:
static bool load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret);
rabbit::WeakRef *_env;
rabbit::WeakRef *_root;
SQClass *_base;
rabbit::Class *_base;
SQFunctionProto *_function;
rabbit::ObjectPtr *_outervalues;
rabbit::ObjectPtr *_defaultparams;

View File

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

View File

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

View File

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