private void EmitIfStatement(Statement.If ifStmt, BlockCollector blockCollector) { var ifStmtElseIfs = (IAstList <ElseIf>)ifStmt.ElseIfs; var elseBody = ifStmt.Else.HasValue ? EmitStatement(ifStmt.Else.Value.Body).ToBlockExpression() : null; Expression elseIfExpr = null; // else if statements if (ifStmt.ElseIfs != null && ifStmtElseIfs.Count > 0) { var lastElseIf = ifStmtElseIfs[ifStmtElseIfs.Count - 1]; Expression lastElseIfExpr = elseBody == null ? Expression.IfThen(EmitExpression(lastElseIf.Condition), EmitStatement(lastElseIf.Body).ToBlockExpression()) : Expression.IfThenElse(EmitExpression(lastElseIf.Condition), EmitStatement(lastElseIf.Body).ToBlockExpression(), elseBody); for (int i = ifStmtElseIfs.Count - 2; i >= 0; i--) { var currentElseIf = ifStmtElseIfs[i]; elseIfExpr = Expression.IfThenElse( EmitExpression(currentElseIf.Condition), EmitStatement(currentElseIf.Body).ToBlockExpression(), Expression.Block(lastElseIfExpr)); lastElseIfExpr = elseIfExpr; } elseBody = Expression.Block(elseIfExpr ?? lastElseIfExpr); } blockCollector.AddExpression(elseBody == null ? Expression.IfThen(EmitExpression(ifStmt.Condition), EmitStatement(ifStmt.Body).ToBlockExpression()) : Expression.IfThenElse(EmitExpression(ifStmt.Condition), EmitStatement(ifStmt.Body).ToBlockExpression(), elseBody)); }
private void EmitTextWriteStatement <T>(T value, BlockCollector blockCollector) { var valueType = typeof(T); if (!_writeTextWriteMethodInfoMap.TryGetValue(valueType, out var methodInfo)) { methodInfo = _defaultTextWriteMethodInfo; } blockCollector.AddExpression(Expression.Call(_textWriterParameter, methodInfo, Expression.Constant(value, valueType))); }
private void EmitOutputStatement(Statement.Output outputStmt, BlockCollector blockCollector) { var valExpr = EmitExpression(outputStmt.Expr); var valueType = valExpr.Type; if (!_writeTextWriteMethodInfoMap.TryGetValue(valueType, out var methodInfo)) { methodInfo = _defaultTextWriteMethodInfo; } blockCollector.AddExpression(Expression.Call(_textWriterParameter, methodInfo, valExpr)); }
private void EmitStatement(Statement statement, BlockCollector blockCollector) { switch (statement) { case Statement.Plain plainStmt: EmitTextWriteStatement <string>(plainStmt.Value.Value, blockCollector); break; case Statement.Output outputStmt: EmitOutputStatement(outputStmt, blockCollector); break; case SimpleLocalVariable simpleLocalVariableStmt: EmitSimpleLocalVariableStatement(simpleLocalVariableStmt, blockCollector); break; case CaptureLocalVariable captureLocalVariableStmt: break; case Statement.Unless unlessStmt: break; case Statement.If ifStmt: EmitIfStatement(ifStmt, blockCollector); break; case For forStmt: EmitForStatement(forStmt, blockCollector); break; case Statement.Break breakStmt: //blockCollector.AddExpression(Expression.Return(Expression.la)) break; case Statement.Continue continueStmt: break; default: blockCollector.AddExpression(Expression.Empty()); break; } }
private void EmitForStatement(For forStmtFor, BlockCollector blockCollector) { var forBlockCollector = new BlockCollector(); var collectionExpr = EmitExpression(forStmtFor.ForSource); var elementType = _context.PredefinedTypes.GetDotNetType(forStmtFor.Symbol.Type); var enumerableType = typeof(IEnumerable <>).MakeGenericType(elementType); var enumeratorType = typeof(IEnumerator <>).MakeGenericType(elementType); var enumeratorVar = Expression.Variable(enumeratorType, "enumerator"); var getEnumeratorCall = Expression.Call(collectionExpr, enumerableType.GetMethod("GetEnumerator", BindingFlags.Instance | BindingFlags.Public)); var enumeratorAssign = Expression.Assign(enumeratorVar, getEnumeratorCall); blockCollector.AddVariable(enumeratorVar); // The MoveNext method's actually on IEnumerator, not IEnumerator<T> var moveNextCall = Expression.Call(enumeratorVar, typeof(IEnumerator).GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.Public)); var breakLabel = Expression.Label("LoopBreak"); var loopVar = Expression.Variable(elementType, forStmtFor.Name.Text); forBlockCollector.AddVariable(loopVar); _variablesMap[forStmtFor.Symbol] = loopVar; forBlockCollector.AddExpression(Expression.Assign(loopVar, Expression.Property(enumeratorVar, "Current"))); EmitStatement(forStmtFor.Body, forBlockCollector); var loop = Expression.Block(new[] { enumeratorVar }, enumeratorAssign, Expression.Loop( Expression.IfThenElse( Expression.Equal(moveNextCall, Expression.Constant(true)), forBlockCollector.ToBlockExpression(), Expression.Break(breakLabel) ), breakLabel) ); blockCollector.AddExpression(loop); }