소스 검색

Several fixes from squirrel.

mingodad 8 년 전
부모
커밋
ea079daa15

+ 1 - 0
SquiLu/include/sqapi.h

@@ -181,6 +181,7 @@ SQUIRREL_API_FUNC(SQRESULT, throwerror, (HSQUIRRELVM v,const SQChar *fmt, ...))
 SQUIRREL_API_FUNC(SQRESULT, throwobject, (HSQUIRRELVM v))
 SQUIRREL_API_FUNC(SQRESULT, throwobject, (HSQUIRRELVM v))
 SQUIRREL_API_FUNC(void, reseterror, (HSQUIRRELVM v))
 SQUIRREL_API_FUNC(void, reseterror, (HSQUIRRELVM v))
 SQUIRREL_API_FUNC(void, getlasterror, (HSQUIRRELVM v))
 SQUIRREL_API_FUNC(void, getlasterror, (HSQUIRRELVM v))
+SQUIRREL_API_FUNC(SQRESULT, tailcall, (HSQUIRRELVM v, SQInteger nparams))
 SQUIRREL_API_FUNC(const SQChar*, getlasterror_str, (HSQUIRRELVM v))
 SQUIRREL_API_FUNC(const SQChar*, getlasterror_str, (HSQUIRRELVM v))
 SQUIRREL_API_FUNC(void, getlasterror_line_col, (HSQUIRRELVM v, SQInteger *line, SQInteger *column))
 SQUIRREL_API_FUNC(void, getlasterror_line_col, (HSQUIRRELVM v, SQInteger *line, SQInteger *column))
 
 

+ 6 - 1
SquiLu/sqstdlib/sqstdblob.cpp

@@ -254,6 +254,11 @@ static SQRESULT _blob__get(HSQUIRRELVM v)
 {
 {
 	SETUP_BLOB(v);
 	SETUP_BLOB(v);
 	SQInteger idx;
 	SQInteger idx;
+	if ((sq_gettype(v, 2) & SQOBJECT_NUMERIC) == 0)
+	{
+		sq_pushnull(v);
+		return sq_throwobject(v);
+	}
 	SQObjectType ptype = sq_gettype(v, 2);
 	SQObjectType ptype = sq_gettype(v, 2);
 	if( !(ptype & SQOBJECT_NUMERIC) ){
 	if( !(ptype & SQOBJECT_NUMERIC) ){
 	    //allow call metatable methods indexed by strings
 	    //allow call metatable methods indexed by strings
@@ -484,7 +489,7 @@ static SQRegFunction _blob_methods[] = {
 	_DECL_BLOB_FUNC(swap4,1,_SC("x")),
 	_DECL_BLOB_FUNC(swap4,1,_SC("x")),
 	_DECL_BLOB_FUNC(memset,4,_SC("xiii")),
 	_DECL_BLOB_FUNC(memset,4,_SC("xiii")),
 	_DECL_BLOB_FUNC(_set,3,_SC("xnn")),
 	_DECL_BLOB_FUNC(_set,3,_SC("xnn")),
-	_DECL_BLOB_FUNC(_get,2,_SC("x n|s")), //allow call metatable methods indexed by strings
+	_DECL_BLOB_FUNC(_get,2,_SC("x.")), //allow call metatable methods indexed by strings
 	_DECL_BLOB_FUNC(_typeof,1,_SC("x")),
 	_DECL_BLOB_FUNC(_typeof,1,_SC("x")),
 	_DECL_BLOB_FUNC(_nexti,2,_SC("x")),
 	_DECL_BLOB_FUNC(_nexti,2,_SC("x")),
 	_DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
 	_DECL_BLOB_FUNC(_cloned,2,_SC("xx")),

+ 1 - 1
SquiLu/sqstdlib/sqstdblobimpl.h

@@ -23,7 +23,7 @@ struct SQBlob : public SQStream
 	}
 	}
 	SQInteger Seek(SQInteger offset, SQInteger origin);
 	SQInteger Seek(SQInteger offset, SQInteger origin);
 	bool IsValid() {
 	bool IsValid() {
-		return _buf?true:false;
+		return _size == 0 || _buf?true:false;
 	}
 	}
 	bool EOS() {
 	bool EOS() {
 		return _ptr == _size;
 		return _ptr == _size;

+ 29 - 4
SquiLu/squirrel/sqapi.cpp

@@ -1265,8 +1265,11 @@ SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
 	if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
 	if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
 	SQObjectPtr &key = v->GetUp(-3);
 	SQObjectPtr &key = v->GetUp(-3);
 	if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
 	if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
-	if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false))
-		return SQ_ERROR;
+	if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false)) {
+         v->Pop(3);
+         return SQ_ERROR;
+    }
+    v->Pop(3);
 	return SQ_OK;
 	return SQ_OK;
 }
 }
 
 
@@ -1276,8 +1279,11 @@ SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
 	if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
 	if(sq_type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
 	SQObjectPtr &key = v->GetUp(-3);
 	SQObjectPtr &key = v->GetUp(-3);
 	if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
 	if(sq_type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
-	if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true))
-		return SQ_ERROR;
+	if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true)) {
+         v->Pop(3);
+         return SQ_ERROR;
+    }
+    v->Pop(3);
 	return SQ_OK;
 	return SQ_OK;
 }
 }
 
 
@@ -1595,6 +1601,25 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)
 	return sq_throwerror(v,_SC("call failed"));
 	return sq_throwerror(v,_SC("call failed"));
 }
 }
 
 
+SQRESULT sq_tailcall(HSQUIRRELVM v, SQInteger nparams)
+{
+	SQObjectPtr &res = v->GetUp(-(nparams + 1));
+	if (sq_type(res) != OT_CLOSURE) {
+		return sq_throwerror(v, _SC("only closure can be tail called"));
+	}
+	SQClosure *clo = _closure(res);
+	if (clo->_function->_bgenerator)
+	{
+		return sq_throwerror(v, _SC("generators cannot be tail called"));
+	}
+
+	SQInteger stackbase = (v->_top - nparams) - v->_stackbase;
+	if (!v->TailCall(clo, stackbase, nparams)) {
+		return SQ_ERROR;
+	}
+	return SQ_TAILCALL_FLAG;
+}
+
 SQRESULT sq_suspendvm(HSQUIRRELVM v)
 SQRESULT sq_suspendvm(HSQUIRRELVM v)
 {
 {
 	return v->Suspend();
 	return v->Suspend();

+ 6 - 1
SquiLu/squirrel/sqbaselib.cpp

@@ -2361,7 +2361,12 @@ static SQRESULT closure_pcall(HSQUIRRELVM v)
 
 
 static SQRESULT closure_call(HSQUIRRELVM v)
 static SQRESULT closure_call(HSQUIRRELVM v)
 {
 {
-	return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;
+	SQObjectPtr &c = stack_get(v, -1);
+	if (sq_type(c) == OT_CLOSURE && (_closure(c)->_function->_bgenerator == false))
+	{
+		return sq_tailcall(v, sq_gettop(v) - 1);
+	}
+	return SQ_SUCCEEDED(sq_call(v, sq_gettop(v) - 1, SQTrue, SQTrue)) ? 1 : SQ_ERROR;
 }
 }
 
 
 static SQRESULT _closure_acall(HSQUIRRELVM v,SQBool raiseerror, SQBool v2)
 static SQRESULT _closure_acall(HSQUIRRELVM v,SQBool raiseerror, SQBool v2)

+ 1 - 1
SquiLu/squirrel/sqcompiler.cpp

@@ -2114,9 +2114,9 @@ if(color == "yellow"){
 		}
 		}
 		_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
 		_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
 		if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
 		if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
-		END_SCOPE();
 
 
 		END_BREAKBLE_BLOCK(continuetrg);
 		END_BREAKBLE_BLOCK(continuetrg);
+		END_SCOPE();
 	}
 	}
 	void ForEachStatement()
 	void ForEachStatement()
 	{
 	{

+ 33 - 9
SquiLu/squirrel/sqvm.cpp

@@ -958,7 +958,8 @@ exception_restore:
 						continue;
 						continue;
 					case OT_NATIVECLOSURE: {
 					case OT_NATIVECLOSURE: {
 						bool suspend;
 						bool suspend;
-						_GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));
+						bool tailcall;
+                        _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo, (SQInt32)sarg0, suspend, tailcall));
 #ifdef SQ_WITH_DELAYED_RELEASE_HOOKS
 #ifdef SQ_WITH_DELAYED_RELEASE_HOOKS
 						if(_check_delayed_relase_hooks) _sharedstate->CallDelayedReleaseHooks(this);
 						if(_check_delayed_relase_hooks) _sharedstate->CallDelayedReleaseHooks(this);
 #endif
 #endif
@@ -970,7 +971,7 @@ exception_restore:
 							outres = clo;
 							outres = clo;
 							return true;
 							return true;
 						}
 						}
-						if(sarg0 != -1) {
+						if((sarg0 != -1) && !tailcall) {
 							STK(arg0) = clo;
 							STK(arg0) = clo;
 						}
 						}
                     }
                     }
@@ -989,10 +990,10 @@ exception_restore:
 								_GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
 								_GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
 								break;
 								break;
 							case OT_NATIVECLOSURE:
 							case OT_NATIVECLOSURE:
-								bool suspend;
+								bool dummy;
 								stkbase = _stackbase+arg2;
 								stkbase = _stackbase+arg2;
 								_stack._vals[stkbase] = inst;
 								_stack._vals[stkbase] = inst;
-								_GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
+								_GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo, -1, dummy, dummy));
 								break;
 								break;
 							default: break; //shutup GCC 4.x
 							default: break; //shutup GCC 4.x
 						}
 						}
@@ -1373,7 +1374,7 @@ void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
 	_debughook = true;
 	_debughook = true;
 }
 }
 
 
-bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend)
+bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, SQInt32 target, bool &suspend, bool &tailcall)
 {
 {
 	SQInteger nparamscheck = nclosure->_nparamscheck;
 	SQInteger nparamscheck = nclosure->_nparamscheck;
 	SQInteger newtop = newbase + nargs + nclosure->_noutervalues;
 	SQInteger newtop = newbase + nargs + nclosure->_noutervalues;
@@ -1412,6 +1413,7 @@ bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newb
 
 
 	if(!EnterFrame(newbase, newtop, false)) return false;
 	if(!EnterFrame(newbase, newtop, false)) return false;
 	ci->_closure  = nclosure;
 	ci->_closure  = nclosure;
+	ci->_target = target;
 
 
 	SQInteger outers = nclosure->_noutervalues;
 	SQInteger outers = nclosure->_noutervalues;
 	for (SQInteger i = 0; i < outers; i++) {
 	for (SQInteger i = 0; i < outers; i++) {
@@ -1426,8 +1428,13 @@ bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newb
 	_nnativecalls--;
 	_nnativecalls--;
 
 
 	suspend = false;
 	suspend = false;
-	if (ret == SQ_SUSPEND_FLAG) {
-		suspend = true;
+	tailcall = false;
+	if (ret == SQ_TAILCALL_FLAG) {
+		tailcall = true;
+		return true;
+	}
+    else if (ret == SQ_SUSPEND_FLAG) {
+        suspend = true;
 	}
 	}
 	else if (ret < 0) {
 	else if (ret < 0) {
 		LeaveFrame();
 		LeaveFrame();
@@ -1445,6 +1452,23 @@ bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newb
 	return true;
 	return true;
 }
 }
 
 
+bool SQVM::TailCall(SQClosure *closure, SQInteger parambase,SQInteger nparams)
+{
+	SQInteger last_top = _top;
+	SQObjectPtr clo = closure;
+	if (ci->_root)
+	{
+		Raise_Error("root calls cannot invoke tailcalls");
+		return false;
+	}
+	for (SQInteger i = 0; i < nparams; i++) STK(i) = STK(parambase + i);
+	bool ret = StartCall(closure, ci->_target, nparams, _stackbase, true);
+	if (last_top >= _top) {
+		_top = last_top;
+	}
+	return ret;
+}
+
 #define FALLBACK_OK			0
 #define FALLBACK_OK			0
 #define FALLBACK_NO_MATCH	1
 #define FALLBACK_NO_MATCH	1
 #define FALLBACK_ERROR		2
 #define FALLBACK_ERROR		2
@@ -1793,8 +1817,8 @@ SQInteger prevstackbase = _stackbase;
 		return Execute(closure, nparams, stackbase, outres, raiseerror);
 		return Execute(closure, nparams, stackbase, outres, raiseerror);
 		break;
 		break;
 	case OT_NATIVECLOSURE:{
 	case OT_NATIVECLOSURE:{
-		bool suspend;
-		return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
+		bool dummy;
+		return CallNative(_nativeclosure(closure), nparams, stackbase, outres, -1, dummy, dummy);
 
 
 						  }
 						  }
 		break;
 		break;

+ 3 - 1
SquiLu/squirrel/sqvm.h

@@ -12,6 +12,7 @@
 #define MIN_STACK_OVERHEAD 15
 #define MIN_STACK_OVERHEAD 15
 
 
 #define SQ_SUSPEND_FLAG -666
 #define SQ_SUSPEND_FLAG -666
+#define SQ_TAILCALL_FLAG -777
 #define DONT_FALL_BACK 666
 #define DONT_FALL_BACK 666
 //#define EXISTS_FALL_BACK -1
 //#define EXISTS_FALL_BACK -1
 
 
@@ -66,7 +67,8 @@ public:
 	bool Init(SQVM *friendvm, SQInteger stacksize);
 	bool Init(SQVM *friendvm, SQInteger stacksize);
 	bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
 	bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
 	//starts a native call return when the NATIVE closure returns
 	//starts a native call return when the NATIVE closure returns
-	bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval,bool &suspend);
+    bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, SQInt32 target, bool &suspend,bool &tailcall);
+	bool TailCall(SQClosure *closure, SQInteger firstparam, SQInteger nparams);
 	//starts a SQUIRREL call in the same "Execution loop"
 	//starts a SQUIRREL call in the same "Execution loop"
 	bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
 	bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
 	bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
 	bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);