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 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); }