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

Generated on Thu Sep 24 19:34:59 2009 for OpenTTD by  doxygen 1.5.6