void EmitTemplateMethod(IAst ast, TypeBuilder tb, NLiquidDependentPropertyEvalContext context) { var compilationUnit = (CompilationUnit)ast; var methodBuilder = CreatreMethodBuilder(ast, tb); _variablesMap = new Dictionary <LocalVariableSymbol, Expression>(); _context = context; //_variablesMap = new Dictionary<LocalVariableSymbol, Expression>(context.PredefinedTypes.DotNetTypesMap); // the first parameter of tempalte method is TextWriter var methodParameters = new BlockCollector(); methodParameters.AddVariable(_textWriterParameter); var commentParameter = EmitCommentParameter(compilationUnit); if (commentParameter != null) { methodParameters.AddVariable(commentParameter); } var blockCollector = new BlockCollector(); foreach (var statement in compilationUnit.Statements) { EmitStatement(statement, blockCollector); } var templateMethod = Expression.Lambda(blockCollector.ToBlockExpression(), methodParameters.Variables); templateMethod.CompileToMethod(methodBuilder); }
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 BlockCollector EmitStatement(IEnumerable <Statement> statements, BlockCollector blockCollector = null) { if (blockCollector == null) { blockCollector = new BlockCollector(); } foreach (var statement in statements) { EmitStatement(statement, blockCollector); } return(blockCollector); }
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); }
private void EmitSimpleLocalVariableStatement(SimpleLocalVariable simpleLocalVariableStmt, BlockCollector blockCollector) { if (_context.PredefinedTypes.DotNetTypesMap.TryGetValue(simpleLocalVariableStmt.Symbol.Type, out var type)) { var variable = Expression.Variable(type, simpleLocalVariableStmt.Name.Text); var assingExpr = Expression.Assign(variable, EmitExpression(simpleLocalVariableStmt.Initializer)); blockCollector.AddVariable(variable).AddExpression(assingExpr); _variablesMap[simpleLocalVariableStmt.Symbol] = variable; } }