Просмотр исходного кода

The "goto" implementation is in a working state but still need more work.
We are no storing the label names and that is a problem when trying to dump the opcode.

mingodad 9 лет назад
Родитель
Сommit
035fb55be6

+ 2 - 1
SquiLu/samples/test-goto.nut

@@ -35,7 +35,7 @@ start:
 				try
 				{
 				print("x > 10");
-				return "x > 10";
+				//return "x > 10";
 				goto done2;
 				goto done5;
 				goto change;
@@ -48,6 +48,7 @@ start:
 				catch(e)
 				{
 				}
+				goto done4;
 			}
 			catch(e)
 			{

+ 57 - 96
SquiLu/squirrel/sqcompiler.cpp

@@ -61,7 +61,7 @@ struct SQScope {
 						} \
 						_scope = __oldscope__; \
 						_scope_consts.pop_back();\
-						EndScopeCheckGotoLabels(_scope);\
+						EndScopeCheckGotoLabels(_scope.stacksize);\
 					}
 
 #define END_SCOPE() {	SQInteger oldouters = _fs->_outers;\
@@ -625,13 +625,11 @@ public:
 			SQGotoLabelsInfo info;
 			info.name = id;
 			info.line = _lex.data->currentline; //need to get line number here
+			info.traps = _fs->_traps;
 		    Expect(_SC(';'));
 
-            //if(_fs->_traps > 0)
-			//		_fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
-			//RESOLVE_OUTERS();
-			_fs->AddInstruction(_OP_NOP, _fs->_traps, 0); //for _OP_POPTRAP
-			_fs->AddInstruction(_OP_NOP, _scope.nested, 0); //for OUTERS
+			RESOLVE_OUTERS();
+			_fs->AddInstruction(_OP_NOP, 0, 0); //for _OP_POPTRAP
 			_fs->AddInstruction(_OP_JMP, 0, -1234);
 			//instruction pos
 			info.pos = _fs->GetCurrentPos();
@@ -794,7 +792,7 @@ public:
             if(lhtk == _SC(':'))
             {
                 if(!_fs->_parent) Error(_SC("'label' has to be inside a function block"));
-                if(!_fs->AddGotoTarget(id, _lex.data->currentline)) Error(_SC("Label already declared"));
+                if(!_fs->AddGotoTarget(id, _lex.data->currentline, _fs->_traps)) Error(_SC("Label already declared"));
                 Warning(_SC("%s:%d:%d warning labels are only parsed right now\n"),
                         _stringval(_sourcename), _lex.data->currentline, _lex.data->currentcolumn);
                 Lex(); //eat ':'
@@ -2521,9 +2519,9 @@ error:
 		else {
 			Statement(false);
 		}
+		ResolveGotos(0, true);
 		funcstate->AddLineInfos(_lex.data->prevtoken == _SC('\n')?_lex.data->lasttokenline:_lex.data->currentline, _lineinfo, true);
         funcstate->AddInstruction(_OP_RETURN, -1);
-		ResolveGotos(funcstate);
 		funcstate->SetStackSize(0);
 
 		SQFunctionProto *func = funcstate->BuildProto();
@@ -2534,10 +2532,27 @@ error:
 		_fs->_functions.push_back(func);
 		_fs->PopChildState();
 	}
+	void AdjustGotoInstruction(const SQGotoLabelsInfo &goto_info, const SQGotoLabelsInfo &label)
+	{
+        SQInteger target_pos = label.pos;
+        SQInteger jump_pos = target_pos - goto_info.pos;
+        //set the jmp instruction
+
+        SQInteger poptraps = goto_info.traps - label.traps;
+        if(poptraps)
+        {
+            SQInstruction &i_op_poptrap = _fs->GetInstruction(goto_info.pos-1);
+            //printf("poptraps for %s = %d : %d\n", _stringval(label.name), (int)poptraps, (int)i_op_poptrap._arg0);
+            i_op_poptrap.op = _OP_POPTRAP;
+            i_op_poptrap._arg0 = poptraps;
+        }
+
+        _fs->SetIntructionParams(goto_info.pos, 0, jump_pos, 0);
+	}
 	bool ResolveGotLabel(SQInteger stack_pos, const SQGotoLabelsInfo &label)
 	{
 	    bool resolved = false;
-		for(int i = _fs->_unresolvedgotos.size()-1; i >= 0; --i) {
+		for(SQInteger i = _fs->_unresolvedgotos.size()-1; i >= 0; --i) {
 			SQGotoLabelsInfo goto_info = _fs->_unresolvedgotos[i];
 			//printf("ResolveGotLabel : %s : %s\n", _stringval(label.name), _stringval(goto_info.name));
 			if(_string(label.name) == _string(goto_info.name))
@@ -2548,53 +2563,48 @@ error:
                     Error(_SC("Goto can not jump to nested label '%s'"), _stringval(label.name));
                 }
                 resolved = true;
-                SQInteger target_pos = label.pos;
-                SQInteger jump_pos = target_pos - goto_info.pos;
-                //set the jmp instruction
-/*
-                SQInteger poptraps = 0, istart, iend;
-                if(jump_pos < 0)
-                {
-                    istart = target_pos;
-                    iend = goto_info.pos;
-                }
-                else
-                {
-                    istart = goto_info.pos;
-                    iend = target_pos;
-                }
-                for(SQInteger i=istart; i < iend; ++i)
-                {
-                    SQInstruction &instruction = _fs->GetInstruction(i);
-                    switch(instruction.op)
-                    {
-                        case _OP_PUSHTRAP: ++poptraps;break;
-                        //case _OP_POPTRAP: --poptraps;break;
-                    }
-                }
-                if(poptraps)
-                {
-                    SQInstruction &i_op_poptrap = _fs->GetInstruction(goto_info.pos-2);
-                    //printf("poptraps for %s = %d : %d\n", _stringval(label.name), (int)poptraps, (int)i_op_poptrap._arg0);
-                    i_op_poptrap.op = _OP_POPTRAP;
-                    i_op_poptrap._arg0 = poptraps;
-                }
-*/
-                _fs->SetIntructionParams(goto_info.pos, 0, jump_pos, 0);
+                AdjustGotoInstruction(goto_info, label);
                 _fs->_unresolvedgotos.remove(i);
             }
 		}
 		return resolved;
 	}
-	void EndScopeCheckGotoLabels(const SQScope &scope)
+	bool ResolveOneGoto(SQGotoLabelsInfo &goto_info)
+	{
+        for(SQInteger i = _fs->_gototargets.size()-1; i >= 0; --i) {
+            SQGotoLabelsInfo &label = _fs->_gototargets[i];
+            if(_string(label.name) == _string(goto_info.name))
+            {
+                AdjustGotoInstruction(goto_info, label);
+                return true;
+            }
+        }
+        return false;
+	}
+	void ResolveGotos(SQInteger stack_pos, bool raiseError=false)
+	{
+        if(_fs->_unresolvedgotos.size() && (_fs->_unresolvedgotos.top().pos >= stack_pos))
+        {
+            //we can resolve gotos upward here
+            for(SQInteger i = _fs->_unresolvedgotos.size()-1; i >= 0; --i) {
+                SQGotoLabelsInfo &goto_info = _fs->_unresolvedgotos[i];
+                if(!ResolveOneGoto(goto_info) && raiseError)
+                {
+                    _lex.data->currentline = goto_info.line;
+                    Error(_SC("Goto can not jump to undeclared label '%s'"), _stringval(goto_info.name));
+                }
+            }
+        }
+	}
+	void EndScopeCheckGotoLabels(SQInteger stack_pos)
 	{
 	    //do we have declared any new label ?
-        if(_fs->_gototargets.size() && (_fs->_gototargets.top().pos >= scope.stacksize))
+        if(_fs->_gototargets.size() && (_fs->_gototargets.top().pos >= stack_pos))
         {
             //any new label at this point should have a goto call inside/nested this block
             SQGotoLabelsInfo &label = _fs->_gototargets.top();
-            while(label.pos >= scope.stacksize) {
-                if(!ResolveGotLabel(scope.stacksize, label))
+            while(label.pos >= stack_pos) {
+                if(!ResolveGotLabel(stack_pos, label))
                 {
                     _lex.data->currentline = label.line;
                     Error(_SC("Label not resolved at this point '%s'"), _stringval(label.name));
@@ -2608,56 +2618,7 @@ error:
             }
         }
 	    //do we have declared any new goto ?
-        if(_fs->_unresolvedgotos.size() && (_fs->_unresolvedgotos.top().pos >= scope.stacksize))
-        {
-            //we can resolve gotos upward here
-        }
-	}
-	void ResolveGotos(SQFuncState *funcstate)
-	{
-		while(funcstate->_unresolvedgotos.size() > 0) {
-			SQGotoLabelsInfo goto_info = funcstate->_unresolvedgotos.back();
-			funcstate->_unresolvedgotos.pop_back();
-			//set the jmp instruction
-			SQInteger target = funcstate->FindGotoTarget(goto_info.name);
-			if(target < 0)
-            {
-                _lex.data->currentline = goto_info.line;
-                Error(_SC("Label for goto not found '%s'"), _stringval(goto_info.name));
-            }
-			SQInteger target_pos = funcstate->_gototargets[target].pos;
-			SQInteger jump_pos = target_pos - goto_info.pos;
-
-/*
-			SQInteger poptraps = 0, istart, iend;
-			if(jump_pos < 0)
-            {
-                istart = target_pos;
-                iend = goto_info.pos;
-            }
-            else
-            {
-                istart = goto_info.pos;
-                iend = target_pos;
-            }
-			for(SQInteger i=istart; i < iend; ++i)
-            {
-                SQInstruction &instruction = _fs->GetInstruction(i);
-                switch(instruction.op)
-                {
-                    case _OP_PUSHTRAP: ++poptraps;break;
-                    case _OP_POPTRAP: --poptraps;break;
-                }
-            }
-            if(poptraps)
-            {
-                SQInstruction &i_op_poptrap = _fs->GetInstruction(goto_info.pos-2);
-                i_op_poptrap.op = _OP_POPTRAP;
-                i_op_poptrap._arg0 = abs(poptraps);
-            }
-*/
-			funcstate->SetIntructionParams(goto_info.pos, 0, jump_pos, 0);
-		}
+	    ResolveGotos(stack_pos);
 	}
 	void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
 	{

+ 1 - 1
SquiLu/squirrel/sqfuncproto.h

@@ -66,7 +66,7 @@ struct SQLocalVarInfo
 };
 
 struct SQLineInfo { SQInteger _line;SQInteger _op; };
-struct SQGotoLabelsInfo { SQObjectPtr name; SQInt32 pos; SQInt32 line;};
+struct SQGotoLabelsInfo { SQObjectPtr name; SQInt32 pos; SQInt16 line; SQInt16 traps;};
 
 typedef sqvector<SQOuterVar> SQOuterVarVec;
 typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;

+ 2 - 1
SquiLu/squirrel/sqfuncstate.cpp

@@ -391,7 +391,7 @@ SQInteger SQFuncState::FindGotoTarget(const SQObject &name)
 	return -1;
 }
 
-bool SQFuncState::AddGotoTarget(const SQObject &name, SQInteger line)
+bool SQFuncState::AddGotoTarget(const SQObject &name, SQInteger line, SQInteger traps)
 {
     if(FindGotoTarget(name) >= 0) return false;
 	SQGotoLabelsInfo info;
@@ -399,6 +399,7 @@ bool SQFuncState::AddGotoTarget(const SQObject &name, SQInteger line)
 	info.name = name;
 	info.pos = GetCurrentPos();
 	info.line = line;
+	info.traps = traps;
 	_gototargets.push_back(info);
 	return true;
 }

+ 1 - 1
SquiLu/squirrel/sqfuncstate.h

@@ -53,7 +53,7 @@ struct SQFuncState
 	SQObject CreateTable();
 	bool IsConstant(const SQObject &name,SQObject &e);
 	SQInteger FindGotoTarget(const SQObject &name);
-	bool AddGotoTarget(const SQObject &name, SQInteger line);
+	bool AddGotoTarget(const SQObject &name, SQInteger line, SQInteger traps);
 	SQGotoLabelsInfoVec _unresolvedgotos;
 	SQGotoLabelsInfoVec _gototargets;
 	SQInteger _returnexp;