/// <summary> /// Applies beta reduction on invocation expressions in the given expression, using the specified configuration flags. /// This is an advanced method which should be used with care when side-effects in expression trees are critical to maintain. /// Some configurations may lead to changes in timing and the arity of side-effects. /// </summary> /// <param name="expression">Expression to apply beta reductions on.</param> /// <param name="nodeTypes">Flags to restrict the argument expression node types that will be inlined during beta reduction. (Default: Atoms)</param> /// <param name="restrictions">Flags to restrict the number of uses of each argument expression during inlining. (Default: None)</param> /// <returns>Expression after applying beta reductions.</returns> public static Expression Reduce(Expression expression, BetaReductionNodeTypes nodeTypes, BetaReductionRestrictions restrictions) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } return(ReduceCore(expression, nodeTypes, restrictions)); }
public BetaReductionExpressionVisitor(BetaReductionNodeTypes nodeTypes, BetaReductionRestrictions restrictions) { _includeConstant = (nodeTypes & BetaReductionNodeTypes.Constant) != 0; _includeDefault = (nodeTypes & BetaReductionNodeTypes.Default) != 0; _includeParameter = (nodeTypes & BetaReductionNodeTypes.Parameter) != 0; _includeQuote = (nodeTypes & BetaReductionNodeTypes.Quote) != 0; _includeMolecules = (nodeTypes & BetaReductionNodeTypes.Molecules) != 0; _inDangerOfCaptures = _includeParameter | _includeQuote | _includeMolecules; _disallowDiscard = (restrictions & BetaReductionRestrictions.DisallowDiscard) != 0; _disallowMultiple = (restrictions & BetaReductionRestrictions.DisallowMultiple) != 0; }
/// <summary> /// Applies beta reduction on invocation expressions in the given expression, using the specified configuration flags, until no further reductions are possible. /// This is an advanced method which should be used with care when side-effects in expression trees are critical to maintain. /// Some configurations may lead to changes in timing and the arity of side-effects. /// </summary> /// <param name="expression">Expression to apply beta reductions on.</param> /// <param name="nodeTypes">Flags to restrict the argument expression node types that will be inlined during beta reduction.</param> /// <param name="restrictions">Flags to restrict the number of uses of each argument expression during inlining.</param> /// <param name="throwOnCycle">Indicates whether to throw an exception if the reduction gets stuck in a cyclic reduction (e.g. for a recursive lambda expression). If set to false, the reduction stops and the current expression is returned.</param> /// <returns>Expression after applying beta reductions.</returns> public static Expression ReduceEager(Expression expression, BetaReductionNodeTypes nodeTypes, BetaReductionRestrictions restrictions, bool throwOnCycle) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } var history = new HashSet <Expression>(new ExpressionEqualityComparer()); var current = expression; var reduced = default(Expression); var i = 0; while (current != reduced) { if (!history.Add(current)) { if (throwOnCycle) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Irreducible recursive lambda expression detected: '{0}'.", current)); } else { break; } } reduced = current; current = ReduceCore(current, nodeTypes, restrictions); i++; } return(current); }
private static Expression ReduceCore(Expression expression, BetaReductionNodeTypes nodeTypes, BetaReductionRestrictions restrictions) => new BetaReductionExpressionVisitor(nodeTypes, restrictions).Visit(expression);