Quellcode durchsuchen

Added two new api functions "sq_setfenv" and "sq_getfenv" the first sets a function environment with optionally cloning it, the second gets (push on stack) a function env with the option to push the roottable when the env is null.
Added the same functions to the language "setenv" and "getenv".

Notice that there is a problem with nested functions inside instance methods, the outer variables are not recognized if they are instance values.

mingodad vor 13 Jahren
Ursprung
Commit
ad3e5f5c6c
3 geänderte Dateien mit 63 neuen und 9 gelöschten Zeilen
  1. 4 2
      include/squirrel.h
  2. 35 6
      squirrel/sqapi.cpp
  3. 24 1
      squirrel/sqbaselib.cpp

+ 4 - 2
include/squirrel.h

@@ -373,7 +373,9 @@ SQUIRREL_API void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity);
 SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);
 SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);
 SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
 SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
 SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
 SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
-SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_setfenv(HSQUIRRELVM v,SQInteger idx, SQBool cloning);
+SQUIRREL_API SQRESULT sq_getfenv(HSQUIRRELVM v,SQInteger idx, SQBool roottable_when_null);
+SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
 SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len);
 SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len);
 SQUIRREL_API void sq_pushfstring(HSQUIRRELVM v,const SQChar *fmt, ...);
 SQUIRREL_API void sq_pushfstring(HSQUIRRELVM v,const SQChar *fmt, ...);
 SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f);
 SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f);
@@ -401,7 +403,7 @@ SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointe
 SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
 SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
 SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
 SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
 SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
 SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
-SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
+SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
 SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
 SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
 SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi);
 SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi);
 SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);
 SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);

+ 35 - 6
squirrel/sqapi.cpp

@@ -485,7 +485,7 @@ SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *ty
 	return SQ_OK;
 	return SQ_OK;
 }
 }
 
 
-SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
+SQRESULT sq_setfenv(HSQUIRRELVM v,SQInteger idx, SQBool cloning)
 {
 {
 	SQObjectPtr &o = stack_get(v,idx);
 	SQObjectPtr &o = stack_get(v,idx);
 	if(!sq_isnativeclosure(o) &&
 	if(!sq_isnativeclosure(o) &&
@@ -499,7 +499,7 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
 	SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env));
 	SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env));
 	SQObjectPtr ret;
 	SQObjectPtr ret;
 	if(sq_isclosure(o)) {
 	if(sq_isclosure(o)) {
-		SQClosure *c = _closure(o)->Clone();
+		SQClosure *c = cloning ? _closure(o)->Clone() : _closure(o);
 		__ObjRelease(c->_env);
 		__ObjRelease(c->_env);
 		c->_env = w;
 		c->_env = w;
 		__ObjAddRef(c->_env);
 		__ObjAddRef(c->_env);
@@ -510,20 +510,49 @@ SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
 		ret = c;
 		ret = c;
 	}
 	}
 	else { //then must be a native closure
 	else { //then must be a native closure
-		SQNativeClosure *c = _nativeclosure(o)->Clone();
+		SQNativeClosure *c = cloning ? _nativeclosure(o)->Clone() : _nativeclosure(o);
 		__ObjRelease(c->_env);
 		__ObjRelease(c->_env);
 		c->_env = w;
 		c->_env = w;
 		__ObjAddRef(c->_env);
 		__ObjAddRef(c->_env);
 		ret = c;
 		ret = c;
 	}
 	}
 	v->Pop();
 	v->Pop();
-	v->Push(ret);
+	if(cloning) v->Push(ret);
+	return SQ_OK;
+}
+
+SQRESULT sq_getfenv(HSQUIRRELVM v,SQInteger idx, SQBool roottable_when_null)
+{
+	SQObjectPtr &o = stack_get(v,idx);
+	if(!sq_isnativeclosure(o) &&
+		!sq_isclosure(o))
+		return sq_throwerror(v,_SC("the source is not a closure"));
+	if(sq_isclosure(o)) {
+	    if(_closure(o)->_env) v->Push(_closure(o)->_env);
+	    else {
+	        if(roottable_when_null) sq_pushroottable(v);
+	        else sq_pushnull(v);
+	    }
+	}
+	else { //then must be a native closure
+	    if(_nativeclosure(o)->_env) v->Push(_nativeclosure(o)->_env);
+	    else {
+	        if(roottable_when_null) sq_pushroottable(v);
+	        else sq_pushnull(v);
+	    }
+	}
 	return SQ_OK;
 	return SQ_OK;
 }
 }
 
 
+SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
+{
+    return sq_setfenv(v, idx, SQTrue);
+}
+
 SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx)
 SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx)
 {
 {
-	SQObjectPtr &o = stack_get(v,idx);
+	SQObjectPtr &o = stack_get(v,idx);
+
 	if(!sq_isnativeclosure(o) &&
 	if(!sq_isnativeclosure(o) &&
 		!sq_isclosure(o))
 		!sq_isclosure(o))
 		return sq_throwerror(v,_SC("the target is not a closure"));
 		return sq_throwerror(v,_SC("the target is not a closure"));
@@ -1345,7 +1374,7 @@ void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)
 		}
 		}
 	}
 	}
 }
 }
-
+
 void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)
 void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)
 {
 {
 	_ss(v)->_compilererrorhandler = f;
 	_ss(v)->_compilererrorhandler = f;

+ 24 - 1
squirrel/sqbaselib.cpp

@@ -1207,7 +1207,15 @@ static SQRESULT string_gmatch(HSQUIRRELVM v)
             0, 0, 0, 0);
             0, 0, 0, 0);
     if(ms.error) return sq_throwerror(v, ms.error);
     if(ms.error) return sq_throwerror(v, ms.error);
     if(ms.level){
     if(ms.level){
-        sq_pushstring(v, ms.capture[0].init, ms.capture[0].len);
+        if(ms.level == 1) sq_pushstring(v, ms.capture[0].init, ms.capture[0].len);
+        else {
+            sq_newarray(v, ms.level);
+            for(int i=0; i < ms.level; ++i){
+                sq_pushinteger(v, i);
+                sq_pushstring(v, ms.capture[i].init, ms.capture[i].len);
+                sq_rawset(v, -3);
+            }
+        }
     } else {
     } else {
         if(ms.end_pos > ms.start_pos) sq_pushstring(v, src + ms.start_pos, ms.end_pos-ms.start_pos+1);
         if(ms.end_pos > ms.start_pos) sq_pushstring(v, src + ms.start_pos, ms.end_pos-ms.start_pos+1);
         else sq_pushnull(v);
         else sq_pushnull(v);
@@ -1705,6 +1713,19 @@ static SQInteger closure_bindenv(HSQUIRRELVM v)
 		return SQ_ERROR;
 		return SQ_ERROR;
 	return 1;
 	return 1;
 }
 }
+
+static SQInteger closure_setenv(HSQUIRRELVM v)
+{
+	if(SQ_FAILED(sq_setfenv(v,1, SQFalse)))
+		return SQ_ERROR;
+	return 0;
+}
+static SQInteger closure_getenv(HSQUIRRELVM v)
+{
+	if(SQ_FAILED(sq_getfenv(v,1, SQFalse)))
+		return SQ_ERROR;
+	return 1;
+}
 
 
 static SQInteger closure_getinfos(HSQUIRRELVM v) {
 static SQInteger closure_getinfos(HSQUIRRELVM v) {
 	SQObject o = stack_get(v,1);
 	SQObject o = stack_get(v,1);
@@ -1760,6 +1781,8 @@ SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
 	{_SC("weakref"),obj_delegate_weakref,1, NULL },
 	{_SC("weakref"),obj_delegate_weakref,1, NULL },
 	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
 	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
 	{_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},
 	{_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},
+	{_SC("setenv"),closure_setenv,2, _SC("c x|y|t")},
+	{_SC("getenv"),closure_getenv,1, _SC("c")},
 	{_SC("getinfos"),closure_getinfos,1, _SC("c")},
 	{_SC("getinfos"),closure_getinfos,1, _SC("c")},
 	{0,0}
 	{0,0}
 };
 };