private static Expression GenerateForLoop(LoopScope loopScope, Token tStart, List<ParameterExpression> loopVars, Expression[] explist) { const string csFunc = "#f"; const string csState = "#s"; const string csVar = "#var"; ParameterExpression varTmp = Expression.Variable(typeof(LuaResult), "#tmp"); ParameterExpression varFunc = Expression.Variable(explist.Length > 0 && typeof(Delegate).GetTypeInfo().IsAssignableFrom(explist[0].Type.GetTypeInfo()) ? explist[0].Type : typeof(object), csFunc); ParameterExpression varState = Expression.Variable(typeof(object), csState); ParameterExpression varVar = Expression.Variable(typeof(object), csVar); // local var1, ..., varn = tmp; for (int i = 0; i < loopVars.Count; i++) loopScope.InsertExpression(i, Expression.Assign(loopVars[i], ConvertExpression(loopScope.Runtime, tStart, GetResultExpression(loopScope.Runtime, tStart, varTmp, i), loopVars[i].Type))); return Expression.Block(new ParameterExpression[] { varTmp, varFunc, varState, varVar }, // fill the local loop variables initial // local #f, #s, #var = explist Expression.Assign(varTmp, GetLuaResultExpression(loopScope, tStart, explist)), Expression.Assign(varFunc, ConvertExpression(loopScope.Runtime, tStart, GetResultExpression(loopScope.Runtime, tStart, varTmp, 0), varFunc.Type)), Expression.Assign(varState, GetResultExpression(loopScope.Runtime, tStart, varTmp, 1)), Expression.Assign(varVar, GetResultExpression(loopScope.Runtime, tStart, varTmp, 2)), Expression.Label(loopScope.ContinueLabel), // local tmp = f(s, var) Expression.Assign(varTmp, InvokeExpression(loopScope, tStart, varFunc, InvokeResult.LuaResult, new ArgumentsList(varState, varVar), true) ), // var = tmp[0] Expression.Assign(varVar, GetResultExpression(loopScope.Runtime, tStart, varTmp, 0)), // if var == nil then goto break; Expression.IfThenElse(Expression.Equal(varVar, Expression.Constant(null, typeof(object))), Expression.Goto(loopScope.BreakLabel), loopScope.ExpressionBlock), // LoopBody Expression.Goto(loopScope.ContinueLabel), Expression.Label(loopScope.BreakLabel) ); }
private static void ParseForEachLoop(Scope scope, LuaLexer code) { ParameterExpression varEnumerable = Expression.Variable(typeof(System.Collections.IEnumerable), "#enumerable"); ParameterExpression varEnumerator = Expression.Variable(typeof(System.Collections.IEnumerator), "#enumerator"); // foreach name in exp do block end; code.Next(); // foreach // fetch the loop variable LoopScope loopScope = new LoopScope(scope); Token tLoopVar; Type typeLoopVar; ParseIdentifierAndType(scope, code, out tLoopVar, out typeLoopVar); ParameterExpression loopVar = loopScope.RegisterVariable(typeLoopVar, tLoopVar.Value); // get the enumerable expression FetchToken(LuaToken.KwIn, code); Expression exprEnum = Lua.EnsureType(ParseExpression(scope, code, InvokeResult.None, scope.EmitExpressionDebug), typeof(object)); // parse the loop body FetchToken(LuaToken.KwDo, code); ParseBlock(loopScope, code); FetchToken(LuaToken.KwEnd, code); loopScope.InsertExpression(0, Expression.Assign(loopVar, ConvertExpression(scope.Runtime, tLoopVar, Expression.Property(varEnumerator, Lua.EnumeratorCurrentPropertyInfo), loopVar.Type))); scope.AddExpression( Expression.Block(new ParameterExpression[] { varEnumerable, varEnumerator, loopVar }, // local enumerable = exprEnum as IEnumerator Expression.Assign(varEnumerable, Expression.TypeAs(exprEnum, typeof(System.Collections.IEnumerable))), // if enumerable == nil then error Expression.IfThen(Expression.Equal(varEnumerable, Expression.Constant(null, typeof(object))), Lua.ThrowExpression(Properties.Resources.rsExpressionNotEnumerable)), // local enum = exprEnum.GetEnumerator() Expression.Assign(varEnumerator, Expression.Call(varEnumerable, Lua.EnumerableGetEnumeratorMethodInfo)), // while enum.MoveNext() do Expression.Label(loopScope.ContinueLabel), Expression.IfThenElse(Expression.Call(varEnumerator, Lua.EnumeratorMoveNextMethodInfo), Expression.Empty(), Expression.Goto(loopScope.BreakLabel)), // loopVar = enum.Current loopScope.ExpressionBlock, // end; Expression.Goto(loopScope.ContinueLabel), Expression.Label(loopScope.BreakLabel) )); }
private static Expression GenerateForLoop(LoopScope loopScope, Token tStart, ParameterExpression loopVar, Expression loopStart, Expression loopEnd, Expression loopStep) { const string csVar = "#var"; const string csEnd = "#end"; const string csStep = "#step"; ParameterExpression internLoopVar = Expression.Variable(loopVar.Type, csVar); ParameterExpression endVar = Expression.Variable(loopEnd.Type, csEnd); ParameterExpression stepVar = Expression.Variable(loopStep.Type, csStep); LabelTarget labelLoop = Expression.Label("#loop"); // Erzeuge CodeBlock loopScope.InsertExpression(0, Expression.Assign(loopVar, internLoopVar)); // Erzeuge den Schleifenblock return Expression.Block(new ParameterExpression[] { internLoopVar, endVar, stepVar }, Expression.Assign(internLoopVar, ConvertExpression(loopScope.Runtime, tStart, loopStart, internLoopVar.Type)), Expression.Assign(endVar, loopEnd), Expression.Assign(stepVar, loopStep), Expression.Label(labelLoop), Expression.IfThenElse( BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.OrElse, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.AndAlso, ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.GreaterThan, stepVar, Expression.Constant(0, typeof(int))), typeof(bool)), ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.LessThanOrEqual, internLoopVar, endVar), typeof(bool)) ), BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.AndAlso, ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.LessThanOrEqual, stepVar, Expression.Constant(0, typeof(int))), typeof(bool)), ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.GreaterThanOrEqual, internLoopVar, endVar), typeof(bool)) ) ), loopScope.ExpressionBlock, Expression.Goto(loopScope.BreakLabel) ), Expression.Label(loopScope.ContinueLabel), Expression.Assign(internLoopVar, ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.Add, internLoopVar, stepVar), internLoopVar.Type)), Expression.Goto(labelLoop), Expression.Label(loopScope.BreakLabel) ); }