Sfoglia il codice sorgente

app_squirrel: imported last version of squirrel interpreter

- master branch
Daniel-Constantin Mierla 7 anni fa
parent
commit
8233e5191d

+ 1 - 0
src/modules/app_sqlang/squirrel/include/squirrel.h

@@ -332,6 +332,7 @@ SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);
 SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v);
 SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);
 SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_tailcall(HSQUIRRELVM v, SQInteger nparams);
 
 /*raw object handling*/
 SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po);

+ 7 - 1
src/modules/app_sqlang/squirrel/sqstdlib/sqstdblob.cpp

@@ -82,6 +82,12 @@ static SQInteger _blob__get(HSQUIRRELVM v)
 {
     SETUP_BLOB(v);
     SQInteger idx;
+	
+	if ((sq_gettype(v, 2) & SQOBJECT_NUMERIC) == 0)
+	{
+		sq_pushnull(v);
+		return sq_throwobject(v);
+	}
     sq_getinteger(v,2,&idx);
     if(idx < 0 || idx >= self->Len())
         return sq_throwerror(v,_SC("index out of range"));
@@ -168,7 +174,7 @@ static const SQRegFunction _blob_methods[] = {
     _DECL_BLOB_FUNC(swap2,1,_SC("x")),
     _DECL_BLOB_FUNC(swap4,1,_SC("x")),
     _DECL_BLOB_FUNC(_set,3,_SC("xnn")),
-    _DECL_BLOB_FUNC(_get,2,_SC("xn")),
+    _DECL_BLOB_FUNC(_get,2,_SC("x.")),
     _DECL_BLOB_FUNC(_typeof,1,_SC("x")),
     _DECL_BLOB_FUNC(_nexti,2,_SC("x")),
     _DECL_BLOB_FUNC(_cloned,2,_SC("xx")),

+ 1 - 1
src/modules/app_sqlang/squirrel/sqstdlib/sqstdblobimpl.h

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

+ 27 - 2
src/modules/app_sqlang/squirrel/squirrel/sqapi.cpp

@@ -947,8 +947,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"));
     SQObjectPtr &key = v->GetUp(-3);
     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))
+    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;
 }
 
@@ -958,8 +961,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"));
     SQObjectPtr &key = v->GetUp(-3);
     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))
+    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;
 }
 
@@ -1188,6 +1194,25 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)
     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)
 {
     return v->Suspend();

+ 49 - 4
src/modules/app_sqlang/squirrel/squirrel/sqbaselib.cpp

@@ -156,7 +156,14 @@ static SQInteger base_getstackinfos(HSQUIRRELVM v)
 static SQInteger base_assert(HSQUIRRELVM v)
 {
     if(SQVM::IsFalse(stack_get(v,2))){
-        return sq_throwerror(v,_SC("assertion failed"));
+        SQInteger top = sq_gettop(v);
+        if (top>2 && SQ_SUCCEEDED(sq_tostring(v,3))) {
+            const SQChar *str = 0;
+            if (SQ_SUCCEEDED(sq_getstring(v,-1,&str))) {
+                return sq_throwerror(v, str);
+            }
+        }
+        return sq_throwerror(v, _SC("assertion failed"));
     }
     return 0;
 }
@@ -283,7 +290,7 @@ static const SQRegFunction base_funcs[]={
     {_SC("setroottable"),base_setroottable,2, NULL},
     {_SC("getconsttable"),base_getconsttable,1, NULL},
     {_SC("setconsttable"),base_setconsttable,2, NULL},
-    {_SC("assert"),base_assert,2, NULL},
+    {_SC("assert"),base_assert,-2, NULL},
     {_SC("print"),base_print,2, NULL},
     {_SC("error"),base_error,2, NULL},
     {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
@@ -465,6 +472,34 @@ static SQInteger table_getdelegate(HSQUIRRELVM v)
     return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR;
 }
 
+static SQInteger table_filter(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v,1);
+    SQTable *tbl = _table(o);
+    SQObjectPtr ret = SQTable::Create(_ss(v),0);
+
+    SQObjectPtr itr, key, val;
+    SQInteger nitr;
+    while((nitr = tbl->Next(false, itr, key, val)) != -1) {
+        itr = (SQInteger)nitr;
+
+        v->Push(o);
+        v->Push(key);
+        v->Push(val);
+        if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
+            return SQ_ERROR;
+        }
+        if(!SQVM::IsFalse(v->GetUp(-1))) {
+            _table(ret)->NewSlot(key, val);
+        }
+        v->Pop();
+    }
+
+    v->Push(ret);
+    return 1;
+}
+
+
 const SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
     {_SC("len"),default_delegate_len,1, _SC("t")},
     {_SC("rawget"),container_rawget,2, _SC("t")},
@@ -476,6 +511,7 @@ const SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
     {_SC("clear"),obj_clear,1, _SC(".")},
     {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},
     {_SC("getdelegate"),table_getdelegate,1, _SC(".")},
+    {_SC("filter"),table_filter,2, _SC("tc")},
     {NULL,(SQFUNCTION)0,0,NULL}
 };
 
@@ -542,9 +578,13 @@ static SQInteger array_resize(HSQUIRRELVM v)
     SQObject &nsize = stack_get(v, 2);
     SQObjectPtr fill;
     if(sq_isnumeric(nsize)) {
+        SQInteger sz = tointeger(nsize);
+        if (sz<0)
+          return sq_throwerror(v, _SC("resizing to negative length"));
+
         if(sq_gettop(v) > 2)
             fill = stack_get(v, 3);
-        _array(o)->Resize(tointeger(nsize),fill);
+        _array(o)->Resize(sz,fill);
         return 0;
     }
     return sq_throwerror(v, _SC("size must be a number"));
@@ -885,7 +925,12 @@ static SQInteger closure_pcall(HSQUIRRELVM v)
 
 static SQInteger 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 SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)

+ 3 - 2
src/modules/app_sqlang/squirrel/squirrel/sqcompiler.cpp

@@ -1171,9 +1171,10 @@ public:
         }
         _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
         if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
-        END_SCOPE();
-
+        
         END_BREAKBLE_BLOCK(continuetrg);
+
+		END_SCOPE();
     }
     void ForEachStatement()
     {

+ 1 - 1
src/modules/app_sqlang/squirrel/squirrel/sqfuncstate.cpp

@@ -120,7 +120,7 @@ void SQFuncState::Dump(SQFunctionProto *func)
     scprintf(_SC("SQInstruction sizeof %d\n"),(SQInt32)sizeof(SQInstruction));
     scprintf(_SC("SQObject sizeof %d\n"), (SQInt32)sizeof(SQObject));
     scprintf(_SC("--------------------------------------------------------------------\n"));
-    scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
+    scprintf(_SC("*****FUNCTION [%s]\n"),sq_type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
     scprintf(_SC("-----LITERALS\n"));
     SQObjectPtr refidx,key,val;
     SQInteger idx;

+ 1 - 1
src/modules/app_sqlang/squirrel/squirrel/sqlexer.cpp

@@ -383,7 +383,7 @@ SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)
                     break;
                     case _SC('U'):
                     case _SC('u'):  {
-                        const SQInteger maxdigits = x == 'u' ? 4 : 8;
+                        const SQInteger maxdigits = CUR_CHAR == 'u' ? 4 : 8;
                         SQChar temp[8 + 1];
                         ProcessStringHexEscape(temp, maxdigits);
                         SQChar *stemp;

+ 33 - 9
src/modules/app_sqlang/squirrel/squirrel/sqvm.cpp

@@ -744,7 +744,8 @@ exception_restore:
                         continue;
                     case OT_NATIVECLOSURE: {
                         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));
                         if(suspend){
                             _suspended = SQTrue;
                             _suspended_target = sarg0;
@@ -753,7 +754,7 @@ exception_restore:
                             outres = clo;
                             return true;
                         }
-                        if(sarg0 != -1) {
+                        if(sarg0 != -1 && !tailcall) {
                             STK(arg0) = clo;
                         }
                                            }
@@ -772,10 +773,10 @@ exception_restore:
                                 _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
                                 break;
                             case OT_NATIVECLOSURE:
-                                bool suspend;
+                                bool dummy;
                                 stkbase = _stackbase+arg2;
                                 _stack._vals[stkbase] = inst;
-                                _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
+                                _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo, -1, dummy, dummy));
                                 break;
                             default: break; //shutup GCC 4.x
                         }
@@ -1139,7 +1140,7 @@ void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
     _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 newtop = newbase + nargs + nclosure->_noutervalues;
@@ -1169,6 +1170,7 @@ bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newb
 
     if(!EnterFrame(newbase, newtop, false)) return false;
     ci->_closure  = nclosure;
+	ci->_target = target;
 
     SQInteger outers = nclosure->_noutervalues;
     for (SQInteger i = 0; i < outers; i++) {
@@ -1183,7 +1185,12 @@ bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newb
     _nnativecalls--;
 
     suspend = false;
-    if (ret == SQ_SUSPEND_FLAG) {
+	tailcall = false;
+	if (ret == SQ_TAILCALL_FLAG) {
+		tailcall = true;
+		return true;
+	}
+    else if (ret == SQ_SUSPEND_FLAG) {
         suspend = true;
     }
     else if (ret < 0) {
@@ -1202,6 +1209,23 @@ bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newb
     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_NO_MATCH   1
 #define FALLBACK_ERROR      2
@@ -1551,8 +1575,8 @@ SQInteger prevstackbase = _stackbase;
         return Execute(closure, nparams, stackbase, outres, raiseerror);
         break;
     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;
@@ -1723,7 +1747,7 @@ void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
         SQObjectPtr &obj=_stack[i];
         if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
         scprintf(_SC("[" _PRINT_INT_FMT "]:"),n);
-        switch(type(obj)){
+        switch(sq_type(obj)){
         case OT_FLOAT:          scprintf(_SC("FLOAT %.3f"),_float(obj));break;
         case OT_INTEGER:        scprintf(_SC("INTEGER " _PRINT_INT_FMT),_integer(obj));break;
         case OT_BOOL:           scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;

+ 3 - 1
src/modules/app_sqlang/squirrel/squirrel/sqvm.h

@@ -8,6 +8,7 @@
 #define MIN_STACK_OVERHEAD 15
 
 #define SQ_SUSPEND_FLAG -666
+#define SQ_TAILCALL_FLAG -777
 #define DONT_FALL_BACK 666
 //#define EXISTS_FALL_BACK -1
 
@@ -56,7 +57,8 @@ public:
     bool Init(SQVM *friendvm, SQInteger stacksize);
     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
-    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"
     bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
     bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);