The Squirrel interpreter. See http://www.squirrel-lang.org/

Dependents:   Squirrel

Revision:
0:97a4f8cc534c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/squirrel/sqclass.cpp	Tue Dec 16 10:20:34 2014 +0000
@@ -0,0 +1,213 @@
+/*
+	see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqtable.h"
+#include "sqclass.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+
+
+
+SQClass::SQClass(SQSharedState *ss,SQClass *base)
+{
+	_base = base;
+	_typetag = 0;
+	_hook = NULL;
+	_udsize = 0;
+	_locked = false;
+	_constructoridx = -1;
+	if(_base) {
+		_constructoridx = _base->_constructoridx;
+		_udsize = _base->_udsize;
+		_defaultvalues.copy(base->_defaultvalues);
+		_methods.copy(base->_methods);
+		_COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
+		__ObjAddRef(_base);
+	}
+	_members = base?base->_members->Clone() : SQTable::Create(ss,0);
+	__ObjAddRef(_members);
+	
+	INIT_CHAIN();
+	ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
+}
+
+void SQClass::Finalize() { 
+	_attributes.Null();
+	_NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
+	_methods.resize(0);
+	_NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
+	__ObjRelease(_members);
+	if(_base) {
+		__ObjRelease(_base);
+	}
+}
+
+SQClass::~SQClass()
+{
+	REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
+	Finalize();
+}
+
+bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
+{
+	SQObjectPtr temp;
+	bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
+	if(_locked && !belongs_to_static_table) 
+		return false; //the class already has an instance so cannot be modified
+	if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
+	{
+		_defaultvalues[_member_idx(temp)].val = val;
+		return true;
+	}
+	if(belongs_to_static_table) {
+		SQInteger mmidx;
+		if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && 
+			(mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
+			_metamethods[mmidx] = val;
+		} 
+		else {
+			SQObjectPtr theval = val;
+			if(_base && type(val) == OT_CLOSURE) {
+				theval = _closure(val)->Clone();
+				_closure(theval)->_base = _base;
+				__ObjAddRef(_base); //ref for the closure
+			}
+			if(type(temp) == OT_NULL) {
+				bool isconstructor;
+				SQVM::IsEqual(ss->_constructoridx, key, isconstructor);
+				if(isconstructor) {
+					_constructoridx = (SQInteger)_methods.size();
+				}
+				SQClassMember m;
+				m.val = theval;
+				_members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
+				_methods.push_back(m);
+			}
+			else {
+				_methods[_member_idx(temp)].val = theval;
+			}
+		}
+		return true;
+	}
+	SQClassMember m;
+	m.val = val;
+	_members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
+	_defaultvalues.push_back(m);
+	return true;
+}
+
+SQInstance *SQClass::CreateInstance()
+{
+	if(!_locked) Lock();
+	return SQInstance::Create(_opt_ss(this),this);
+}
+
+SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
+{
+	SQObjectPtr oval;
+	SQInteger idx = _members->Next(false,refpos,outkey,oval);
+	if(idx != -1) {
+		if(_ismethod(oval)) {
+			outval = _methods[_member_idx(oval)].val;
+		}
+		else {
+			SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
+			outval = _realval(o);
+		}
+	}
+	return idx;
+}
+
+bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
+{
+	SQObjectPtr idx;
+	if(_members->Get(key,idx)) {
+		if(_isfield(idx))
+			_defaultvalues[_member_idx(idx)].attrs = val;
+		else
+			_methods[_member_idx(idx)].attrs = val;
+		return true;
+	}
+	return false;
+}
+
+bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
+{
+	SQObjectPtr idx;
+	if(_members->Get(key,idx)) {
+		outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
+		return true;
+	}
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+void SQInstance::Init(SQSharedState *ss)
+{
+	_userpointer = NULL;
+	_hook = NULL;
+	__ObjAddRef(_class);
+	_delegate = _class->_members;
+	INIT_CHAIN();
+	ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
+}
+
+SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
+{
+	_memsize = memsize;
+	_class = c;
+	SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+	for(SQUnsignedInteger n = 0; n < nvalues; n++) {
+		new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
+	}
+	Init(ss);
+}
+
+SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
+{
+	_memsize = memsize;
+	_class = i->_class;
+	SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+	for(SQUnsignedInteger n = 0; n < nvalues; n++) {
+		new (&_values[n]) SQObjectPtr(i->_values[n]);
+	}
+	Init(ss);
+}
+
+void SQInstance::Finalize() 
+{
+	SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+	__ObjRelease(_class);
+	_NULL_SQOBJECT_VECTOR(_values,nvalues);
+	//for(SQUnsignedInteger i = 0; i < nvalues; i++) {
+//		_values[i].Null();
+//	}
+}
+
+SQInstance::~SQInstance()
+{
+	REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
+	if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
+}
+
+bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res)
+{
+	if(type(_class->_metamethods[mm]) != OT_NULL) {
+		res = _class->_metamethods[mm];
+		return true;
+	}
+	return false;
+}
+
+bool SQInstance::InstanceOf(SQClass *trg)
+{
+	SQClass *parent = _class;
+	while(parent != NULL) {
+		if(parent == trg)
+			return true;
+		parent = parent->_base;
+	}
+	return false;
+}