/* see copyright notice in squirrel.h */ #ifndef _SQCLOSURE_H_ #define _SQCLOSURE_H_ #define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(SQObjectPtr)) + (func->_ndefaultparams*sizeof(SQObjectPtr))) struct SQFunctionProto; struct SQClass; struct SQClosure : public CHAINABLE_OBJ { private: SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL; _root=NULL;} public: static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func,SQWeakRef *root){ SQInteger size = _CALC_CLOSURE_SIZE(func); SQClosure *nc=(SQClosure*)SQ_MALLOC(size); new (nc) SQClosure(ss,func); nc->_outervalues = (SQObjectPtr *)(nc + 1); nc->_defaultparams = &nc->_outervalues[func->_noutervalues]; nc->_root = root; __ObjAddRef(nc->_root); _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues); _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams); return nc; } void Release(){ SQFunctionProto *f = _function; SQInteger size = _CALC_CLOSURE_SIZE(f); _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues); _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams); __ObjRelease(_function); this->~SQClosure(); sq_vm_free(this,size); } void SetRoot(SQWeakRef *r) { __ObjRelease(_root); _root = r; __ObjAddRef(_root); } SQClosure *Clone() { SQFunctionProto *f = _function; SQClosure * ret = SQClosure::Create(_opt_ss(this),f,_root); ret->_env = _env; if(ret->_env) __ObjAddRef(ret->_env); _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues); _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams); return ret; } ~SQClosure(); bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); void Finalize(){ SQFunctionProto *f = _function; _NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues); _NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams); } SQObjectType GetType() {return OT_CLOSURE;} #endif SQWeakRef *_env; SQWeakRef *_root; SQClass *_base; SQFunctionProto *_function; SQObjectPtr *_outervalues; SQObjectPtr *_defaultparams; }; ////////////////////////////////////////////// struct SQOuter : public CHAINABLE_OBJ { private: SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } public: static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer) { SQOuter *nc = (SQOuter*)SQ_MALLOC(sizeof(SQOuter)); new (nc) SQOuter(ss, outer); return nc; } ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } void Release() { this->~SQOuter(); sq_vm_free(this,sizeof(SQOuter)); } #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); void Finalize() { _value.Null(); } SQObjectType GetType() {return OT_OUTER;} #endif SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */ SQInteger _idx; /* idx in stack array, for relocation */ SQObjectPtr _value; /* value of outer after stack frame is closed */ SQOuter *_next; /* pointer to next outer when frame is open */ }; ////////////////////////////////////////////// struct SQGenerator : public CHAINABLE_OBJ { enum SQGeneratorState{eRunning,eSuspended,eDead}; private: SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} public: static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){ SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator)); new (nc) SQGenerator(ss,closure); return nc; } ~SQGenerator() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } void Kill(){ _state=eDead; _stack.resize(0); _closure.Null();} void Release(){ sq_delete(this,SQGenerator); } bool Yield(SQVM *v,SQInteger target); bool Resume(SQVM *v,SQObjectPtr &dest); #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); void Finalize(){_stack.resize(0);_closure.Null();} SQObjectType GetType() {return OT_GENERATOR;} #endif SQObjectPtr _closure; SQObjectPtrVec _stack; SQVM::CallInfo _ci; ExceptionsTraps _etraps; SQGeneratorState _state; }; #define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr))) struct SQNativeClosure : public CHAINABLE_OBJ { private: SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;} public: static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters) { SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters); SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size); new (nc) SQNativeClosure(ss,func); nc->_outervalues = (SQObjectPtr *)(nc + 1); nc->_noutervalues = nouters; _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues); return nc; } SQNativeClosure *Clone() { SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function,_noutervalues); ret->_env = _env; if(ret->_env) __ObjAddRef(ret->_env); ret->_name = _name; _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues); ret->_typecheck.copy(_typecheck); ret->_nparamscheck = _nparamscheck; return ret; } ~SQNativeClosure() { __ObjRelease(_env); REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); } void Release(){ SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues); _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues); this->~SQNativeClosure(); sq_free(this,size); } #ifndef NO_GARBAGE_COLLECTOR void Mark(SQCollectable **chain); void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); } SQObjectType GetType() {return OT_NATIVECLOSURE;} #endif SQInteger _nparamscheck; SQIntVec _typecheck; SQObjectPtr *_outervalues; SQUnsignedInteger _noutervalues; SQWeakRef *_env; SQFUNCTION _function; SQObjectPtr _name; }; #endif //_SQCLOSURE_H_