Skip to content

Instantly share code, notes, and snippets.

@cybernetics
Forked from jbgi/Expressions.java
Created December 13, 2023 10:20
Show Gist options
  • Save cybernetics/8e7e19f372e68de6f3a7ab88af495c19 to your computer and use it in GitHub Desktop.
Save cybernetics/8e7e19f372e68de6f3a7ab88af495c19 to your computer and use it in GitHub Desktop.

Revisions

  1. @jbgi jbgi revised this gist Jan 24, 2016. 1 changed file with 11 additions and 3 deletions.
    14 changes: 11 additions & 3 deletions Expressions.java
    Original file line number Diff line number Diff line change
    @@ -53,13 +53,21 @@ public static Expression lazy(Supplier<Expression> expression) {
    return new Lazy(expression);
    }

    public static <R> Expression.Cases<R> cases(Function<Integer, R> Const, AddMapper<Expression, R> Add, MultMapper<Expression, R> Mult, Function<Expression, R> Neg) {
    public static <R> Expression.Cases<R> cases(Function<Integer, R> Const, AddMapper<Expression, R> Add,
    MultMapper<Expression, R> Mult, Function<Expression, R> Neg) {
    return new LambdaCases<>(Const, Add, Mult, Neg);
    }

    public static <R> Function<Expression, R> cata(Function<Integer, R> Const, AddMapper<Supplier<R>, R> Add, MultMapper<Supplier<R>, R> Mult, Function<Supplier<R>, R> Neg) {
    public static <R> Function<Expression, R> cata(Function<Integer, R> Const, AddMapper<Supplier<R>, R> Add,
    MultMapper<Supplier<R>, R> Mult, Function<Supplier<R>, R> Neg) {
    Expression.Cases<R> cata = new Object() {
    Expression.Cases<R> cata = Expressions.cases(Const, (left, right) -> Add.Add(() -> left.match(this.cata), () -> right.match(this.cata)), (left, right) -> Mult.Mult(() -> left.match(this.cata), () -> right.match(this.cata)), (expr) -> Neg.apply(() -> expr.match(this.cata)));
    Expression.Cases<R> cata = Expressions.cases(
    Const,
    (left, right) -> Add.Add(() -> left.match(this.cata),
    () -> right.match(this.cata)),
    (left, right) -> Mult.Mult(() -> left.match(this.cata),
    () -> right.match(this.cata)), (expr) -> Neg.apply(() -> expr.match(this.cata))
    );
    ;
    }.cata;
    return expression -> expression.match(cata);
  2. @jbgi jbgi revised this gist Dec 29, 2015. 1 changed file with 131 additions and 51 deletions.
    182 changes: 131 additions & 51 deletions Expressions.java
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ public final class Expressions {
    private Expressions() {
    }

    public static Expression Const(Integer value) {
    public static Expression Const(int value) {
    return new Const(value);
    }

    @@ -53,10 +53,18 @@ public static Expression lazy(Supplier<Expression> expression) {
    return new Lazy(expression);
    }

    public static <R> Expression.Cases<R> cases(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult, NegMapper<R> Neg) {
    public static <R> Expression.Cases<R> cases(Function<Integer, R> Const, AddMapper<Expression, R> Add, MultMapper<Expression, R> Mult, Function<Expression, R> Neg) {
    return new LambdaCases<>(Const, Add, Mult, Neg);
    }

    public static <R> Function<Expression, R> cata(Function<Integer, R> Const, AddMapper<Supplier<R>, R> Add, MultMapper<Supplier<R>, R> Mult, Function<Supplier<R>, R> Neg) {
    Expression.Cases<R> cata = new Object() {
    Expression.Cases<R> cata = Expressions.cases(Const, (left, right) -> Add.Add(() -> left.match(this.cata), () -> right.match(this.cata)), (left, right) -> Mult.Mult(() -> left.match(this.cata), () -> right.match(this.cata)), (expr) -> Neg.apply(() -> expr.match(this.cata)));
    ;
    }.cata;
    return expression -> expression.match(cata);
    }

    public static Optional<Integer> getValue(Expression expression) {
    return expression.match(valueGetter);
    }
    @@ -126,9 +134,9 @@ public static TotalMatchBuilderConst cases() {
    }

    private static final class Const extends Expression {
    private final Integer value;
    private final int value;

    Const(Integer value) {
    Const(int value) {
    this.value = value;
    }

    @@ -214,41 +222,33 @@ public <R> R match(Expression.Cases<R> cases) {
    }
    }

    public interface ConstMapper<R> {
    R Const(Integer value);
    }

    public interface AddMapper<R> {
    R Add(Expression left, Expression right);
    }

    public interface MultMapper<R> {
    R Mult(Expression left, Expression right);
    public interface AddMapper<R_, R> {
    R Add(R_ left, R_ right);
    }

    public interface NegMapper<R> {
    R Neg(Expression expr);
    public interface MultMapper<R_, R> {
    R Mult(R_ left, R_ right);
    }

    private static final class LambdaCases<R> implements Expression.Cases<R> {
    private final ConstMapper<R> Const;
    private final Function<Integer, R> Const;

    private final AddMapper<R> Add;
    private final AddMapper<Expression, R> Add;

    private final MultMapper<R> Mult;
    private final MultMapper<Expression, R> Mult;

    private final NegMapper<R> Neg;
    private final Function<Expression, R> Neg;

    LambdaCases(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult, NegMapper<R> Neg) {
    LambdaCases(Function<Integer, R> Const, AddMapper<Expression, R> Add, MultMapper<Expression, R> Mult, Function<Expression, R> Neg) {
    this.Const = Const;
    this.Add = Add;
    this.Mult = Mult;
    this.Neg = Neg;
    }

    @Override
    public R Const(Integer value) {
    return this.Const.Const(value);
    public R Const(int value) {
    return this.Const.apply(value);
    }

    @Override
    @@ -263,126 +263,190 @@ public R Mult(Expression left, Expression right) {

    @Override
    public R Neg(Expression expr) {
    return this.Neg.Neg(expr);
    return this.Neg.apply(expr);
    }
    }

    public static final class TotalMatchBuilderConst {
    private TotalMatchBuilderConst() {
    }

    public final <R> TotalMatchBuilderAdd<R> Const(ConstMapper<R> Const) {
    public final <R> TotalMatchBuilderAdd<R> Const(Function<Integer, R> Const) {
    return new TotalMatchBuilderAdd<>(Const);
    }

    public final <R> PartialMatchBuilderMult<R> Add(AddMapper<R> Add) {
    public final <R> TotalMatchBuilderAdd<R> Const(R r) {
    return this.Const((value) -> r);
    }

    public final <R> PartialMatchBuilderMult<R> Add(AddMapper<Expression, R> Add) {
    return new PartialMatchBuilderMult<>(null, Add);
    }

    public final <R> PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    public final <R> PartialMatchBuilderMult<R> Add(R r) {
    return this.Add((left, right) -> r);
    }

    public final <R> PartialMatchBuilderNeg<R> Mult(MultMapper<Expression, R> Mult) {
    return new PartialMatchBuilderNeg<>(null, null, Mult);
    }

    public final <R> PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    public final <R> PartialMatchBuilderNeg<R> Mult(R r) {
    return this.Mult((left, right) -> r);
    }

    public final <R> PartialMatchBuilder<R> Neg(Function<Expression, R> Neg) {
    return new PartialMatchBuilder<>(null, null, null, Neg);
    }

    public final <R> PartialMatchBuilder<R> Neg(R r) {
    return this.Neg((expr) -> r);
    }
    }

    public static final class TotalMatchBuilderAdd<R> extends PartialMatchBuilder<R> {
    private TotalMatchBuilderAdd(ConstMapper<R> Const) {
    private TotalMatchBuilderAdd(Function<Integer, R> Const) {
    super(Const, null, null, null);
    }

    public final TotalMatchBuilderMult<R> Add(AddMapper<R> Add) {
    public final TotalMatchBuilderMult<R> Add(AddMapper<Expression, R> Add) {
    return new TotalMatchBuilderMult<>(super.Const, Add);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    public final TotalMatchBuilderMult<R> Add(R r) {
    return this.Add((left, right) -> r);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<Expression, R> Mult) {
    return new PartialMatchBuilderNeg<>(super.Const, null, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    public final PartialMatchBuilderNeg<R> Mult(R r) {
    return this.Mult((left, right) -> r);
    }

    public final PartialMatchBuilder<R> Neg(Function<Expression, R> Neg) {
    return new PartialMatchBuilder<>(super.Const, null, null, Neg);
    }

    public final PartialMatchBuilder<R> Neg(R r) {
    return this.Neg((expr) -> r);
    }
    }

    public static final class TotalMatchBuilderMult<R> extends PartialMatchBuilder<R> {
    private TotalMatchBuilderMult(ConstMapper<R> Const, AddMapper<R> Add) {
    private TotalMatchBuilderMult(Function<Integer, R> Const, AddMapper<Expression, R> Add) {
    super(Const, Add, null, null);
    }

    public final TotalMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    public final TotalMatchBuilderNeg<R> Mult(MultMapper<Expression, R> Mult) {
    return new TotalMatchBuilderNeg<>(super.Const, super.Add, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    public final TotalMatchBuilderNeg<R> Mult(R r) {
    return this.Mult((left, right) -> r);
    }

    public final PartialMatchBuilder<R> Neg(Function<Expression, R> Neg) {
    return new PartialMatchBuilder<>(super.Const, super.Add, null, Neg);
    }

    public final PartialMatchBuilder<R> Neg(R r) {
    return this.Neg((expr) -> r);
    }
    }

    public static final class TotalMatchBuilderNeg<R> extends PartialMatchBuilder<R> {
    private TotalMatchBuilderNeg(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult) {
    private TotalMatchBuilderNeg(Function<Integer, R> Const, AddMapper<Expression, R> Add, MultMapper<Expression, R> Mult) {
    super(Const, Add, Mult, null);
    }

    public final Function<Expression, R> Neg(NegMapper<R> Neg) {
    public final Function<Expression, R> Neg(Function<Expression, R> Neg) {
    Expression.Cases<R> cases = Expressions.cases(super.Const, super.Add, super.Mult, Neg);
    return expression -> expression.match(cases);
    }

    public final Function<Expression, R> Neg(R r) {
    return this.Neg((expr) -> r);
    }
    }

    public static class PartialMatchBuilderAdd<R> extends PartialMatchBuilder<R> {
    private PartialMatchBuilderAdd(ConstMapper<R> Const) {
    private PartialMatchBuilderAdd(Function<Integer, R> Const) {
    super(Const, null, null, null);
    }

    public final PartialMatchBuilderMult<R> Add(AddMapper<R> Add) {
    public final PartialMatchBuilderMult<R> Add(AddMapper<Expression, R> Add) {
    return new PartialMatchBuilderMult<>(super.Const, Add);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    public final PartialMatchBuilderMult<R> Add(R r) {
    return this.Add((left, right) -> r);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<Expression, R> Mult) {
    return new PartialMatchBuilderNeg<>(super.Const, null, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    public final PartialMatchBuilderNeg<R> Mult(R r) {
    return this.Mult((left, right) -> r);
    }

    public final PartialMatchBuilder<R> Neg(Function<Expression, R> Neg) {
    return new PartialMatchBuilder<>(super.Const, null, null, Neg);
    }

    public final PartialMatchBuilder<R> Neg(R r) {
    return this.Neg((expr) -> r);
    }
    }

    public static class PartialMatchBuilderMult<R> extends PartialMatchBuilder<R> {
    private PartialMatchBuilderMult(ConstMapper<R> Const, AddMapper<R> Add) {
    private PartialMatchBuilderMult(Function<Integer, R> Const, AddMapper<Expression, R> Add) {
    super(Const, Add, null, null);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    public final PartialMatchBuilderNeg<R> Mult(MultMapper<Expression, R> Mult) {
    return new PartialMatchBuilderNeg<>(super.Const, super.Add, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    public final PartialMatchBuilderNeg<R> Mult(R r) {
    return this.Mult((left, right) -> r);
    }

    public final PartialMatchBuilder<R> Neg(Function<Expression, R> Neg) {
    return new PartialMatchBuilder<>(super.Const, super.Add, null, Neg);
    }

    public final PartialMatchBuilder<R> Neg(R r) {
    return this.Neg((expr) -> r);
    }
    }

    public static class PartialMatchBuilderNeg<R> extends PartialMatchBuilder<R> {
    private PartialMatchBuilderNeg(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult) {
    private PartialMatchBuilderNeg(Function<Integer, R> Const, AddMapper<Expression, R> Add, MultMapper<Expression, R> Mult) {
    super(Const, Add, Mult, null);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    public final PartialMatchBuilder<R> Neg(Function<Expression, R> Neg) {
    return new PartialMatchBuilder<>(super.Const, super.Add, super.Mult, Neg);
    }

    public final PartialMatchBuilder<R> Neg(R r) {
    return this.Neg((expr) -> r);
    }
    }

    public static class PartialMatchBuilder<R> {
    private final ConstMapper<R> Const;
    private final Function<Integer, R> Const;

    private final AddMapper<R> Add;
    private final AddMapper<Expression, R> Add;

    private final MultMapper<R> Mult;
    private final MultMapper<Expression, R> Mult;

    private final NegMapper<R> Neg;
    private final Function<Expression, R> Neg;

    private PartialMatchBuilder(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult, NegMapper<R> Neg) {
    private PartialMatchBuilder(Function<Integer, R> Const, AddMapper<Expression, R> Add, MultMapper<Expression, R> Mult, Function<Expression, R> Neg) {
    this.Const = Const;
    this.Add = Add;
    this.Mult = Mult;
    @@ -396,5 +460,21 @@ public final Function<Expression, R> otherwise(Supplier<R> otherwise) {
    this.Neg != null ? this.Neg : (expr) -> otherwise.get());
    return expression -> expression.match(cases);
    }

    public final Function<Expression, R> otherwise(R r) {
    return this.otherwise(() -> r);
    }

    public final Function<Expression, Optional<R>> otherwiseEmpty() {
    Expression.Cases<Optional<R>> cases = Expressions.cases((this.Const != null) ? (value) -> Optional.of(this.Const.apply(value))
    : (value) -> Optional.empty(),
    (this.Add != null) ? (left, right) -> Optional.of(this.Add.Add(left, right))
    : (left, right) -> Optional.empty(),
    (this.Mult != null) ? (left, right) -> Optional.of(this.Mult.Mult(left, right))
    : (left, right) -> Optional.empty(),
    (this.Neg != null) ? (expr) -> Optional.of(this.Neg.apply(expr))
    : (expr) -> Optional.empty());
    return expression -> expression.match(cases);
    }
    }
    }
  3. @jbgi jbgi revised this gist Oct 20, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Expressions.java
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    package test;
    package org.derive4j.exemple;

    import java.lang.Integer;
    import java.lang.Object;
  4. @jbgi jbgi revised this gist Oct 20, 2015. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions Expressions.java
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    package org.derive4j.exemple;
    package test;

    import java.lang.Integer;
    import java.lang.Object;
    @@ -28,6 +28,8 @@ public final class Expressions {
    (left, right) -> Optional.empty(),
    (expr) -> Optional.of(expr));

    private static final TotalMatchBuilderConst totalMatchBuilderConst = new TotalMatchBuilderConst();

    private Expressions() {
    }

    @@ -119,8 +121,8 @@ public static Function<Expression, Expression> modExpr(Function<Expression, Expr
    return expression -> expression.match(cases);
    }

    public static TotalMatchBuilderConst match() {
    return new TotalMatchBuilderConst();
    public static TotalMatchBuilderConst cases() {
    return totalMatchBuilderConst;
    }

    private static final class Const extends Expression {
    @@ -395,4 +397,4 @@ public final Function<Expression, R> otherwise(Supplier<R> otherwise) {
    return expression -> expression.match(cases);
    }
    }
    }
    }
  5. @jbgi jbgi renamed this gist Oct 19, 2015. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions Generated code for @Data Expression → Expressions.java
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@
    ```java
    package org.derive4j.exemple;

    import java.lang.Integer;
    @@ -396,5 +395,4 @@ public final Function<Expression, R> otherwise(Supplier<R> otherwise) {
    return expression -> expression.match(cases);
    }
    }
    }
    ```
    }
  6. @jbgi jbgi revised this gist Oct 19, 2015. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions Generated code for @Data Expression
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    ```java
    package org.derive4j.exemple;

    import java.lang.Integer;
    @@ -396,3 +397,4 @@ public final class Expressions {
    }
    }
    }
    ```
  7. @jbgi jbgi created this gist Oct 19, 2015.
    398 changes: 398 additions & 0 deletions Generated code for @Data Expression
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,398 @@
    package org.derive4j.exemple;

    import java.lang.Integer;
    import java.lang.Object;
    import java.lang.Override;
    import java.util.Optional;
    import java.util.function.Function;
    import java.util.function.Supplier;

    public final class Expressions {
    private static final Expression.Cases<Optional<Integer>> valueGetter = Expressions.cases((value) -> Optional.of(value),
    (left, right) -> Optional.empty(),
    (left, right) -> Optional.empty(),
    (expr) -> Optional.empty());

    private static final Expression.Cases<Optional<Expression>> leftGetter = Expressions.cases((value) -> Optional.empty(),
    (left, right) -> Optional.of(left),
    (left, right) -> Optional.of(left),
    (expr) -> Optional.empty());

    private static final Expression.Cases<Optional<Expression>> rightGetter = Expressions.cases((value) -> Optional.empty(),
    (left, right) -> Optional.of(right),
    (left, right) -> Optional.of(right),
    (expr) -> Optional.empty());

    private static final Expression.Cases<Optional<Expression>> exprGetter = Expressions.cases((value) -> Optional.empty(),
    (left, right) -> Optional.empty(),
    (left, right) -> Optional.empty(),
    (expr) -> Optional.of(expr));

    private Expressions() {
    }

    public static Expression Const(Integer value) {
    return new Const(value);
    }

    public static Expression Add(Expression left, Expression right) {
    return new Add(left, right);
    }

    public static Expression Mult(Expression left, Expression right) {
    return new Mult(left, right);
    }

    public static Expression Neg(Expression expr) {
    return new Neg(expr);
    }

    public static Expression lazy(Supplier<Expression> expression) {
    return new Lazy(expression);
    }

    public static <R> Expression.Cases<R> cases(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult, NegMapper<R> Neg) {
    return new LambdaCases<>(Const, Add, Mult, Neg);
    }

    public static Optional<Integer> getValue(Expression expression) {
    return expression.match(valueGetter);
    }

    public static Optional<Expression> getLeft(Expression expression) {
    return expression.match(leftGetter);
    }

    public static Optional<Expression> getRight(Expression expression) {
    return expression.match(rightGetter);
    }

    public static Optional<Expression> getExpr(Expression expression) {
    return expression.match(exprGetter);
    }

    public static Function<Expression, Expression> setValue(Integer newValue) {
    return modValue(__ -> newValue);
    }

    public static Function<Expression, Expression> modValue(Function<Integer, Integer> valueMod) {
    Expression.Cases<Expression> cases = Expressions.cases((value) -> Const(valueMod.apply(value)),
    (left, right) -> Add(left, right),
    (left, right) -> Mult(left, right),
    (expr) -> Neg(expr));
    return expression -> expression.match(cases);
    }

    public static Function<Expression, Expression> setLeft(Expression newLeft) {
    return modLeft(__ -> newLeft);
    }

    public static Function<Expression, Expression> modLeft(Function<Expression, Expression> leftMod) {
    Expression.Cases<Expression> cases = Expressions.cases((value) -> Const(value),
    (left, right) -> Add(leftMod.apply(left), right),
    (left, right) -> Mult(leftMod.apply(left), right),
    (expr) -> Neg(expr));
    return expression -> expression.match(cases);
    }

    public static Function<Expression, Expression> setRight(Expression newRight) {
    return modRight(__ -> newRight);
    }

    public static Function<Expression, Expression> modRight(Function<Expression, Expression> rightMod) {
    Expression.Cases<Expression> cases = Expressions.cases((value) -> Const(value),
    (left, right) -> Add(left, rightMod.apply(right)),
    (left, right) -> Mult(left, rightMod.apply(right)),
    (expr) -> Neg(expr));
    return expression -> expression.match(cases);
    }

    public static Function<Expression, Expression> setExpr(Expression newExpr) {
    return modExpr(__ -> newExpr);
    }

    public static Function<Expression, Expression> modExpr(Function<Expression, Expression> exprMod) {
    Expression.Cases<Expression> cases = Expressions.cases((value) -> Const(value),
    (left, right) -> Add(left, right),
    (left, right) -> Mult(left, right),
    (expr) -> Neg(exprMod.apply(expr)));
    return expression -> expression.match(cases);
    }

    public static TotalMatchBuilderConst match() {
    return new TotalMatchBuilderConst();
    }

    private static final class Const extends Expression {
    private final Integer value;

    Const(Integer value) {
    this.value = value;
    }

    @Override
    public <R> R match(Expression.Cases<R> cases) {
    return cases.Const(this.value);
    }
    }

    private static final class Add extends Expression {
    private final Expression left;

    private final Expression right;

    Add(Expression left, Expression right) {
    this.left = left;
    this.right = right;
    }

    @Override
    public <R> R match(Expression.Cases<R> cases) {
    return cases.Add(this.left, this.right);
    }
    }

    private static final class Mult extends Expression {
    private final Expression left;

    private final Expression right;

    Mult(Expression left, Expression right) {
    this.left = left;
    this.right = right;
    }

    @Override
    public <R> R match(Expression.Cases<R> cases) {
    return cases.Mult(this.left, this.right);
    }
    }

    private static final class Neg extends Expression {
    private final Expression expr;

    Neg(Expression expr) {
    this.expr = expr;
    }

    @Override
    public <R> R match(Expression.Cases<R> cases) {
    return cases.Neg(this.expr);
    }
    }

    private static final class Lazy extends Expression {
    private final Object lock = new Object();

    private Supplier<Expression> expression;

    private volatile Expression evaluation;

    Lazy(Supplier<Expression> expression) {
    this.expression = expression;
    }

    private Expression eval() {
    Expression _evaluation = this.evaluation;
    if (_evaluation == null) {
    synchronized (this.lock) {
    _evaluation = this.evaluation;
    if (_evaluation == null) {
    this.evaluation = _evaluation = expression.get();
    this.expression = null;
    }
    }
    }
    return _evaluation;
    }

    @Override
    public <R> R match(Expression.Cases<R> cases) {
    return this.eval().match(cases);
    }
    }

    public interface ConstMapper<R> {
    R Const(Integer value);
    }

    public interface AddMapper<R> {
    R Add(Expression left, Expression right);
    }

    public interface MultMapper<R> {
    R Mult(Expression left, Expression right);
    }

    public interface NegMapper<R> {
    R Neg(Expression expr);
    }

    private static final class LambdaCases<R> implements Expression.Cases<R> {
    private final ConstMapper<R> Const;

    private final AddMapper<R> Add;

    private final MultMapper<R> Mult;

    private final NegMapper<R> Neg;

    LambdaCases(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult, NegMapper<R> Neg) {
    this.Const = Const;
    this.Add = Add;
    this.Mult = Mult;
    this.Neg = Neg;
    }

    @Override
    public R Const(Integer value) {
    return this.Const.Const(value);
    }

    @Override
    public R Add(Expression left, Expression right) {
    return this.Add.Add(left, right);
    }

    @Override
    public R Mult(Expression left, Expression right) {
    return this.Mult.Mult(left, right);
    }

    @Override
    public R Neg(Expression expr) {
    return this.Neg.Neg(expr);
    }
    }

    public static final class TotalMatchBuilderConst {
    private TotalMatchBuilderConst() {
    }

    public final <R> TotalMatchBuilderAdd<R> Const(ConstMapper<R> Const) {
    return new TotalMatchBuilderAdd<>(Const);
    }

    public final <R> PartialMatchBuilderMult<R> Add(AddMapper<R> Add) {
    return new PartialMatchBuilderMult<>(null, Add);
    }

    public final <R> PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    return new PartialMatchBuilderNeg<>(null, null, Mult);
    }

    public final <R> PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    return new PartialMatchBuilder<>(null, null, null, Neg);
    }
    }

    public static final class TotalMatchBuilderAdd<R> extends PartialMatchBuilder<R> {
    private TotalMatchBuilderAdd(ConstMapper<R> Const) {
    super(Const, null, null, null);
    }

    public final TotalMatchBuilderMult<R> Add(AddMapper<R> Add) {
    return new TotalMatchBuilderMult<>(super.Const, Add);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    return new PartialMatchBuilderNeg<>(super.Const, null, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    return new PartialMatchBuilder<>(super.Const, null, null, Neg);
    }
    }

    public static final class TotalMatchBuilderMult<R> extends PartialMatchBuilder<R> {
    private TotalMatchBuilderMult(ConstMapper<R> Const, AddMapper<R> Add) {
    super(Const, Add, null, null);
    }

    public final TotalMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    return new TotalMatchBuilderNeg<>(super.Const, super.Add, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    return new PartialMatchBuilder<>(super.Const, super.Add, null, Neg);
    }
    }

    public static final class TotalMatchBuilderNeg<R> extends PartialMatchBuilder<R> {
    private TotalMatchBuilderNeg(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult) {
    super(Const, Add, Mult, null);
    }

    public final Function<Expression, R> Neg(NegMapper<R> Neg) {
    Expression.Cases<R> cases = Expressions.cases(super.Const, super.Add, super.Mult, Neg);
    return expression -> expression.match(cases);
    }
    }

    public static class PartialMatchBuilderAdd<R> extends PartialMatchBuilder<R> {
    private PartialMatchBuilderAdd(ConstMapper<R> Const) {
    super(Const, null, null, null);
    }

    public final PartialMatchBuilderMult<R> Add(AddMapper<R> Add) {
    return new PartialMatchBuilderMult<>(super.Const, Add);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    return new PartialMatchBuilderNeg<>(super.Const, null, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    return new PartialMatchBuilder<>(super.Const, null, null, Neg);
    }
    }

    public static class PartialMatchBuilderMult<R> extends PartialMatchBuilder<R> {
    private PartialMatchBuilderMult(ConstMapper<R> Const, AddMapper<R> Add) {
    super(Const, Add, null, null);
    }

    public final PartialMatchBuilderNeg<R> Mult(MultMapper<R> Mult) {
    return new PartialMatchBuilderNeg<>(super.Const, super.Add, Mult);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    return new PartialMatchBuilder<>(super.Const, super.Add, null, Neg);
    }
    }

    public static class PartialMatchBuilderNeg<R> extends PartialMatchBuilder<R> {
    private PartialMatchBuilderNeg(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult) {
    super(Const, Add, Mult, null);
    }

    public final PartialMatchBuilder<R> Neg(NegMapper<R> Neg) {
    return new PartialMatchBuilder<>(super.Const, super.Add, super.Mult, Neg);
    }
    }

    public static class PartialMatchBuilder<R> {
    private final ConstMapper<R> Const;

    private final AddMapper<R> Add;

    private final MultMapper<R> Mult;

    private final NegMapper<R> Neg;

    private PartialMatchBuilder(ConstMapper<R> Const, AddMapper<R> Add, MultMapper<R> Mult, NegMapper<R> Neg) {
    this.Const = Const;
    this.Add = Add;
    this.Mult = Mult;
    this.Neg = Neg;
    }

    public final Function<Expression, R> otherwise(Supplier<R> otherwise) {
    Expression.Cases<R> cases = Expressions.cases(this.Const != null ? this.Const : (value) -> otherwise.get(),
    this.Add != null ? this.Add : (left, right) -> otherwise.get(),
    this.Mult != null ? this.Mult : (left, right) -> otherwise.get(),
    this.Neg != null ? this.Neg : (expr) -> otherwise.get());
    return expression -> expression.match(cases);
    }
    }
    }