Update to Squirrel 3.0.6
[supertux.git] / external / squirrel / squirrel / sqobject.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 40c5ba4..18ea008
@@ -35,6 +35,7 @@ const SQChar *IdType2Name(SQObjectType type)
        case _RT_CLASS: return _SC("class");\r
        case _RT_INSTANCE: return _SC("instance");\r
        case _RT_WEAKREF: return _SC("weakref");\r
+       case _RT_OUTER: return _SC("outer");\r
        default:\r
                return NULL;\r
        }\r
@@ -48,7 +49,6 @@ const SQChar *GetTypeName(const SQObjectPtr &obj1)
 SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)\r
 {\r
        SQString *str=ADD_STRING(ss,s,len);\r
-       str->_sharedstate=ss;\r
        return str;\r
 }\r
 \r
@@ -62,7 +62,7 @@ SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjec
        SQInteger idx = (SQInteger)TranslateIndex(refpos);\r
        while(idx < _len){\r
                outkey = (SQInteger)idx;\r
-               outval = SQInteger(_val[idx]);\r
+               outval = (SQInteger)((SQUnsignedInteger)_val[idx]);\r
                //return idx for the next iteration\r
                return ++idx;\r
        }\r
@@ -128,22 +128,24 @@ bool SQDelegable::SetDelegate(SQTable *mt)
        return true;\r
 }\r
 \r
-bool SQGenerator::Yield(SQVM *v)\r
+bool SQGenerator::Yield(SQVM *v,SQInteger target)\r
 {\r
        if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}\r
        if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }\r
        SQInteger size = v->_top-v->_stackbase;\r
-       _ci=*v->ci;\r
+       \r
        _stack.resize(size);\r
-       for(SQInteger n =0; n<size; n++) {\r
+       SQObject _this = v->_stack[v->_stackbase];\r
+       _stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;\r
+       for(SQInteger n =1; n<target; n++) {\r
                _stack._vals[n] = v->_stack[v->_stackbase+n];\r
-               v->_stack[v->_stackbase+n] = _null_;\r
        }\r
-       SQInteger nvargs = v->ci->_vargs.size;\r
-       SQInteger vargsbase = v->ci->_vargs.base;\r
-       for(SQInteger j = nvargs - 1; j >= 0; j--) {\r
-               _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
+       for(SQInteger j =0; j < size; j++)\r
+       {\r
+               v->_stack[v->_stackbase+j].Null();\r
        }\r
+\r
+       _ci = *v->ci;\r
        _ci._generator=NULL;\r
        for(SQInteger i=0;i<_ci._etraps;i++) {\r
                _etraps.push_back(v->_etraps.top());\r
@@ -153,37 +155,39 @@ bool SQGenerator::Yield(SQVM *v)
        return true;\r
 }\r
 \r
-bool SQGenerator::Resume(SQVM *v,SQInteger target)\r
+bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest)\r
 {\r
-       SQInteger size=_stack.size();\r
        if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }\r
        if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }\r
-       SQInteger prevtop=v->_top-v->_stackbase;\r
-       PUSH_CALLINFO(v,_ci);\r
-       SQInteger oldstackbase=v->_stackbase;\r
-       v->_stackbase = v->_top;\r
-       v->ci->_target = (SQInt32)target;\r
-       v->ci->_generator = this;\r
-       v->ci->_vargs.size = (unsigned short)_vargsstack.size();\r
-       \r
+       SQInteger size = _stack.size();\r
+       SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]);\r
+       assert(target>=0 && target<=255);\r
+       if(!v->EnterFrame(v->_top, v->_top + size, false)) \r
+               return false;\r
+       v->ci->_generator   = this;\r
+       v->ci->_target      = (SQInt32)target;\r
+       v->ci->_closure     = _ci._closure;\r
+       v->ci->_ip          = _ci._ip;\r
+       v->ci->_literals    = _ci._literals;\r
+       v->ci->_ncalls      = _ci._ncalls;\r
+       v->ci->_etraps      = _ci._etraps;\r
+       v->ci->_root        = _ci._root;\r
+\r
+\r
        for(SQInteger i=0;i<_ci._etraps;i++) {\r
                v->_etraps.push_back(_etraps.top());\r
                _etraps.pop_back();\r
        }\r
-       for(SQInteger n =0; n<size; n++) {\r
+       SQObject _this = _stack._vals[0];\r
+       v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;\r
+\r
+       for(SQInteger n = 1; n<size; n++) {\r
                v->_stack[v->_stackbase+n] = _stack._vals[n];\r
-               _stack._vals[0] = _null_;\r
+               _stack._vals[n].Null();\r
        }\r
-       while(_vargsstack.size()) {\r
-               v->_vargsstack.push_back(_vargsstack.back());\r
-               _vargsstack.pop_back();\r
-       }\r
-       v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size);\r
-       v->_top=v->_stackbase+size;\r
-       v->ci->_prevtop = (SQInt32)prevtop;\r
-       v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase);\r
+\r
        _state=eRunning;\r
-       if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure))\r
+       if (v->_debughook)\r
                v->CallDebugHook(_SC('c'));\r
 \r
        return true;\r
@@ -216,18 +220,45 @@ const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQU
        return res;\r
 }\r
 \r
+\r
 SQInteger SQFunctionProto::GetLine(SQInstruction *curr)\r
 {\r
        SQInteger op = (SQInteger)(curr-_instructions);\r
        SQInteger line=_lineinfos[0]._line;\r
-       for(SQInteger i=1;i<_nlineinfos;i++){\r
-               if(_lineinfos[i]._op>=op)\r
-                       return line;\r
-               line=_lineinfos[i]._line;\r
+       SQInteger low = 0;\r
+       SQInteger high = _nlineinfos - 1;\r
+       SQInteger mid = 0;\r
+       while(low <= high)\r
+       {\r
+               mid = low + ((high - low) >> 1);\r
+               SQInteger curop = _lineinfos[mid]._op;\r
+               if(curop > op)\r
+               {\r
+                       high = mid - 1;\r
+               }\r
+               else if(curop < op) {\r
+                       if(mid < (_nlineinfos - 1) \r
+                               && _lineinfos[mid + 1]._op >= op) {\r
+                               break;\r
+                       }\r
+                       low = mid + 1;\r
+               }\r
+               else { //equal\r
+                       break;\r
+               }\r
        }\r
+\r
+       line = _lineinfos[mid]._line;\r
        return line;\r
 }\r
 \r
+SQClosure::~SQClosure()\r
+{\r
+       __ObjRelease(_env);\r
+       __ObjRelease(_base);\r
+       REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
 #define _CHECK_IO(exp)  { if(!exp)return false; }\r
 bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)\r
 {\r
@@ -247,14 +278,14 @@ bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest
        return true;\r
 }\r
 \r
-bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag)\r
+bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag)\r
 {\r
        return SafeWrite(v,write,up,&tag,sizeof(tag));\r
 }\r
 \r
-bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)\r
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag)\r
 {\r
-       SQInteger t;\r
+       SQUnsignedInteger32 t;\r
        _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));\r
        if(t != tag){\r
                v->Raise_Error(_SC("invalid or corrupted closure stream"));\r
@@ -265,12 +296,14 @@ bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)
 \r
 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)\r
 {\r
-       _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));\r
+       SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);\r
+       _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));\r
        switch(type(o)){\r
        case OT_STRING:\r
                _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));\r
                _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));\r
                break;\r
+       case OT_BOOL:\r
        case OT_INTEGER:\r
                _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;\r
        case OT_FLOAT:\r
@@ -286,8 +319,9 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o
 \r
 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)\r
 {\r
-       SQObjectType t;\r
-       _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));\r
+       SQUnsignedInteger32 _type;\r
+       _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));\r
+       SQObjectType t = (SQObjectType)_type;\r
        switch(t){\r
        case OT_STRING:{\r
                SQInteger len;\r
@@ -300,12 +334,16 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
                SQInteger i;\r
                _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;\r
                                        }\r
+       case OT_BOOL:{\r
+               SQInteger i;\r
+               _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;\r
+                                       }\r
        case OT_FLOAT:{\r
                SQFloat f;\r
                _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;\r
                                  }\r
        case OT_NULL:\r
-               o=_null_;\r
+               o.Null();\r
                break;\r
        default:\r
                v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));\r
@@ -318,7 +356,9 @@ bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
 {\r
        _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));\r
        _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));\r
-       _CHECK_IO(_funcproto(_function)->Save(v,up,write));\r
+       _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger)));\r
+       _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat)));\r
+       _CHECK_IO(_function->Save(v,up,write));\r
        _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));\r
        return true;\r
 }\r
@@ -327,6 +367,8 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
 {\r
        _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
        _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
+       _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger)));\r
+       _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat)));\r
        SQObjectPtr func;\r
        _CHECK_IO(SQFunctionProto::Load(v,up,read,func));\r
        _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
@@ -334,6 +376,18 @@ bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
        return true;\r
 }\r
 \r
+SQFunctionProto::SQFunctionProto(SQSharedState *ss)\r
+{\r
+       _stacksize=0;\r
+       _bgenerator=false;\r
+       INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
+SQFunctionProto::~SQFunctionProto()\r
+{\r
+       REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
 bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
 {\r
        SQInteger i,nliterals = _nliterals,nparameters = _nparameters;\r
@@ -419,7 +473,7 @@ bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr
        _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));\r
        \r
 \r
-       SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,\r
+       SQFunctionProto *f = SQFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters,\r
                        nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);\r
        SQObjectPtr proto = f; //gets a ref in case of failure\r
        f->_sourcename = sourcename;\r
@@ -492,11 +546,10 @@ void SQVM::Mark(SQCollectable **chain)
        START_MARK()\r
                SQSharedState::MarkObject(_lasterror,chain);\r
                SQSharedState::MarkObject(_errorhandler,chain);\r
-               SQSharedState::MarkObject(_debughook,chain);\r
+               SQSharedState::MarkObject(_debughook_closure,chain);\r
                SQSharedState::MarkObject(_roottable, chain);\r
                SQSharedState::MarkObject(temp_reg, chain);\r
                for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
-               for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
                for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);\r
        END_MARK()\r
 }\r
@@ -534,7 +587,7 @@ void SQClass::Mark(SQCollectable **chain)
                        SQSharedState::MarkObject(_methods[j].val, chain);\r
                        SQSharedState::MarkObject(_methods[j].attrs, chain);\r
                }\r
-               for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) {\r
+               for(SQUnsignedInteger k =0; k< MT_LAST; k++) {\r
                        SQSharedState::MarkObject(_metamethods[k], chain);\r
                }\r
        END_MARK()\r
@@ -555,23 +608,43 @@ void SQGenerator::Mark(SQCollectable **chain)
 {\r
        START_MARK()\r
                for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
-               for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
                SQSharedState::MarkObject(_closure, chain);\r
        END_MARK()\r
 }\r
 \r
+void SQFunctionProto::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain);\r
+               for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain);\r
+       END_MARK()\r
+}\r
+\r
 void SQClosure::Mark(SQCollectable **chain)\r
 {\r
        START_MARK()\r
-               for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
-               for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain);\r
+               if(_base) _base->Mark(chain);\r
+               SQFunctionProto *fp = _function;\r
+               fp->Mark(chain);\r
+               for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+               for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain);\r
        END_MARK()\r
 }\r
 \r
 void SQNativeClosure::Mark(SQCollectable **chain)\r
 {\r
        START_MARK()\r
-               for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+               for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+       END_MARK()\r
+}\r
+\r
+void SQOuter::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+    /* If the valptr points to a closed value, that value is alive */\r
+    if(_valptr == &_value) {\r
+      SQSharedState::MarkObject(_value, chain);\r
+    }\r
        END_MARK()\r
 }\r
 \r