-***version 2.2 stable***\r
+***version 2.2.2 stable***\r
+-fixed some behaviour inconsistencies in thread.call() and thread.wakeup() (thx Mr.Accident)\r
+-fixed coroutine error propagation\r
+-fixed lingering return value from native function (thx Tom Leonard)\r
+-fixed a bug if array.sort() is given a bad sort function (thx Tom Leonard)\r
+-fixed some minor api bug\r
+-added sq_arrayremove() and sq_arrayinsert()\r
+\r
+***2008-05-16 ***\r
+***version 2.2.1 stable***\r
+-fixed a tailcall bug\r
+\r
+***2008-02-17 ***\r
+***version 2.2 stable ***\r
-added _newslot metamethod in classes\r
-added enums added constants\r
-added sq_pushconsttable, sq_setconsttable\r
-The programming language SQUIRREL 2.2 stable\r
+The programming language SQUIRREL 2.2.1 stable\r
\r
--------------------------------------------------\r
The project has been compiled and run on Windows(Windows XP/2000 on Intel x86 Windows XP Pro on AMD x64) and\r
#define SQSTD_STREAM_TYPE_TAG 0x80000000
struct SQStream {
- virtual ~SQStream() {}
-
virtual SQInteger Read(void *buffer, SQInteger size) = 0;
virtual SQInteger Write(void *buffer, SQInteger size) = 0;
virtual SQInteger Flush() = 0;
#define SQUIRREL_API extern
#endif
+#if (defined(_WIN64) || defined(_LP64))
+#define _SQ64
+#endif
+
#ifdef _SQ64
#ifdef _MSC_VER
typedef __int64 SQInteger;
#define MAX_CHAR 0xFF
#endif
-#define SQUIRREL_VERSION _SC("Squirrel 2.2 stable")
+#define SQUIRREL_VERSION _SC("Squirrel 2.2.2 stable")
#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2008 Alberto Demichelis")
#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")
SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);
+SQUIRREL_API SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);
SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx);
sq_aux_paramscheck(v,1);
SQObjectPtr *arr;
_GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
- if(_array(*arr)->Size() > 0) {
+ if(newsize >= 0) {
_array(*arr)->Resize(newsize);
return SQ_OK;
}
- return SQ_OK;
+ return sq_throwerror(v,_SC("negative size"));
}
return SQ_OK;
}
+SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)
+{
+ sq_aux_paramscheck(v, 1);
+ SQObjectPtr *arr;
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+ return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
+}
+
+SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)
+{
+ sq_aux_paramscheck(v, 1);
+ SQObjectPtr *arr;
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+ SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
+ v->Pop();
+ return ret;
+}
+
+
void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)
{
SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);
v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval
v->Pop();
} else v->GetAt(v->_stackbase+v->_suspended_target)=_null_;
- if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,SQVM::ET_RESUME_VM))
+ if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,SQVM::ET_RESUME_VM)) {
return SQ_ERROR;
- if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) {
- while (v->_top > 1) v->_stack[--v->_top] = _null_;
}
if(retval)
v->Push(ret);
void Extend(const SQArray *a);
SQObjectPtr &Top(){return _values.top();}
void Pop(){_values.pop_back(); ShrinkIfNeeded(); }
- void Insert(const SQObject& idx,const SQObject &val){_values.insert((SQUnsignedInteger)tointeger(idx),val);}
+ bool Insert(SQInteger idx,const SQObject &val){
+ if(idx < 0 || idx > (SQInteger)_values.size())
+ return false;
+ _values.insert(idx,val);
+ return true;
+ }
void ShrinkIfNeeded() {
if(_values.size() <= _values.capacity()>>2) //shrink the array
_values.shrinktofit();
}
- void Remove(SQUnsignedInteger idx){
+ bool Remove(SQInteger idx){
+ if(idx < 0 || idx >= (SQInteger)_values.size())
+ return false;
_values.remove(idx);
ShrinkIfNeeded();
+ return true;
}
void Release()
{
SQObject &o=stack_get(v,1);
SQObject &idx=stack_get(v,2);
SQObject &val=stack_get(v,3);
- _array(o)->Insert(idx,val);
+ if(!_array(o)->Insert(tointeger(idx),val))
+ return sq_throwerror(v,_SC("index out of range"));
return 0;
}
v->Push(a);
v->Push(b);
if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) {
- v->Raise_Error(_SC("compare func failed"));
+ if(!sq_isstring( v->_lasterror))
+ v->Raise_Error(_SC("compare func failed"));
return false;
}
sq_getinteger(v, -1, &ret);
return false;
} while( ret <= 0);
do {
- --j;
+ --j;
+ if ( j < 0 ) {
+ v->Raise_Error( _SC("Invalid qsort, probably compare function defect") );
+ return false;
+ }
if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))
return false;
}
static SQInteger thread_call(HSQUIRRELVM v)
{
+
SQObjectPtr o = stack_get(v,1);
if(type(o) == OT_THREAD) {
SQInteger nparams = sq_gettop(v);
sq_move(_thread(o),v,i);
if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) {
sq_move(v,_thread(o),-1);
+ sq_pop(_thread(o),1);
return 1;
}
+ v->_lasterror = _thread(o)->_lasterror;
return SQ_ERROR;
}
return sq_throwerror(v,_SC("wrong parameter"));
if(wakeupret) {
sq_move(thread,v,2);
}
- if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1,SQFalse))) {
+ if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQFalse))) {
sq_move(v,thread,-1);
- sq_pop(thread,1);
+ sq_pop(thread,1); //pop retval
if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
- sq_pop(thread,1);
+ sq_settop(thread,1); //pop roottable
}
return 1;
}
+ sq_settop(thread,1);
+ v->_lasterror = thread->_lasterror;
return SQ_ERROR;
}
return sq_throwerror(v,_SC("wrong parameter"));
{
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);}
+ 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));
bool SQDelegable::SetDelegate(SQTable *mt)
{
SQTable *temp = mt;
+ if(temp == this) return false;
while (temp) {
if (temp->_delegate == this) return false; //cycle detected
temp = temp->_delegate;
for(SQInteger j = nvargs - 1; j >= 0; j--) {
_vargsstack.push_back(v->_vargsstack[vargsbase+j]);
}
- _ci._generator=_null_;
+ _ci._generator=NULL;
for(SQInteger i=0;i<_ci._etraps;i++) {
_etraps.push_back(v->_etraps.top());
v->_etraps.pop_back();
SQInteger oldstackbase=v->_stackbase;
v->_stackbase = v->_top;
v->ci->_target = (SQInt32)target;
- v->ci->_generator = SQObjectPtr(this);
+ v->ci->_generator = this;
v->ci->_vargs.size = (unsigned short)_vargsstack.size();
for(SQInteger i=0;i<_ci._etraps;i++) {
SQSharedState::MarkObject(temp_reg, chain);
for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
+ for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);
END_MARK()
}
_errorhandler = _null_;
_debughook = _null_;
temp_reg = _null_;
+ _callstackdata.resize(0);
SQInteger size=_stack.size();
for(SQInteger i=0;i<size;i++)
_stack[i]=_null_;
SQVM::~SQVM()
{
Finalize();
- sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo));
+ //sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo));
REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
}
_stack.resize(stacksize);
//_callsstack.reserve(4);
_alloccallsstacksize = 4;
+ _callstackdata.resize(_alloccallsstacksize);
_callsstacksize = 0;
- _callsstack = (CallInfo*)sq_malloc(_alloccallsstacksize*sizeof(CallInfo));
+ _callsstack = &_callstackdata[0];
+ //_callsstack = (CallInfo*)sq_malloc(_alloccallsstacksize*sizeof(CallInfo));
_stackbase = 0;
_top = 0;
if(!friendvm)
if (!tailcall) {
CallInfo lc;
+ lc._generator = NULL;
lc._etraps = 0;
lc._prevstkbase = (SQInt32) ( stackbase - _stackbase );
lc._target = (SQInt32) target;
}
ci->_vargs.size = (SQInt32)(nargs - paramssize);
ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size));
- ci->_closure._unVal.pClosure = closure;
- ci->_closure._type = OT_CLOSURE;
+ ci->_closure = closure;
ci->_literals = func->_literals;
ci->_ip = func->_instructions;
//grows the stack if needed
case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue;
case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
case _OP_RETURN:
- if(type((ci)->_generator) == OT_GENERATOR) {
- _generator((ci)->_generator)->Kill();
+ if(ci->_generator) {
+ ci->_generator->Kill();
}
if(Return(arg0, arg1, temp_reg)){
assert(traps==0);
continue;
}
case _OP_YIELD:{
- if(type(ci->_generator) == OT_GENERATOR) {
+ if(ci->_generator) {
if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
- _GUARD(_generator(ci->_generator)->Yield(this));
+ _GUARD(ci->_generator->Yield(this));
traps -= ci->_etraps;
if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg;
}
//if is a native closure
if(type(ci->_closure) != OT_CLOSURE && n)
break;
- if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();
+ if(ci->_generator) ci->_generator->Kill();
PopVarArgs(ci->_vargs);
POP_CALLINFO(this);
n++;
//remove call stack until a C function is found or the cstack is empty
if(ci) do {
SQBool exitafterthisone = ci->_root;
- if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();
+ if(ci->_generator) ci->_generator->Kill();
_stackbase -= ci->_prevstkbase;
_top = _stackbase + ci->_prevtop;
PopVarArgs(ci->_vargs);
SQInteger oldstackbase = _stackbase;
_top = stackbase + nargs;
CallInfo lci;
+ lci._closure = nclosure;
+ lci._generator = NULL;
lci._etraps = 0;
- lci._closure._unVal.pNativeClosure = nclosure;
- lci._closure._type = OT_NATIVECLOSURE;
lci._prevstkbase = (SQInt32) (stackbase - _stackbase);
lci._ncalls = 1;
lci._prevtop = (SQInt32) (oldtop - oldstackbase);
return false;
}
- if (ret != 0){ retval = TOP(); }
+ if (ret != 0){ retval = TOP(); TOP().Null(); }
else { retval = _null_; }
_stackbase = oldstackbase;
_top = oldtop;
};
struct CallInfo{
- CallInfo() { _generator._type = OT_NULL;}
+ //CallInfo() { _generator._type = OT_NULL;}
SQInstruction *_ip;
SQObjectPtr *_literals;
- SQObject _closure;
- SQObject _generator;
+ SQObjectPtr _closure;
+ SQGenerator *_generator;
SQInt32 _etraps;
SQInt32 _prevstkbase;
SQInt32 _prevtop;
void Finalize();
void GrowCallStack() {
SQInteger newsize = _alloccallsstacksize*2;
- _callsstack = (CallInfo*)sq_realloc(_callsstack,_alloccallsstacksize*sizeof(CallInfo),newsize*sizeof(CallInfo));
+ _callstackdata.resize(newsize);
+ _callsstack = &_callstackdata[0];
_alloccallsstacksize = newsize;
}
void Release(){ sq_delete(this,SQVM); } //does nothing
CallInfo* _callsstack;
SQInteger _callsstacksize;
SQInteger _alloccallsstacksize;
+ sqvector<CallInfo> _callstackdata;
ExceptionsTraps _etraps;
CallInfo *ci;
#define POP_CALLINFO(v){ \
v->_callsstacksize--; \
+ v->ci->_closure.Null(); \
if(v->_callsstacksize) \
v->ci = &v->_callsstack[v->_callsstacksize-1] ; \
else \