Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }