예제 #1
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		// forstat -> FOR (fornum | forlist) END
		private void ForStat( int line )
		{
			var fs = CurFunc;
			var block = new BlockCnt();
			EnterBlock( fs, block, true );
			Lexer.Next(); // skip `for'
			string varname = CheckName();
			switch( Lexer.Token.TokenType )
			{
				case (int)'=': ForNum( varname, line ); break;
				case (int)',': case (int)TK.IN: ForList( varname ); break;
				default: Lexer.SyntaxError("'=' or 'in' expected"); break;
			}
			CheckMatch( (int)TK.END, (int)TK.FOR, line );
			LeaveBlock( fs );
		}
예제 #2
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		// test_then_block -> [IF | ELSEIF] cond THEN block
		private int TestThenBlock( int escapeList )
		{
			var fs = CurFunc;
			var block = new BlockCnt();
			int jf; // instruction to skip `then' code (if condition is false)

			// skip IF or ELSEIF
			Lexer.Next();

			// read condition
			var v = new ExpDesc();
			Expr( v );

			CheckNext( (int)TK.THEN );
			if( Lexer.Token.TokenType == (int)TK.GOTO ||
				Lexer.Token.TokenType == (int)TK.BREAK )
			{
				// will jump to label if condition is true
				Coder.GoIfFalse( CurFunc, v );

				// must enter block before `goto'
				EnterBlock( fs, block, false );

				// handle goto/break
				GotoStat( v.ExitTrue );

				// skip other no-op statements
				SkipNoOpStat();

				// `goto' is the entire block?
				if( BlockFollow( false ) )
				{
					LeaveBlock( fs );
					return escapeList;
				}
				else
				{
					jf = Coder.Jump( fs );
				}
			}
			// regular case (not goto/break)
			else
			{
				// skip over block if condition is false
				Coder.GoIfTrue( CurFunc, v );
				EnterBlock( fs, block, false );
				jf = v.ExitFalse;
			}

			// `then' part
			StatList();
			LeaveBlock( fs );

			// followed by `else' or `elseif'
			if( Lexer.Token.TokenType == (int)TK.ELSE ||
				Lexer.Token.TokenType == (int)TK.ELSEIF )
			{
				// must jump over it
				escapeList = Coder.Concat( fs, escapeList, Coder.Jump(fs) );
			}
			Coder.PatchToHere( fs, jf );
			return escapeList;
		}
예제 #3
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		// repeatstat -> REPEAT block UNTIL cond
		private void RepeatStat( int line )
		{
			var fs = CurFunc;
			int repeatInit = Coder.GetLabel( fs );
			var blockLoop  = new BlockCnt();
			var blockScope = new BlockCnt();
			EnterBlock( fs, blockLoop, true );
			EnterBlock( fs, blockScope, false );
			Lexer.Next();
			StatList();
			CheckMatch( (int)TK.UNTIL, (int)TK.REPEAT, line );
			int condExit = Cond();
			if( blockScope.HasUpValue )
			{
				Coder.PatchClose( fs, condExit, blockScope.NumActVar );
			}
			LeaveBlock( fs );
			Coder.PatchList( fs, condExit, repeatInit ); // close the loop
			LeaveBlock( fs );
		}
예제 #4
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		// forbody -> DO block
		private void ForBody( int t, int line, int nvars, bool isnum )
		{
			var fs = CurFunc;
			var block = new BlockCnt();
			AdjustLocalVars( 3 ); // control variables
			CheckNext( (int)TK.DO );
			int prep = isnum ? Coder.CodeAsBx( fs, OpCode.OP_FORPREP, t, Coder.NO_JUMP )
				: Coder.Jump( fs );
			EnterBlock( fs, block, false );
			AdjustLocalVars( nvars );
			Coder.ReserveRegs( fs, nvars );
			Block();
			LeaveBlock( fs );
			Coder.PatchToHere( fs, prep );

			int endfor;
			if( isnum ) // numeric for?
			{
				endfor = Coder.CodeAsBx( fs, OpCode.OP_FORLOOP, t, Coder.NO_JUMP );
			}
			else // generic for
			{
				Coder.CodeABC( fs, OpCode.OP_TFORCALL, t, 0, nvars );
				Coder.FixLine( fs, line );
				endfor = Coder.CodeAsBx( fs, OpCode.OP_TFORLOOP, t+2, Coder.NO_JUMP );
			}
			Coder.PatchList( fs, endfor, prep+1 );
			Coder.FixLine( fs, line );
		}
예제 #5
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		private void EnterBlock( FuncState fs, BlockCnt block, bool isLoop )
		{
			block.IsLoop 		= isLoop;
			block.NumActVar 	= fs.NumActVar;
			block.FirstLabel 	= ActiveLabels.Count;
			block.FirstGoto 	= PendingGotos.Count;
			block.HasUpValue 	= false;
			block.Previous 		= fs.Block;
			fs.Block 			= block;
			Utl.Assert( fs.FreeReg == fs.NumActVar );
		}
예제 #6
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		// whilestat -> WHILE cond DO block END
		private void WhileStat( int line )
		{
			var fs = CurFunc;
			var block = new BlockCnt();

			Lexer.Next(); // skip WHILE
			int whileInit = Coder.GetLabel( fs );
			int condExit = Cond();
			EnterBlock( fs, block, true );
			CheckNext( (int)TK.DO );
			Block();
			Coder.JumpTo( fs, whileInit );
			CheckMatch( (int)TK.END, (int)TK.WHILE, line );
			LeaveBlock( fs );
			Coder.PatchToHere( fs, condExit );
		}
예제 #7
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		// "export" pending gotos to outer level, to check them against
		// outer labels; if the block being exited has upvalues, and
		// the goto exits the scope of any variable (which can be the
		// upvalue), close those variables being exited.
		private void MoveGotosOut( FuncState fs, BlockCnt block )
		{
			int i = block.FirstGoto;

			// correct pending gotos to current block and try to close it
			// with visible labels
			while( i < PendingGotos.Count )
			{
				var gt = PendingGotos[i];
				if( gt.NumActVar > block.NumActVar )
				{
					if( block.HasUpValue )
						Coder.PatchClose( fs, gt.Pc, block.NumActVar );
					gt.NumActVar = block.NumActVar;
				}
				if( !FindLabel(i) )
					++i; // move to next one
			}
		}
예제 #8
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		private void MainFunc( FuncState fs )
		{
			ExpDesc v = new ExpDesc();
			var block = new BlockCnt();
			OpenFunc( fs, block );
			fs.Proto.IsVarArg = true; // main func is always vararg
			InitExp( v, ExpKind.VLOCAL, 0 );
			NewUpvalue( fs, LuaDef.LUA_ENV, v );
			Lexer.Next(); // read first token
			StatList();
			// check TK_EOS
			CloseFunc();
		}
예제 #9
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		private void OpenFunc( FuncState fs, BlockCnt block )
		{
			fs.Lexer = Lexer;

			fs.Prev = CurFunc;
			CurFunc = fs;

			fs.Pc = 0;
			fs.LastTarget = 0;
			fs.Jpc = Coder.NO_JUMP;
			fs.FreeReg = 0;
			fs.NumActVar = 0;
			fs.FirstLocal = ActVars.Count;

			// registers 0/1 are always valid
			fs.Proto.MaxStackSize = 2;
			fs.Proto.Source = Lexer.Source;

			EnterBlock( fs, block, false );
		}
예제 #10
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		private void Body( ExpDesc e, bool isMethod, int line )
		{
			var newFs = new FuncState();
			var block = new BlockCnt();
			newFs.Proto = AddPrototype();
			newFs.Proto.LineDefined = line;
			OpenFunc( newFs, block );
			CheckNext( (int)'(' );
			if( isMethod )
			{
				// create `self' parameter
				var v = NewLocalVar("self");
				ActVars.Add(v);
				AdjustLocalVars(1);
			}
			ParList();
			CheckNext( (int)')' );
			StatList();
			newFs.Proto.LastLineDefined = Lexer.LineNumber;
			CheckMatch( (int)TK.END, (int)TK.FUNCTION, line );
			CodeClosure(e);
			CloseFunc();
		}
예제 #11
0
파일: Parser.cs 프로젝트: Jornason/UniLua
		// block -> statlist
		private void Block()
		{
			var fs = CurFunc;
			var block = new BlockCnt();
			EnterBlock( fs, block, false );
			StatList();
			LeaveBlock( fs );
		}