0001
0002
0003
0004 #include "pspcheader.h"
0005 #include "psvm.h"
0006 #include "pstable.h"
0007 #include "psclass.h"
0008 #include "psfuncproto.h"
0009 #include "psclosure.h"
0010
0011
0012
0013 PSClass::PSClass(PSSharedState *ss,PSClass *base)
0014 {
0015 _base = base;
0016 _typetag = 0;
0017 _hook = NULL;
0018 _udsize = 0;
0019 _locked = false;
0020 _constructoridx = -1;
0021 if(_base) {
0022 _constructoridx = _base->_constructoridx;
0023 _udsize = _base->_udsize;
0024 _defaultvalues.copy(base->_defaultvalues);
0025 _methods.copy(base->_methods);
0026 _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
0027 __ObjAddRef(_base);
0028 }
0029 _members = base?base->_members->Clone() : PSTable::Create(ss,0);
0030 __ObjAddRef(_members);
0031
0032 INIT_CHAIN();
0033 ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
0034 }
0035
0036 void PSClass::Finalize() {
0037 _attributes.Null();
0038 _NULL_PSOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
0039 _methods.resize(0);
0040 _NULL_PSOBJECT_VECTOR(_metamethods,MT_LAST);
0041 __ObjRelease(_members);
0042 if(_base) {
0043 __ObjRelease(_base);
0044 }
0045 }
0046
0047 PSClass::~PSClass()
0048 {
0049 REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
0050 Finalize();
0051 }
0052
0053 bool PSClass::NewSlot(PSSharedState *ss,const PSObjectPtr &key,const PSObjectPtr &val,bool bstatic)
0054 {
0055 PSObjectPtr temp;
0056 bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
0057 if(_locked && !belongs_to_static_table)
0058 return false;
0059 if(_members->Get(key,temp) && _isfield(temp))
0060 {
0061 _defaultvalues[_member_idx(temp)].val = val;
0062 return true;
0063 }
0064
0065 if (_members->CountUsed() >= MEMBER_MAX_COUNT) {
0066 return false;
0067 }
0068
0069 if(belongs_to_static_table) {
0070 PSInteger mmidx;
0071 if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
0072 (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
0073 _metamethods[mmidx] = val;
0074 }
0075 else {
0076 PSObjectPtr theval = val;
0077 if(_base && type(val) == OT_CLOSURE) {
0078 theval = _closure(val)->Clone();
0079 _closure(theval)->_base = _base;
0080 __ObjAddRef(_base);
0081 }
0082 if(type(temp) == OT_NULL) {
0083 bool isconstructor;
0084 PSVM::IsEqual(ss->_constructoridx, key, isconstructor);
0085 if(isconstructor) {
0086 _constructoridx = (PSInteger)_methods.size();
0087 }
0088 PSClassMember m;
0089 m.val = theval;
0090 _members->NewSlot(key,PSObjectPtr(_make_method_idx(_methods.size())));
0091 _methods.push_back(m);
0092 }
0093 else {
0094 _methods[_member_idx(temp)].val = theval;
0095 }
0096 }
0097 return true;
0098 }
0099 PSClassMember m;
0100 m.val = val;
0101 _members->NewSlot(key,PSObjectPtr(_make_field_idx(_defaultvalues.size())));
0102 _defaultvalues.push_back(m);
0103 return true;
0104 }
0105
0106 PSInstance *PSClass::CreateInstance()
0107 {
0108 if(!_locked) Lock();
0109 return PSInstance::Create(_opt_ss(this),this);
0110 }
0111
0112 PSInteger PSClass::Next(const PSObjectPtr &refpos, PSObjectPtr &outkey, PSObjectPtr &outval)
0113 {
0114 PSObjectPtr oval;
0115 PSInteger idx = _members->Next(false,refpos,outkey,oval);
0116 if(idx != -1) {
0117 if(_ismethod(oval)) {
0118 outval = _methods[_member_idx(oval)].val;
0119 }
0120 else {
0121 PSObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
0122 outval = _realval(o);
0123 }
0124 }
0125 return idx;
0126 }
0127
0128 bool PSClass::SetAttributes(const PSObjectPtr &key,const PSObjectPtr &val)
0129 {
0130 PSObjectPtr idx;
0131 if(_members->Get(key,idx)) {
0132 if(_isfield(idx))
0133 _defaultvalues[_member_idx(idx)].attrs = val;
0134 else
0135 _methods[_member_idx(idx)].attrs = val;
0136 return true;
0137 }
0138 return false;
0139 }
0140
0141 bool PSClass::GetAttributes(const PSObjectPtr &key,PSObjectPtr &outval)
0142 {
0143 PSObjectPtr idx;
0144 if(_members->Get(key,idx)) {
0145 outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
0146 return true;
0147 }
0148 return false;
0149 }
0150
0151
0152 void PSInstance::Init(PSSharedState *ss)
0153 {
0154 _userpointer = NULL;
0155 _hook = NULL;
0156 __ObjAddRef(_class);
0157 _delegate = _class->_members;
0158 INIT_CHAIN();
0159 ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
0160 }
0161
0162 PSInstance::PSInstance(PSSharedState *ss, PSClass *c, PSInteger memsize)
0163 {
0164 _memsize = memsize;
0165 _class = c;
0166 PSUnsignedInteger nvalues = _class->_defaultvalues.size();
0167 for(PSUnsignedInteger n = 0; n < nvalues; n++) {
0168 new (&_values[n]) PSObjectPtr(_class->_defaultvalues[n].val);
0169 }
0170 Init(ss);
0171 }
0172
0173 PSInstance::PSInstance(PSSharedState *ss, PSInstance *i, PSInteger memsize)
0174 {
0175 _memsize = memsize;
0176 _class = i->_class;
0177 PSUnsignedInteger nvalues = _class->_defaultvalues.size();
0178 for(PSUnsignedInteger n = 0; n < nvalues; n++) {
0179 new (&_values[n]) PSObjectPtr(i->_values[n]);
0180 }
0181 Init(ss);
0182 }
0183
0184 void PSInstance::Finalize()
0185 {
0186 PSUnsignedInteger nvalues = _class->_defaultvalues.size();
0187 __ObjRelease(_class);
0188 _NULL_PSOBJECT_VECTOR(_values,nvalues);
0189 }
0190
0191 PSInstance::~PSInstance()
0192 {
0193 REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
0194 if(_class){ Finalize(); }
0195 }
0196
0197 bool PSInstance::GetMetaMethod(PSVM PS_UNUSED_ARG(*v),PSMetaMethod mm,PSObjectPtr &res)
0198 {
0199 if(type(_class->_metamethods[mm]) != OT_NULL) {
0200 res = _class->_metamethods[mm];
0201 return true;
0202 }
0203 return false;
0204 }
0205
0206 bool PSInstance::InstanceOf(PSClass *trg)
0207 {
0208 PSClass *parent = _class;
0209 while(parent != NULL) {
0210 if(parent == trg)
0211 return true;
0212 parent = parent->_base;
0213 }
0214 return false;
0215 }