text: /*	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;}
  public:
  	static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){
  		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];
  		_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);
  	}
  	
  	SQClosure *Clone()
  	{
  		SQFunctionProto *f = _function;
  		SQClosure * ret = SQClosure::Create(_opt_ss(this),f);
  		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;
  	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_
  