Browse Source

Merge branch 'newbindenv'

albertodemichelis 4 years ago
parent
commit
d7c9103cc4
3 changed files with 61 additions and 18 deletions
  1. 45 15
      squirrel/sqcompiler.cpp
  2. 15 2
      squirrel/sqvm.cpp
  3. 1 1
      squirrel/sqvm.h

+ 45 - 15
squirrel/sqcompiler.cpp

@@ -842,8 +842,8 @@ public:
             _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
             Lex();ParseTableOrClass(_SC(','),_SC('}'));
             break;
-        case TK_FUNCTION: FunctionExp(_token);break;
-        case _SC('@'): FunctionExp(_token,true);break;
+        case TK_FUNCTION: FunctionExp();break;
+        case _SC('@'): FunctionExp(true);break;
         case TK_CLASS: Lex(); ClassExp();break;
         case _SC('-'):
             Lex();
@@ -989,10 +989,15 @@ public:
                 SQInteger tk = _token;
                 Lex();
                 SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
+				_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+				SQInteger boundtarget = 0xFF;
+				if (_token == _SC('[')) {
+					boundtarget = ParseBindEnv();
+				}
                 Expect(_SC('('));
-                _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
-                CreateFunction(id);
-                _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+                
+                CreateFunction(id, boundtarget);
+                _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, boundtarget);
                                 }
                                 break;
             case _SC('['):
@@ -1034,11 +1039,15 @@ public:
         SQObject varname;
         Lex();
         if( _token == TK_FUNCTION) {
+			SQInteger boundtarget = 0xFF;
             Lex();
-            varname = Expect(TK_IDENTIFIER);
+			varname = Expect(TK_IDENTIFIER);
+			if (_token == _SC('[')) {
+				boundtarget = ParseBindEnv();
+			}
             Expect(_SC('('));
-            CreateFunction(varname,false);
-            _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+            CreateFunction(varname,0xFF,false);
+            _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, boundtarget);
             _fs->PopTarget();
             _fs->PushLocalVariable(varname);
             return;
@@ -1310,9 +1319,13 @@ public:
             _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
             if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
         }
+		SQInteger boundtarget = 0xFF;
+		if (_token == _SC('[')) {
+			boundtarget = ParseBindEnv();
+		}
         Expect(_SC('('));
-        CreateFunction(id);
-        _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+        CreateFunction(id, boundtarget);
+        _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, boundtarget);
         EmitDerefOp(_OP_NEWSLOT);
         _fs->PopTarget();
     }
@@ -1438,12 +1451,26 @@ public:
             END_SCOPE();
         }
     }
-    void FunctionExp(SQInteger ftype,bool lambda = false)
+	SQInteger ParseBindEnv()
+	{
+		SQInteger boundtarget;
+		Lex();
+		Expression();
+		boundtarget = _fs->TopTarget();
+		Expect(_SC(']'));
+		return boundtarget;
+	}
+    void FunctionExp(bool lambda = false)
     {
-        Lex(); Expect(_SC('('));
+        Lex(); 
+		SQInteger boundtarget = 0xFF;
+		if (_token == _SC('[')) {
+			boundtarget = ParseBindEnv();
+		}
+		Expect(_SC('('));
         SQObjectPtr dummy;
-        CreateFunction(dummy,lambda);
-        _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
+        CreateFunction(dummy, boundtarget, lambda);
+        _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, boundtarget);
     }
     void ClassExp()
     {
@@ -1508,7 +1535,7 @@ public:
         }
         _es = es;
     }
-    void CreateFunction(SQObject &name,bool lambda = false)
+    void CreateFunction(SQObject &name,SQInteger boundtarget,bool lambda = false)
     {
         SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
         funcstate->_name = name;
@@ -1542,6 +1569,9 @@ public:
             }
         }
         Expect(_SC(')'));
+		if (boundtarget != 0xFF) {
+			_fs->PopTarget();
+		}
         for(SQInteger n = 0; n < defparams; n++) {
             _fs->PopTarget();
         }

+ 15 - 2
squirrel/sqvm.cpp

@@ -586,7 +586,7 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
 
 #define _GUARD(exp) { if(!exp) { SQ_THROW();} }
 
-bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
+bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func,SQInteger boundtarget)
 {
     SQInteger nouters;
     SQClosure *closure = SQClosure::Create(_ss(this), func,_table(_roottable)->GetWeakRef(OT_TABLE));
@@ -610,6 +610,19 @@ bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
             closure->_defaultparams[i] = _stack._vals[_stackbase + spos];
         }
     }
+	if (boundtarget != 0xFF) {
+		SQObjectPtr &val = _stack._vals[_stackbase + boundtarget];
+		SQObjectType t = sq_type(val);
+		if (t == OT_TABLE || t == OT_CLASS || t == OT_CLOSURE || t == OT_ARRAY) {
+			closure->_env = _refcounted(val)->GetWeakRef(t);
+			__ObjAddRef(closure->_env);
+		}
+		else {
+			Raise_Error(_SC("cannot bind a %s as environment object"), IdType2Name(t));
+			closure->Release();
+			return false;
+		}
+	}
     target = closure;
     return true;
 
@@ -1003,7 +1016,7 @@ exception_restore:
             case _OP_CLOSURE: {
                 SQClosure *c = ci->_closure._unVal.pClosure;
                 SQFunctionProto *fp = c->_function;
-                if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
+                if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto,arg2)) { SQ_THROW(); }
                 continue;
             }
             case _OP_YIELD:{

+ 1 - 1
squirrel/sqvm.h

@@ -103,7 +103,7 @@ public:
     _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
     _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
     _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
-    bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
+    bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func, SQInteger boundtarget);
     bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
     //return true if the loop is finished
     bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);