0001
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