Ver código fonte

More work on the implementation of goto statement, still need more work

mingodad 9 anos atrás
pai
commit
5d6b79f3bf

+ 71 - 7
SquiLu/samples/test-goto.nut

@@ -1,19 +1,82 @@
+local s5 = "done5";
+
 local function test10(x)
 local function test10(x)
 {
 {
 	print("goto start");
 	print("goto start");
 goto start;
 goto start;
 change:
 change:
 	x = 5;
 	x = 5;
-	print("change");
+	try
+	{
+		print("change");
+	}
+	catch(e)
+	{
+	}
+//goto dad;
 start:
 start:
 	print("start");
 	print("start");
 	if(x > 10)
 	if(x > 10)
 	{
 	{
-		print("x > 10");
-		goto done4;
-		goto change;
-		goto start;
-		return true;
+		try
+		{
+			goto p2;
+			print("change");
+			p2:
+			print("change p2");
+		}
+		catch(e)
+		{
+		}
+		while(true)
+		{
+			try
+			{
+				try
+				{
+				print("x > 10");
+				return "x > 10";
+				goto done2;
+				goto done5;
+				goto change;
+				goto start;
+				goto done4;
+				goto done3;
+				goto done;
+				return true;
+				}
+				catch(e)
+				{
+				}
+			}
+			catch(e)
+			{
+			}
+			break;
+		}
+	}
+	local z = 0;
+	while(z < 3)
+	{
+		++z;
+		try
+		{
+			print("while");
+			try
+			{
+				print("while2");
+				continue;
+				goto done4;
+				goto done3;
+				goto done;
+			}
+			catch(e)
+			{
+			}
+		}
+		catch(e)
+		{
+		}
 	}
 	}
 done:
 done:
 	return false;
 	return false;
@@ -28,4 +91,5 @@ done5:
 }
 }
 
 
 
 
-print(test10(23));
+print(test10(23));
+print("ok");

+ 126 - 10
SquiLu/squirrel/sqcompiler.cpp

@@ -39,9 +39,9 @@ struct SQExpState {
 #define MAX_COMPILER_ERROR_LEN 256
 #define MAX_COMPILER_ERROR_LEN 256
 
 
 struct SQScope {
 struct SQScope {
-	SQInteger outers;
-	SQInteger stacksize;
-	SQInteger nested;
+	SQInt32 stacksize;
+	SQInt16 outers;
+	SQInt16 nested;
 };
 };
 
 
 #define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \
 #define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \
@@ -61,6 +61,7 @@ struct SQScope {
 						} \
 						} \
 						_scope = __oldscope__; \
 						_scope = __oldscope__; \
 						_scope_consts.pop_back();\
 						_scope_consts.pop_back();\
+						EndScopeCheckGotoLabels(_scope);\
 					}
 					}
 
 
 #define END_SCOPE() {	SQInteger oldouters = _fs->_outers;\
 #define END_SCOPE() {	SQInteger oldouters = _fs->_outers;\
@@ -621,16 +622,18 @@ public:
                         _stringval(_sourcename), _lex.data->currentline, _lex.data->currentcolumn);
                         _stringval(_sourcename), _lex.data->currentline, _lex.data->currentcolumn);
 		    Lex(); //ignore for now
 		    Lex(); //ignore for now
 		    id = Expect(TK_IDENTIFIER);
 		    id = Expect(TK_IDENTIFIER);
+			SQGotoLabelsInfo info;
+			info.name = id;
+			info.line = _lex.data->currentline; //need to get line number here
 		    Expect(_SC(';'));
 		    Expect(_SC(';'));
 
 
             //if(_fs->_traps > 0)
             //if(_fs->_traps > 0)
 			//		_fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
 			//		_fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
 			//RESOLVE_OUTERS();
 			//RESOLVE_OUTERS();
-			_fs->AddInstruction(_OP_NOP, 0, 0); //for _OP_POPTRAP
-			_fs->AddInstruction(_OP_NOP, 0, 0); //for OUTERS
+			_fs->AddInstruction(_OP_NOP, _fs->_traps, 0); //for _OP_POPTRAP
+			_fs->AddInstruction(_OP_NOP, _scope.nested, 0); //for OUTERS
 			_fs->AddInstruction(_OP_JMP, 0, -1234);
 			_fs->AddInstruction(_OP_JMP, 0, -1234);
-			SQGotoLabelsInfo info;
-			info.name = id;
+			//instruction pos
 			info.pos = _fs->GetCurrentPos();
 			info.pos = _fs->GetCurrentPos();
 			_fs->_unresolvedgotos.push_back(info);
 			_fs->_unresolvedgotos.push_back(info);
             }
             }
@@ -791,7 +794,7 @@ public:
             if(lhtk == _SC(':'))
             if(lhtk == _SC(':'))
             {
             {
                 if(!_fs->_parent) Error(_SC("'label' has to be inside a function block"));
                 if(!_fs->_parent) Error(_SC("'label' has to be inside a function block"));
-                if(!_fs->AddGotoTarget(id)) Error(_SC("Label already declared"));
+                if(!_fs->AddGotoTarget(id, _lex.data->currentline)) Error(_SC("Label already declared"));
                 Warning(_SC("%s:%d:%d warning labels are only parsed right now\n"),
                 Warning(_SC("%s:%d:%d warning labels are only parsed right now\n"),
                         _stringval(_sourcename), _lex.data->currentline, _lex.data->currentcolumn);
                         _stringval(_sourcename), _lex.data->currentline, _lex.data->currentcolumn);
                 Lex(); //eat ':'
                 Lex(); //eat ':'
@@ -2531,6 +2534,85 @@ error:
 		_fs->_functions.push_back(func);
 		_fs->_functions.push_back(func);
 		_fs->PopChildState();
 		_fs->PopChildState();
 	}
 	}
+	bool ResolveGotLabel(SQInteger stack_pos, const SQGotoLabelsInfo &label)
+	{
+	    bool resolved = false;
+		for(int 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))
+            {
+                if(goto_info.pos < stack_pos)
+                {
+                    _lex.data->currentline = goto_info.line;
+                    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);
+                _fs->_unresolvedgotos.remove(i);
+            }
+		}
+		return resolved;
+	}
+	void EndScopeCheckGotoLabels(const SQScope &scope)
+	{
+	    //do we have declared any new label ?
+        if(_fs->_gototargets.size() && (_fs->_gototargets.top().pos >= scope.stacksize))
+        {
+            //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))
+                {
+                    _lex.data->currentline = label.line;
+                    Error(_SC("Label not resolved at this point '%s'"), _stringval(label.name));
+                }
+                _fs->_gototargets.pop_back();
+                if(_fs->_gototargets.empty())
+                {
+                    break;
+                }
+                label = _fs->_gototargets.top();
+            }
+        }
+	    //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)
 	void ResolveGotos(SQFuncState *funcstate)
 	{
 	{
 		while(funcstate->_unresolvedgotos.size() > 0) {
 		while(funcstate->_unresolvedgotos.size() > 0) {
@@ -2538,9 +2620,43 @@ error:
 			funcstate->_unresolvedgotos.pop_back();
 			funcstate->_unresolvedgotos.pop_back();
 			//set the jmp instruction
 			//set the jmp instruction
 			SQInteger target = funcstate->FindGotoTarget(goto_info.name);
 			SQInteger target = funcstate->FindGotoTarget(goto_info.name);
-			if(target < 0) Error(_SC("Label for goto not found '%s'"), _stringval(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 target_pos = funcstate->_gototargets[target].pos;
-			funcstate->SetIntructionParams(goto_info.pos, 0, target_pos - goto_info.pos, 0);
+			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);
 		}
 		}
 	}
 	}
 	void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
 	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 SQLineInfo { SQInteger _line;SQInteger _op; };
-struct SQGotoLabelsInfo { SQObjectPtr name; SQInteger pos; };
+struct SQGotoLabelsInfo { SQObjectPtr name; SQInt32 pos; SQInt32 line;};
 
 
 typedef sqvector<SQOuterVar> SQOuterVarVec;
 typedef sqvector<SQOuterVar> SQOuterVarVec;
 typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
 typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;

+ 3 - 1
SquiLu/squirrel/sqfuncstate.cpp

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

+ 3 - 3
SquiLu/squirrel/sqfuncstate.h

@@ -53,15 +53,13 @@ struct SQFuncState
 	SQObject CreateTable();
 	SQObject CreateTable();
 	bool IsConstant(const SQObject &name,SQObject &e);
 	bool IsConstant(const SQObject &name,SQObject &e);
 	SQInteger FindGotoTarget(const SQObject &name);
 	SQInteger FindGotoTarget(const SQObject &name);
-	bool AddGotoTarget(const SQObject &name);
+	bool AddGotoTarget(const SQObject &name, SQInteger line);
 	SQGotoLabelsInfoVec _unresolvedgotos;
 	SQGotoLabelsInfoVec _unresolvedgotos;
 	SQGotoLabelsInfoVec _gototargets;
 	SQGotoLabelsInfoVec _gototargets;
 	SQInteger _returnexp;
 	SQInteger _returnexp;
 	SQLocalVarInfoVec _vlocals;
 	SQLocalVarInfoVec _vlocals;
 	SQIntVec _targetstack;
 	SQIntVec _targetstack;
 	SQInteger _stacksize;
 	SQInteger _stacksize;
-	bool _varparams;
-	bool _bgenerator;
 	SQIntVec _unresolvedbreaks;
 	SQIntVec _unresolvedbreaks;
 	SQIntVec _unresolvedcontinues;
 	SQIntVec _unresolvedcontinues;
 	SQObjectPtrVec _functions;
 	SQObjectPtrVec _functions;
@@ -85,6 +83,8 @@ struct SQFuncState
 	SQInteger _traps; //contains number of nested exception traps
 	SQInteger _traps; //contains number of nested exception traps
 	SQInteger _outers;
 	SQInteger _outers;
 	bool _optimization;
 	bool _optimization;
+	bool _varparams;
+	bool _bgenerator;
 	SQSharedState *_sharedstate;
 	SQSharedState *_sharedstate;
 	sqvector<SQFuncState*> _childstates;
 	sqvector<SQFuncState*> _childstates;
 	SQInteger GetConstant(const SQObject &cons);
 	SQInteger GetConstant(const SQObject &cons);