Back to home page

Enduro/X

 
 

    


0001 /*  see copyright notice in pscript.h */
0002 #ifndef _PSCLASS_H_
0003 #define _PSCLASS_H_
0004 
0005 struct PSInstance;
0006 
0007 struct PSClassMember {
0008     PSObjectPtr val;
0009     PSObjectPtr attrs;
0010     void Null() {
0011         val.Null();
0012         attrs.Null();
0013     }
0014 };
0015 
0016 typedef psvector<PSClassMember> PSClassMemberVec;
0017 
0018 #define MEMBER_TYPE_METHOD 0x01000000
0019 #define MEMBER_TYPE_FIELD 0x02000000
0020 #define MEMBER_MAX_COUNT 0x00FFFFFF
0021 
0022 #define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)
0023 #define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)
0024 #define _make_method_idx(i) ((PSInteger)(MEMBER_TYPE_METHOD|i))
0025 #define _make_field_idx(i) ((PSInteger)(MEMBER_TYPE_FIELD|i))
0026 #define _member_type(o) (_integer(o)&0xFF000000)
0027 #define _member_idx(o) (_integer(o)&0x00FFFFFF)
0028 
0029 struct PSClass : public CHAINABLE_OBJ
0030 {
0031     PSClass(PSSharedState *ss,PSClass *base);
0032 public:
0033     static PSClass* Create(PSSharedState *ss,PSClass *base) {
0034         PSClass *newclass = (PSClass *)PS_MALLOC(sizeof(PSClass));
0035         new (newclass) PSClass(ss, base);
0036         return newclass;
0037     }
0038     ~PSClass();
0039     bool NewSlot(PSSharedState *ss, const PSObjectPtr &key,const PSObjectPtr &val,bool bstatic);
0040     bool Get(const PSObjectPtr &key,PSObjectPtr &val) {
0041         if(_members->Get(key,val)) {
0042             if(_isfield(val)) {
0043                 PSObjectPtr &o = _defaultvalues[_member_idx(val)].val;
0044                 val = _realval(o);
0045             }
0046             else {
0047                 val = _methods[_member_idx(val)].val;
0048             }
0049             return true;
0050         }
0051         return false;
0052     }
0053     bool GetConstructor(PSObjectPtr &ctor)
0054     {
0055         if(_constructoridx != -1) {
0056             ctor = _methods[_constructoridx].val;
0057             return true;
0058         }
0059         return false;
0060     }
0061     bool SetAttributes(const PSObjectPtr &key,const PSObjectPtr &val);
0062     bool GetAttributes(const PSObjectPtr &key,PSObjectPtr &outval);
0063     void Lock() { _locked = true; if(_base) _base->Lock(); }
0064     void Release() {
0065         if (_hook) { _hook(_typetag,0);}
0066         ps_delete(this, PSClass);
0067     }
0068     void Finalize();
0069 #ifndef NO_GARBAGE_COLLECTOR
0070     void Mark(PSCollectable ** );
0071     PSObjectType GetType() {return OT_CLASS;}
0072 #endif
0073     PSInteger Next(const PSObjectPtr &refpos, PSObjectPtr &outkey, PSObjectPtr &outval);
0074     PSInstance *CreateInstance();
0075     PSTable *_members;
0076     PSClass *_base;
0077     PSClassMemberVec _defaultvalues;
0078     PSClassMemberVec _methods;
0079     PSObjectPtr _metamethods[MT_LAST];
0080     PSObjectPtr _attributes;
0081     PSUserPointer _typetag;
0082     PSRELEASEHOOK _hook;
0083     bool _locked;
0084     PSInteger _constructoridx;
0085     PSInteger _udsize;
0086 };
0087 
0088 #define calcinstancesize(_theclass_) \
0089     (_theclass_->_udsize + ps_aligning(sizeof(PSInstance) +  (sizeof(PSObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))
0090 
0091 struct PSInstance : public PSDelegable
0092 {
0093     void Init(PSSharedState *ss);
0094     PSInstance(PSSharedState *ss, PSClass *c, PSInteger memsize);
0095     PSInstance(PSSharedState *ss, PSInstance *c, PSInteger memsize);
0096 public:
0097     static PSInstance* Create(PSSharedState *ss,PSClass *theclass) {
0098 
0099         PSInteger size = calcinstancesize(theclass);
0100         PSInstance *newinst = (PSInstance *)PS_MALLOC(size);
0101         new (newinst) PSInstance(ss, theclass,size);
0102         if(theclass->_udsize) {
0103             newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
0104         }
0105         return newinst;
0106     }
0107     PSInstance *Clone(PSSharedState *ss)
0108     {
0109         PSInteger size = calcinstancesize(_class);
0110         PSInstance *newinst = (PSInstance *)PS_MALLOC(size);
0111         new (newinst) PSInstance(ss, this,size);
0112         if(_class->_udsize) {
0113             newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
0114         }
0115         return newinst;
0116     }
0117     ~PSInstance();
0118     bool Get(const PSObjectPtr &key,PSObjectPtr &val)  {
0119         if(_class->_members->Get(key,val)) {
0120             if(_isfield(val)) {
0121                 PSObjectPtr &o = _values[_member_idx(val)];
0122                 val = _realval(o);
0123             }
0124             else {
0125                 val = _class->_methods[_member_idx(val)].val;
0126             }
0127             return true;
0128         }
0129         return false;
0130     }
0131     bool Set(const PSObjectPtr &key,const PSObjectPtr &val) {
0132         PSObjectPtr idx;
0133         if(_class->_members->Get(key,idx) && _isfield(idx)) {
0134             _values[_member_idx(idx)] = val;
0135             return true;
0136         }
0137         return false;
0138     }
0139     void Release() {
0140         _uiRef++;
0141         if (_hook) { _hook(_userpointer,0);}
0142         _uiRef--;
0143         if(_uiRef > 0) return;
0144         PSInteger size = _memsize;
0145         this->~PSInstance();
0146         PS_FREE(this, size);
0147     }
0148     void Finalize();
0149 #ifndef NO_GARBAGE_COLLECTOR
0150     void Mark(PSCollectable ** );
0151     PSObjectType GetType() {return OT_INSTANCE;}
0152 #endif
0153     bool InstanceOf(PSClass *trg);
0154     bool GetMetaMethod(PSVM *v,PSMetaMethod mm,PSObjectPtr &res);
0155 
0156     PSClass *_class;
0157     PSUserPointer _userpointer;
0158     PSRELEASEHOOK _hook;
0159     PSInteger _memsize;
0160     PSObjectPtr _values[1];
0161 };
0162 
0163 #endif //_PSCLASS_H_