Przeglądaj źródła

Add an initial implementation of goto, still need more work.

mingodad 9 lat temu
rodzic
commit
ba83378ac1

+ 20 - 3
SquiLu/samples/test-goto.nut

@@ -1,14 +1,31 @@
 local function test10(x)
 local function test10(x)
 {
 {
-dente:
+	print("goto start");
+goto start;
+change:
+	x = 5;
+	print("change");
+start:
+	print("start");
 	if(x > 10)
 	if(x > 10)
 	{
 	{
-		goto dente;
-		goto done;
+		print("x > 10");
+		goto done4;
+		goto change;
+		goto start;
 		return true;
 		return true;
 	}
 	}
 done:
 done:
 	return false;
 	return false;
+done2:
+	return "done2";
+done3:
+	return "done3";
+done4:
+	return "done4";
+done5:
+	return "done5";
 }
 }
 
 
+
 print(test10(23));
 print(test10(23));

+ 41 - 15
SquiLu/squirrel/sqcompiler.cpp

@@ -614,6 +614,28 @@ public:
 				_fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize());
 				_fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize());
 			}
 			}
 			break;}
 			break;}
+		case TK_GOTO: {
+		    //error if outside any function
+			if(!_fs->_parent) Error(_SC("'goto' has to be in a function block"));
+		    Warning(_SC("%s:%d:%d warning goto is only parsed right now\n"),
+                        _stringval(_sourcename), _lex.data->currentline, _lex.data->currentcolumn);
+		    Lex(); //ignore for now
+		    id = Expect(TK_IDENTIFIER);
+		    Expect(_SC(';'));
+
+			/*
+			if(_fs->_breaktargets.top() > 0){
+				_fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
+			}
+			*/
+			RESOLVE_OUTERS();
+			_fs->AddInstruction(_OP_JMP, 0, -1234);
+			SQGotoLabelsInfo info;
+			info.name = id;
+			info.pos = _fs->GetCurrentPos();
+			_fs->_unresolvedgotos.push_back(info);
+            }
+			break;
 		case TK_BREAK:
 		case TK_BREAK:
 			if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
 			if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
 			if(_fs->_breaktargets.top() > 0){
 			if(_fs->_breaktargets.top() > 0){
@@ -745,14 +767,6 @@ public:
 		    goto start_again;
 		    goto start_again;
 		    break;
 		    break;
 
 
-		case TK_GOTO:
-		    Warning(_SC("%s:%d:%d warning goto is only parsed right now\n"),
-                        _stringval(_sourcename), _lex.data->currentline, _lex.data->currentcolumn);
-		    Lex(); //ignore for now
-		    id = Expect(TK_IDENTIFIER);
-		    Expect(_SC(';'));
-		    break;
-
         case TK_TEMPLATE: {
         case TK_TEMPLATE: {
             Lex(); //ignore for now
             Lex(); //ignore for now
             Expect(_SC('<'));
             Expect(_SC('<'));
@@ -773,16 +787,18 @@ public:
         }
         }
 
 
         case TK_IDENTIFIER:{
         case TK_IDENTIFIER:{
+            id = _fs->CreateString(_lex.data->svalue);
             SQInteger lhtk = _lex.LookaheadLex();
             SQInteger lhtk = _lex.LookaheadLex();
             if(lhtk == _SC(':'))
             if(lhtk == _SC(':'))
             {
             {
+                if(!_fs->_parent) Error(_SC("'label' has to be inside a function block"));
+                if(!_fs->AddGotoTarget(id)) 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);
-                LabelDeclStatement();
+                Lex(); //eat ':'
                 Lex();
                 Lex();
                 break;
                 break;
             }
             }
-            id = _fs->CreateString(_lex.data->svalue);
             if(CheckTypeName(id)) //C/C++ type declaration;
             if(CheckTypeName(id)) //C/C++ type declaration;
             {
             {
                 if(lhtk != _SC('.'))
                 if(lhtk != _SC('.'))
@@ -1686,11 +1702,6 @@ function_params_decl:
 	    LocalDeclStatement();
 	    LocalDeclStatement();
 	    _is_parsing_extern = false;
 	    _is_parsing_extern = false;
 	}
 	}
-	void LabelDeclStatement()
-	{
-	    Lex();
-	    return; //ignore for now
-	}
 	#define CHECK_REF_DECLARATION(tk) if(tk == _SC('&')){is_reference_declaration = true;Lex();}
 	#define CHECK_REF_DECLARATION(tk) if(tk == _SC('&')){is_reference_declaration = true;Lex();}
 	void LocalDeclStatement()
 	void LocalDeclStatement()
 	{
 	{
@@ -2510,6 +2521,7 @@ error:
 		}
 		}
 		funcstate->AddLineInfos(_lex.data->prevtoken == _SC('\n')?_lex.data->lasttokenline:_lex.data->currentline, _lineinfo, true);
 		funcstate->AddLineInfos(_lex.data->prevtoken == _SC('\n')?_lex.data->lasttokenline:_lex.data->currentline, _lineinfo, true);
         funcstate->AddInstruction(_OP_RETURN, -1);
         funcstate->AddInstruction(_OP_RETURN, -1);
+		ResolveGotos(funcstate);
 		funcstate->SetStackSize(0);
 		funcstate->SetStackSize(0);
 
 
 		SQFunctionProto *func = funcstate->BuildProto();
 		SQFunctionProto *func = funcstate->BuildProto();
@@ -2520,6 +2532,20 @@ error:
 		_fs->_functions.push_back(func);
 		_fs->_functions.push_back(func);
 		_fs->PopChildState();
 		_fs->PopChildState();
 	}
 	}
+	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) Error(_SC("Label not found '%s'"), _stringval(goto_info.name));
+			SQInteger target_pos = funcstate->_gototargets[target].pos;
+			if(target_pos > goto_info.pos) target_pos = target_pos - goto_info.pos;
+			else target_pos = -1 * (goto_info.pos - target_pos);
+			funcstate->SetIntructionParams(goto_info.pos, 0, target_pos, 0);
+		}
+	}
 	void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
 	void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
 	{
 	{
 		while(ntoresolve > 0) {
 		while(ntoresolve > 0) {

+ 186 - 184
SquiLu/squirrel/sqfuncproto.h

@@ -1,193 +1,195 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQFUNCTION_H_
-#define _SQFUNCTION_H_
-
-#include "sqopcodes.h"
-
-enum SQOuterType {
-	otLOCAL = 0,
-	otOUTER = 1
-};
-
-struct SQOuterVar
-{
-
-	SQOuterVar(){}
-	SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
-	{
-		_name = name;
-		_src=src;
-		_type=t;
-	}
-	SQOuterVar(const SQOuterVar &ov)
-	{
-		_type=ov._type;
-		_src=ov._src;
-		_name=ov._name;
-	}
-	SQOuterType _type;
-	SQObjectPtr _name;
-	SQObjectPtr _src;
-};
-
-#define _VAR_ANY			0x00000001
-#define _VAR_INTEGER		0x00000002
-#define _VAR_FLOAT			0x00000004
-#define _VAR_BOOL			0x00000008
-#define _VAR_STRING			0x00000010
-#define _VAR_TABLE			0x00000020
-#define _VAR_ARRAY			0x00000040
-#define _VAR_CLOSURE		0x00000080
-#define _VAR_CLASS			0x00000100
-#define _VAR_REFERENCE  	0x00000200
-#define _VAR_CONST  		0x00000400
-
-struct SQLocalVarInfo
-{
+/*	see copyright notice in squirrel.h */
+#ifndef _SQFUNCTION_H_
+#define _SQFUNCTION_H_
+
+#include "sqopcodes.h"
+
+enum SQOuterType {
+	otLOCAL = 0,
+	otOUTER = 1
+};
+
+struct SQOuterVar
+{
+
+	SQOuterVar(){}
+	SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
+	{
+		_name = name;
+		_src=src;
+		_type=t;
+	}
+	SQOuterVar(const SQOuterVar &ov)
+	{
+		_type=ov._type;
+		_src=ov._src;
+		_name=ov._name;
+	}
+	SQOuterType _type;
+	SQObjectPtr _name;
+	SQObjectPtr _src;
+};
+
+#define _VAR_ANY			0x00000001
+#define _VAR_INTEGER		0x00000002
+#define _VAR_FLOAT			0x00000004
+#define _VAR_BOOL			0x00000008
+#define _VAR_STRING			0x00000010
+#define _VAR_TABLE			0x00000020
+#define _VAR_ARRAY			0x00000040
+#define _VAR_CLOSURE		0x00000080
+#define _VAR_CLASS			0x00000100
+#define _VAR_REFERENCE  	0x00000200
+#define _VAR_CONST  		0x00000400
+
+struct SQLocalVarInfo
+{
 	SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0),
 	SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0),
-        _type(_VAR_ANY),_scope(0) {}
-	SQLocalVarInfo(const SQLocalVarInfo &lvi)
-	{
-		_name=lvi._name;
-		_type_name=lvi._type_name;
-		_start_op=lvi._start_op;
-		_end_op=lvi._end_op;
+        _type(_VAR_ANY),_scope(0) {}
+	SQLocalVarInfo(const SQLocalVarInfo &lvi)
+	{
+		_name=lvi._name;
+		_type_name=lvi._type_name;
+		_start_op=lvi._start_op;
+		_end_op=lvi._end_op;
 		_pos=lvi._pos;
 		_pos=lvi._pos;
-		_type=lvi._type;
+		_type=lvi._type;
 		_scope=lvi._scope;
 		_scope=lvi._scope;
-	}
-	SQObjectPtr _name;
-	SQObjectPtr _type_name;
-	SQUnsignedInteger _start_op;
-	SQUnsignedInteger _end_op;
-	SQUnsignedInteger _pos;
-	unsigned short _type;
+	}
+	SQObjectPtr _name;
+	SQObjectPtr _type_name;
+	SQUnsignedInteger _start_op;
+	SQUnsignedInteger _end_op;
+	SQUnsignedInteger _pos;
+	unsigned short _type;
 	unsigned short _scope;
 	unsigned short _scope;
-};
-
-struct SQLineInfo { SQInteger _line;SQInteger _op; };
-
-typedef sqvector<SQOuterVar> SQOuterVarVec;
-typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
-typedef sqvector<SQLineInfo> SQLineInfoVec;
-
+};
+
+struct SQLineInfo { SQInteger _line;SQInteger _op; };
+struct SQGotoLabelsInfo { SQObjectPtr name; SQInteger pos; };
+
+typedef sqvector<SQOuterVar> SQOuterVarVec;
+typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
+typedef sqvector<SQLineInfo> SQLineInfoVec;
+typedef sqvector<SQGotoLabelsInfo> SQGotoLabelsInfoVec;
+
 #define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) \
 #define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) \
-        (sizeof(SQFunctionProto) \
-		+((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
+        (sizeof(SQFunctionProto) \
+		+((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
 		+(nparams*sizeof(SQObjectPtr))+(/*param_types*/nparams*sizeof(SQObjectPtr)) \
 		+(nparams*sizeof(SQObjectPtr))+(/*param_types*/nparams*sizeof(SQObjectPtr)) \
-        +(nfuncs*sizeof(SQObjectPtr)) \
-		+(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
-		+(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))
-
-
-struct SQFunctionProto : public CHAINABLE_OBJ
-{
-private:
-	SQFunctionProto(SQSharedState *ss);
-	~SQFunctionProto();
-
-public:
-	static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions,
-		SQInteger nliterals,SQInteger nparameters,
-		SQInteger nfunctions,SQInteger noutervalues,
-		SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
-	{
-		SQFunctionProto *f;
-		//I compact the whole class and members in a single memory allocation
-		f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
-		new (f) SQFunctionProto(ss);
+        +(nfuncs*sizeof(SQObjectPtr)) \
+		+(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
+		+(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))
+
+
+struct SQFunctionProto : public CHAINABLE_OBJ
+{
+private:
+	SQFunctionProto(SQSharedState *ss);
+	~SQFunctionProto();
+
+public:
+	static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions,
+		SQInteger nliterals,SQInteger nparameters,
+		SQInteger nfunctions,SQInteger noutervalues,
+		SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
+	{
+		SQFunctionProto *f;
+		//I compact the whole class and members in a single memory allocation
+		f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
+		new (f) SQFunctionProto(ss);
 		f->_ninstructions = ninstructions;
 		f->_ninstructions = ninstructions;
-		//literals start at then end of _instructions
-		f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];
-		f->_nliterals = nliterals;
-		//parameters start at then end of _literals
-		f->_parameters = (SQObjectPtr*)&f->_literals[nliterals];
+		//literals start at then end of _instructions
+		f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];
+		f->_nliterals = nliterals;
+		//parameters start at then end of _literals
+		f->_parameters = (SQObjectPtr*)&f->_literals[nliterals];
 		f->_nparameters = nparameters;
 		f->_nparameters = nparameters;
-		//the same as above repeat till the end
-		f->_parameters_type = (SQObjectPtr*)&f->_parameters[nparameters];
-		f->_functions = (SQObjectPtr*)&f->_parameters_type[nparameters];
-		f->_nfunctions = nfunctions;
-		f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];
-		f->_noutervalues = noutervalues;
-		f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];
-		f->_nlineinfos = nlineinfos;
-		f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
-		f->_nlocalvarinfos = nlocalvarinfos;
-		f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];
-		f->_ndefaultparams = ndefaultparams;
-
-		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);
-		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);
-		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters_type);
-		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions);
-		_CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);
-		//_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
-		_CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
-		return f;
-	}
-	void Release(){
-		_DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
-		_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
-		_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters_type);
-		_DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
-		_DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
-		//_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
-		_DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
-		SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
-		this->~SQFunctionProto();
-		sq_vm_free(this,size);
-	}
-
-	const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
-	SQInteger GetLine(SQInstruction *curr);
+		//the same as above repeat till the end
+		f->_parameters_type = (SQObjectPtr*)&f->_parameters[nparameters];
+		f->_functions = (SQObjectPtr*)&f->_parameters_type[nparameters];
+		f->_nfunctions = nfunctions;
+		f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];
+		f->_noutervalues = noutervalues;
+		f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];
+		f->_nlineinfos = nlineinfos;
+		f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
+		f->_nlocalvarinfos = nlocalvarinfos;
+		f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];
+		f->_ndefaultparams = ndefaultparams;
+
+		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);
+		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);
+		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters_type);
+		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions);
+		_CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);
+		//_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
+		_CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
+		return f;
+	}
+	void Release(){
+		_DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
+		_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
+		_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters_type);
+		_DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
+		_DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
+		//_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
+		_DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
+		SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
+		this->~SQFunctionProto();
+		sq_vm_free(this,size);
+	}
+
+	const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
+	SQInteger GetLine(SQInstruction *curr);
 	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
 	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
-	bool SaveAsSource(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
-	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
-
-#ifdef SQ_JIT_LLVM
-	void JitCompile();
-#endif
-
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); }
-	SQObjectType GetType() {return OT_FUNCPROTO;}
-#endif
-	SQObjectPtr _sourcename;
-	SQObjectPtr _name;
-	SQObjectPtr _return_type;
-    SQInteger _stacksize;
-	bool _bgenerator;
-	SQInteger _varparams;
-
-#ifdef SQ_JIT_LLVM
-	llvm::Function* _jitfunction;
-#endif
-
-	SQInteger _nlocalvarinfos;
-	SQLocalVarInfo *_localvarinfos;
-
-	SQInteger _nlineinfos;
-	SQLineInfo *_lineinfos;
-
-	SQInteger _nliterals;
-	SQObjectPtr *_literals;
-
-	SQInteger _nparameters;
-	SQObjectPtr *_parameters;
-	SQObjectPtr *_parameters_type;
-
-	SQInteger _nfunctions;
-	SQObjectPtr *_functions;
-
-	SQInteger _noutervalues;
-	SQOuterVar *_outervalues;
-
-	SQInteger _ndefaultparams;
-	SQInteger *_defaultparams;
-
-	SQInteger _ninstructions;
-	SQInstruction _instructions[1];
-};
-
-#endif //_SQFUNCTION_H_
+	bool SaveAsSource(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
+
+#ifdef SQ_JIT_LLVM
+	void JitCompile();
+#endif
+
+#ifndef NO_GARBAGE_COLLECTOR
+	void Mark(SQCollectable **chain);
+	void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); }
+	SQObjectType GetType() {return OT_FUNCPROTO;}
+#endif
+	SQObjectPtr _sourcename;
+	SQObjectPtr _name;
+	SQObjectPtr _return_type;
+    SQInteger _stacksize;
+	bool _bgenerator;
+	SQInteger _varparams;
+
+#ifdef SQ_JIT_LLVM
+	llvm::Function* _jitfunction;
+#endif
+
+	SQInteger _nlocalvarinfos;
+	SQLocalVarInfo *_localvarinfos;
+
+	SQInteger _nlineinfos;
+	SQLineInfo *_lineinfos;
+
+	SQInteger _nliterals;
+	SQObjectPtr *_literals;
+
+	SQInteger _nparameters;
+	SQObjectPtr *_parameters;
+	SQObjectPtr *_parameters_type;
+
+	SQInteger _nfunctions;
+	SQObjectPtr *_functions;
+
+	SQInteger _noutervalues;
+	SQOuterVar *_outervalues;
+
+	SQInteger _ndefaultparams;
+	SQInteger *_defaultparams;
+
+	SQInteger _ninstructions;
+	SQInstruction _instructions[1];
+};
+
+#endif //_SQFUNCTION_H_

+ 18 - 0
SquiLu/squirrel/sqfuncstate.cpp

@@ -383,6 +383,24 @@ void SQFuncState::AddParameterTypeName(const SQChar *type_name)
 	if(type_name) AddParameterTypeName(CreateString(type_name, scstrlen(type_name)));
 	if(type_name) AddParameterTypeName(CreateString(type_name, scstrlen(type_name)));
 }
 }
 
 
+SQInteger SQFuncState::FindGotoTarget(const SQObject &name)
+{
+	for(size_t i=0, len=_gototargets.size(); i < len; ++i){
+        if(_string(_gototargets[i].name) == _string(name)) return i;
+	}
+	return -1;
+}
+
+bool SQFuncState::AddGotoTarget(const SQObject &name)
+{
+    if(FindGotoTarget(name) >= 0) return false;
+	SQGotoLabelsInfo info;
+	info.name = name;
+	info.pos = GetCurrentPos();
+	_gototargets.push_back(info);
+	return true;
+}
+
 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
 void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
 {
 {
 	if(_lastline!=line || force){
 	if(_lastline!=line || force){

+ 4 - 0
SquiLu/squirrel/sqfuncstate.h

@@ -52,6 +52,10 @@ struct SQFuncState
 	SQObject CreateString(const SQChar *s,SQInteger len = -1);
 	SQObject CreateString(const SQChar *s,SQInteger len = -1);
 	SQObject CreateTable();
 	SQObject CreateTable();
 	bool IsConstant(const SQObject &name,SQObject &e);
 	bool IsConstant(const SQObject &name,SQObject &e);
+	SQInteger FindGotoTarget(const SQObject &name);
+	bool AddGotoTarget(const SQObject &name);
+	SQGotoLabelsInfoVec _unresolvedgotos;
+	SQGotoLabelsInfoVec _gototargets;
 	SQInteger _returnexp;
 	SQInteger _returnexp;
 	SQLocalVarInfoVec _vlocals;
 	SQLocalVarInfoVec _vlocals;
 	SQIntVec _targetstack;
 	SQIntVec _targetstack;