protected override Expression VisitStaticExpression(StaticExpression stex) { var context = ExpressionShortcuts.Arg <BindingContext>(CompilationContext.BindingContext); var value = ExpressionShortcuts.Arg(stex.Value); return(context.Call(o => o.TextWriter.Write(value, false))); }
public T Compile <T>(Expression <T> expression) where T : class { expression = (Expression <T>)_expressionMiddleware.Aggregate((Expression)expression, (e, m) => m.Invoke(e)); if (_closureFeature == null) { return(expression.CompileFast()); } expression = (Expression <T>)_closureFeature.ExpressionMiddleware.Invoke(expression); var parameters = new[] { _closure }.Concat(expression.Parameters).ToArray(); var lambda = Expression.Lambda(expression.Body, parameters); var compiledDelegateType = Expression.GetDelegateType(parameters.Select(o => o.Type).Concat(new[] { lambda.ReturnType }).ToArray()); var method = typeof(FastExpressionCompiler) .GetMethod(nameof(CompileGeneric), BindingFlags.Static | BindingFlags.NonPublic) ?.MakeGenericMethod(compiledDelegateType); var compiledLambda = method?.Invoke(null, new object[] { lambda }) ?? throw new InvalidOperationException("lambda cannot be compiled"); var outerParameters = expression.Parameters.Select(o => Expression.Parameter(o.Type, o.Name)).ToArray(); var store = ExpressionShortcuts.Arg(_templateClosure).Property(o => o.Store); var outerLambda = Expression.Lambda <T>( Expression.Invoke(Expression.Constant(compiledLambda), new[] { store.Expression }.Concat(outerParameters)), outerParameters); return(outerLambda.CompileFast()); }
protected override Expression VisitIteratorExpression(IteratorExpression iex) { var context = ExpressionShortcuts.Arg <BindingContext>(CompilationContext.BindingContext); var sequence = ExpressionShortcuts.Var <object>("sequence"); var template = FunctionBuilder.CompileCore(new[] { iex.Template }, CompilationContext.Configuration); var ifEmpty = FunctionBuilder.CompileCore(new[] { iex.IfEmpty }, CompilationContext.Configuration); var compiledSequence = ExpressionShortcuts.Arg <object>(FunctionBuilder.Reduce(iex.Sequence, CompilationContext)); var blockParams = ExpressionShortcuts.Arg <BlockParam>(iex.BlockParams); var blockParamsProvider = ExpressionShortcuts.Call(() => BlockParamsValueProvider.Create(context, blockParams)); var blockParamsProviderVar = ExpressionShortcuts.Var <BlockParamsValueProvider>(); return(ExpressionShortcuts.Block() .Parameter(sequence, compiledSequence) .Parameter(blockParamsProviderVar, blockParamsProvider) .Line(blockParamsProviderVar.Using((self, builder) => { builder .Line(context.Call(o => o.RegisterValueProvider((IValueProvider)self))) .Line(ExpressionShortcuts.Try() .Body(ExpressionShortcuts.Call(() => Iterator.Iterate(context, self, sequence, template, ifEmpty) )) .Finally(context.Call(o => o.UnregisterValueProvider((IValueProvider)self))) ); }))); }
protected override Expression VisitPathExpression(PathExpression pex) { var context = ExpressionShortcuts.Arg <BindingContext>(CompilationContext.BindingContext); var pathInfo = pex.PathInfo; return(ExpressionShortcuts.Call(() => PathResolver.ResolvePath(context, ref pathInfo))); }
private Expression HandleInvocationExpression(InvocationExpression invocation) { if (invocation.Type != typeof(void)) { return(invocation.Update(invocation.Expression, ReplaceValuesOf <TextWriter>(invocation.Arguments, ExpressionShortcuts.Null <TextWriter>()).Select(Visit) )); } var context = ExpressionShortcuts.Var <BindingContext>(); var writer = ExpressionShortcuts.Var <TextWriter>(); invocation = invocation.Update(ExpressionUtils.ReplaceParameters(invocation.Expression, context), ExpressionUtils.ReplaceParameters( ReplaceValuesOf <TextWriter>(invocation.Arguments, writer), new Expression[] { context } ).Select(Visit) ); var formatProvider = ExpressionShortcuts.Arg(CompilationContext.Configuration.FormatProvider); var block = ExpressionShortcuts.Block() .Parameter(writer, ExpressionShortcuts.New(() => new PolledStringWriter((IFormatProvider)formatProvider))) .Line(writer.Using((o, body) => body.Line(invocation) .Line(o.Call(x => (object)x.ToString())) )); var continuation = _expressionCompiler.Compile(Expression.Lambda <Func <BindingContext, object> >(block, (ParameterExpression)context)); return(ExpressionShortcuts.Arg <object>(Expression.Invoke(Expression.Constant(continuation), CompilationContext.BindingContext))); }
public void ClosureInCallTest() { var blockBuilder = ExpressionShortcuts.Block() .Line(ExpressionShortcuts.Call(() => _mock.MethodWithReturn())); Expression.Lambda <Func <string> >(blockBuilder).Compile().Invoke(); _mock.Received(1).MethodWithReturn(); }
protected override Expression VisitBoolishExpression(BoolishExpression bex) { var condition = Visit(bex.Condition); condition = FunctionBuilder.Reduce(condition, _compilationContext); var @object = ExpressionShortcuts.Arg <object>(condition); return(ExpressionShortcuts.Call(() => HandlebarsUtils.IsTruthyOrNonEmpty(@object))); }
protected override Expression VisitStatementExpression(StatementExpression sex) { if (!(sex.Body is PathExpression)) { return(Visit(sex.Body)); } var context = ExpressionShortcuts.Arg <BindingContext>(CompilationContext.BindingContext); var value = ExpressionShortcuts.Arg <object>(Visit(sex.Body)); return(context.Call(o => o.TextWriter.Write(value))); }
public static Expression <Action <BindingContext, TextWriter, object> > Bind(CompilationContext context, Expression body, string templatePath) { var configuration = ExpressionShortcuts.Arg(context.Configuration); var writerParameter = ExpressionShortcuts.Parameter <TextWriter>("buffer"); var objectParameter = ExpressionShortcuts.Parameter <object>("data"); var bindingContext = ExpressionShortcuts.Arg <BindingContext>(context.BindingContext); var inlinePartialsParameter = ExpressionShortcuts.Null <IDictionary <string, Action <TextWriter, object> > >(); var textEncoder = configuration.Property(o => o.TextEncoder); var encodedWriterExpression = ExpressionShortcuts.Call(() => EncodedTextWriter.From(writerParameter, (ITextEncoder)textEncoder)); var parentContextArg = ExpressionShortcuts.Var <BindingContext>("parentContext"); var newBindingContext = ExpressionShortcuts.Call( () => BindingContext.Create(configuration, objectParameter, encodedWriterExpression, parentContextArg, templatePath, (IDictionary <string, Action <TextWriter, object> >)inlinePartialsParameter) ); var shouldDispose = ExpressionShortcuts.Var <bool>("shouldDispose"); Expression blockBuilder = ExpressionShortcuts.Block() .Parameter(bindingContext) .Parameter(shouldDispose) .Line(ExpressionShortcuts.Condition() .If(objectParameter.Is <BindingContext>(), bindingContext.Assign(objectParameter.As <BindingContext>()) ) .Else(block => { block.Line(shouldDispose.Assign(true)); block.Line(bindingContext.Assign(newBindingContext)); }) ) .Line(ExpressionShortcuts.Try() .Body(block => block.Lines(((BlockExpression)body).Expressions)) .Finally(ExpressionShortcuts.Condition() .If(shouldDispose, bindingContext.Call(o => o.Dispose())) ) ); return(Expression.Lambda <Action <BindingContext, TextWriter, object> >(blockBuilder, (ParameterExpression)parentContextArg.Expression, (ParameterExpression)writerParameter.Expression, (ParameterExpression)objectParameter.Expression)); }
public void FuncCallTest() { Func <IMock, string> func = m => m.MethodWithReturn(); var expected = _faker.Random.String(); _mock.MethodWithReturn().Returns(expected); var mock = ExpressionShortcuts.Arg(_mock); var data = ExpressionShortcuts.Var <IMock>(); var action = ExpressionShortcuts.Block() .Parameter(data, mock) .Line(ExpressionShortcuts.Call(() => func((IMock)data))) .Lambda <Func <string> >() .Compile(); _mock.DidNotReceive().MethodWithReturn(); var actual = action(); Assert.Equal(expected, actual); _mock.Received(1).MethodWithReturn(); }
public T Compile <T>(Expression <T> expression) where T : class { expression = (Expression <T>)_expressionMiddleware.Aggregate((Expression)expression, (e, m) => m.Invoke(e)); if (_closureFeature == null) { return(expression.Compile()); } expression = (Expression <T>)_closureFeature.ExpressionMiddleware.Invoke(expression); var parameters = new[] { (ParameterExpression)_closure }.Concat(expression.Parameters); var lambda = Expression.Lambda(expression.Body, parameters); var compiledLambda = lambda.Compile(); var outerParameters = expression.Parameters.Select(o => Expression.Parameter(o.Type, o.Name)).ToArray(); var store = ExpressionShortcuts.Arg(_templateClosure).Property(o => o.Store); var outerLambda = Expression.Lambda <T>( Expression.Invoke(Expression.Constant(compiledLambda), new[] { store.Expression }.Concat(outerParameters)), outerParameters); return(outerLambda.Compile()); }