Exemplo n.º 1
0
		// constructor -> '{' [ field { sep field } [sep] ] '}'
		// sep -> ',' | ';'
		private void Constructor( ExpDesc t )
		{
			var fs = CurFunc;
			int line = Lexer.LineNumber;
			int pc = Coder.CodeABC( fs, OpCode.OP_NEWTABLE, 0, 0, 0 );
			var cc = new ConstructorControl();
			cc.ExpTable = t;
			InitExp( t, ExpKind.VRELOCABLE, pc );
			InitExp( cc.ExpLastItem, ExpKind.VVOID, 0); // no value (yet)
			Coder.Exp2NextReg( fs, t );
			CheckNext( (int)'{' );
			do {
				Utl.Assert( cc.ExpLastItem.Kind == ExpKind.VVOID ||
							cc.NumToStore > 0 );
				if( Lexer.Token.TokenType == (int)'}' )
					break;
				CloseListField( fs, cc );
				Field( cc );
			} while( TestNext( (int)',' ) || TestNext( (int)';' ) );
			CheckMatch( (int)'}', (int)'{', line );
			LastListField( fs, cc );

			// set initial array size and table size
			// 因为没有实现 OP_NEWTABLE 对 ARG_B 和 ARG_C 的处理, 所以这里也暂不实现
			// 不影响逻辑, 只是效率差别
			// var ins = fs.Proto.Code[pc];
			// ins.SETARG_B( 0 );
			// ins.SETARG_C( 0 );

			// 算了, 还是实现吧, 方便检查生成的 bytecode 是否跟 luac 一样
			var ins = fs.Proto.Code[pc];
			ins.SETARG_B( Integer2FloatingPointByte( (uint)cc.NumArray ) );
			ins.SETARG_C( Integer2FloatingPointByte( (uint)cc.NumRecord) );
			fs.Proto.Code[pc] = ins; // Instruction 是值类型的 唉
		}
Exemplo n.º 2
0
		// field -> listfield | recfield
		private void Field( ConstructorControl cc )
		{
			switch( Lexer.Token.TokenType )
			{
				// may be 'listfield' or 'recfield'
				case (int)TK.NAME: {
					// expression?
					if( Lexer.GetLookAhead().TokenType != (int)'=' )
						ListField( cc );
					else
						RecField( cc );
					break;
				}

				case (int)'[': {
					RecField( cc );
					break;
				}

				default: {
					ListField( cc );
					break;
				}
			}
		}
Exemplo n.º 3
0
		// listfield -> exp
		private void ListField( ConstructorControl cc )
		{
			Expr( cc.ExpLastItem );
			CheckLimit( CurFunc, cc.NumArray, LuaLimits.MAX_INT,
				"items in a constructor" );
			cc.NumArray++;
			cc.NumToStore++;
		}
Exemplo n.º 4
0
		private void LastListField( FuncState fs, ConstructorControl cc )
		{
			if( cc.NumToStore == 0 )
				return;

			if( HasMultiRet( cc.ExpLastItem.Kind ) )
			{
				Coder.SetMultiRet( fs, cc.ExpLastItem );
				Coder.SetList( fs, cc.ExpTable.Info, cc.NumArray, LuaDef.LUA_MULTRET );

				// do not count last expression (unknown number of elements)
				cc.NumArray--;
			}
			else
			{
				if( cc.ExpLastItem.Kind != ExpKind.VVOID )
					Coder.Exp2NextReg( fs, cc.ExpLastItem );
				Coder.SetList( fs, cc.ExpTable.Info, cc.NumArray, cc.NumToStore );
			}
		}
Exemplo n.º 5
0
		private void CloseListField( FuncState fs, ConstructorControl cc )
		{
			// there is no list item
			if( cc.ExpLastItem.Kind == ExpKind.VVOID )
				return;

			Coder.Exp2NextReg( fs, cc.ExpLastItem );
			cc.ExpLastItem.Kind = ExpKind.VVOID;
			if( cc.NumToStore == LuaDef.LFIELDS_PER_FLUSH )
			{
				// flush
				Coder.SetList( fs, cc.ExpTable.Info, cc.NumArray, cc.NumToStore );

				// no more item pending
				cc.NumToStore = 0;
			}
		}
Exemplo n.º 6
0
		// recfield -> (NAME | '[' exp1 ']') = exp1
		private void RecField( ConstructorControl cc )
		{
			var fs = CurFunc;
			int reg = fs.FreeReg;
			var key = new ExpDesc();
			var val = new ExpDesc();
			if( Lexer.Token.TokenType == (int)TK.NAME )
			{
				CheckLimit( fs, cc.NumRecord, LuaLimits.MAX_INT,
					"items in a constructor" );
				CodeString( key, CheckName() );
			}
			// ls->t.token == '['
			else
			{
				YIndex( key );
			}
			cc.NumRecord++;
			CheckNext( (int)'=' );
			int rkkey = Coder.Exp2RK( fs, key );
			Expr( val );
			Coder.CodeABC( fs, OpCode.OP_SETTABLE, cc.ExpTable.Info, rkkey,
				Coder.Exp2RK( fs, val ) );
			fs.FreeReg = reg; // free registers
		}