Johan Wikman / SQUIRREL3

Dependents:   Squirrel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sqclass.cpp Source File

sqclass.cpp

00001 /*
00002     see copyright notice in squirrel.h
00003 */
00004 #include "sqpcheader.h"
00005 #include "sqvm.h"
00006 #include "sqtable.h"
00007 #include "sqclass.h"
00008 #include "sqfuncproto.h"
00009 #include "sqclosure.h"
00010 
00011 
00012 
00013 SQClass::SQClass(SQSharedState *ss,SQClass *base)
00014 {
00015     _base = base;
00016     _typetag = 0;
00017     _hook = NULL;
00018     _udsize = 0;
00019     _locked = false;
00020     _constructoridx = -1;
00021     if(_base) {
00022         _constructoridx = _base->_constructoridx;
00023         _udsize = _base->_udsize;
00024         _defaultvalues.copy(base->_defaultvalues);
00025         _methods.copy(base->_methods);
00026         _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
00027         __ObjAddRef(_base);
00028     }
00029     _members = base?base->_members->Clone() : SQTable::Create(ss,0);
00030     __ObjAddRef(_members);
00031     
00032     INIT_CHAIN();
00033     ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
00034 }
00035 
00036 void SQClass::Finalize() { 
00037     _attributes.Null();
00038     _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
00039     _methods.resize(0);
00040     _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
00041     __ObjRelease(_members);
00042     if(_base) {
00043         __ObjRelease(_base);
00044     }
00045 }
00046 
00047 SQClass::~SQClass()
00048 {
00049     REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
00050     Finalize();
00051 }
00052 
00053 bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
00054 {
00055     SQObjectPtr temp;
00056     bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
00057     if(_locked && !belongs_to_static_table) 
00058         return false; //the class already has an instance so cannot be modified
00059     if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
00060     {
00061         _defaultvalues[_member_idx(temp)].val = val;
00062         return true;
00063     }
00064     if(belongs_to_static_table) {
00065         SQInteger mmidx;
00066         if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && 
00067             (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
00068             _metamethods[mmidx] = val;
00069         } 
00070         else {
00071             SQObjectPtr theval = val;
00072             if(_base && type(val) == OT_CLOSURE) {
00073                 theval = _closure(val)->Clone();
00074                 _closure(theval)->_base = _base;
00075                 __ObjAddRef(_base); //ref for the closure
00076             }
00077             if(type(temp) == OT_NULL) {
00078                 bool isconstructor;
00079                 SQVM::IsEqual(ss->_constructoridx, key, isconstructor);
00080                 if(isconstructor) {
00081                     _constructoridx = (SQInteger)_methods.size();
00082                 }
00083                 SQClassMember m;
00084                 m.val = theval;
00085                 _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
00086                 _methods.push_back(m);
00087             }
00088             else {
00089                 _methods[_member_idx(temp)].val = theval;
00090             }
00091         }
00092         return true;
00093     }
00094     SQClassMember m;
00095     m.val = val;
00096     _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
00097     _defaultvalues.push_back(m);
00098     return true;
00099 }
00100 
00101 SQInstance *SQClass::CreateInstance()
00102 {
00103     if(!_locked) Lock();
00104     return SQInstance::Create(_opt_ss(this),this);
00105 }
00106 
00107 SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
00108 {
00109     SQObjectPtr oval;
00110     SQInteger idx = _members->Next(false,refpos,outkey,oval);
00111     if(idx != -1) {
00112         if(_ismethod(oval)) {
00113             outval = _methods[_member_idx(oval)].val;
00114         }
00115         else {
00116             SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
00117             outval = _realval(o);
00118         }
00119     }
00120     return idx;
00121 }
00122 
00123 bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
00124 {
00125     SQObjectPtr idx;
00126     if(_members->Get(key,idx)) {
00127         if(_isfield(idx))
00128             _defaultvalues[_member_idx(idx)].attrs = val;
00129         else
00130             _methods[_member_idx(idx)].attrs = val;
00131         return true;
00132     }
00133     return false;
00134 }
00135 
00136 bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
00137 {
00138     SQObjectPtr idx;
00139     if(_members->Get(key,idx)) {
00140         outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
00141         return true;
00142     }
00143     return false;
00144 }
00145 
00146 ///////////////////////////////////////////////////////////////////////
00147 void SQInstance::Init(SQSharedState *ss)
00148 {
00149     _userpointer = NULL;
00150     _hook = NULL;
00151     __ObjAddRef(_class);
00152     _delegate = _class->_members;
00153     INIT_CHAIN();
00154     ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
00155 }
00156 
00157 SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
00158 {
00159     _memsize = memsize;
00160     _class = c;
00161     SQUnsignedInteger nvalues = _class->_defaultvalues.size();
00162     for(SQUnsignedInteger n = 0; n < nvalues; n++) {
00163         new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
00164     }
00165     Init(ss);
00166 }
00167 
00168 SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
00169 {
00170     _memsize = memsize;
00171     _class = i->_class;
00172     SQUnsignedInteger nvalues = _class->_defaultvalues.size();
00173     for(SQUnsignedInteger n = 0; n < nvalues; n++) {
00174         new (&_values[n]) SQObjectPtr(i->_values[n]);
00175     }
00176     Init(ss);
00177 }
00178 
00179 void SQInstance::Finalize() 
00180 {
00181     SQUnsignedInteger nvalues = _class->_defaultvalues.size();
00182     __ObjRelease(_class);
00183     _NULL_SQOBJECT_VECTOR(_values,nvalues);
00184     //for(SQUnsignedInteger i = 0; i < nvalues; i++) {
00185 //      _values[i].Null();
00186 //  }
00187 }
00188 
00189 SQInstance::~SQInstance()
00190 {
00191     REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
00192     if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
00193 }
00194 
00195 bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res)
00196 {
00197     if(type(_class->_metamethods[mm]) != OT_NULL) {
00198         res = _class->_metamethods[mm];
00199         return true;
00200     }
00201     return false;
00202 }
00203 
00204 bool SQInstance::InstanceOf(SQClass *trg)
00205 {
00206     SQClass *parent = _class;
00207     while(parent != NULL) {
00208         if(parent == trg)
00209             return true;
00210         parent = parent->_base;
00211     }
00212     return false;
00213 }