[package] [Java implementation] [Execution output]


Expression


class Expression<T>: {
    const(T: value),
    var(String: name),
    app(String: fun, Expression<T>: arg),
    sum(Expression<T>: a, Expression<T>: b),
    neg(Expression<T>: a),
    sub(Expression<T>: a, Expression<T>: b),
    prd(Expression<T>: a, Expression<T>: b),
    div(Expression<T>: a, Expression<T>: b),
    pow(Expression<T>: a, T: n)
};

evaluate(funNameToFunction, Expression: exp0, varNameToValue) = {
    eval(Expression: exp) = {
         const(value) −> value,
            var(name) −> varNameToValue(name),
      app(funName, a) −> funNameToFunction(funName)(eval(a)),
            sum(f, g) −>  eval(f) + eval(g),
               neg(f) −> -eval(f),
            sub(f, g) −>  eval(f) - eval(g),
            prd(f, g) −>  eval(f) * eval(g),
            div(f, g) −>  eval(f) / eval(g),
            pow(f, n) −>  eval(f) ^ n
    }.get(exp);
    eval(exp0);
}

exprEqual(a, b) = {
     const(v1) −> {const(v2) −> v1 == v2}.getOrDefault(b, false),
       var(n1) −> {  var(n2) −> n1 == n2}.getOrDefault(b, false)
}.getOrDefault(a, false);

/***********************************************************************************************************************
*                                                      Operators                                                       *
***********************************************************************************************************************/

// Output to streams

                                       stream <<  const(v) = stream << v;
                                       stream << var(name) = stream << name;
                                       stream << app(f, a) = stream << f << "(" << a << ")";
                                       stream << sum(a, b) = stream << a << " + " << b;
                                       stream <<    neg(a) = stream << "-" << a;
                                       stream << sub(a, b) = stream << a << " - " << b;
                                       stream << prd(a, b) = stream << a << " * " << b;
                                       stream << div(a, b) = stream << a << " / " << b;
                                       stream << pow(a, b) = stream << a << "^" << b;

// Arithmetic identities

                        (Expression: a) == (Expression: b) = exprEqual(a, b);

                                         additive_identity = const(additive_identity);
                                   multiplicative_identity = const(multiplicative_identity);

                         (Expression: a) + (Expression: b) = a == additive_identity ? b :
                                                             b == additive_identity ? a :
                                                             sum(a, b);

                                          -(Expression: a) = neg(a);

                         (Expression: a) - (Expression: b) = a == additive_identity ? -b :
                                                             b == additive_identity ? a :
                                                             sub(a, b);

                         (Expression: a) * (Expression: b) = a == additive_identity ? additive_identity :
                                                             b == additive_identity ? additive_identity :
                                                             a == multiplicative_identity ? b :
                                                             b == multiplicative_identity ? a :
                                                             prd(a, b);
                                                             
                         (Expression: a) / (Expression: b) = a == additive_identity ? additive_identity :
                                                             b == multiplicative_identity ? a :
                                                             div(a, b);

                                       (Expression: a) ^ n = a == additive_identity ? additive_identity :
                                                             n == additive_identity ? multiplicative_identity :
                                                             n == multiplicative_identity ? a :
                                                             pow(a, n);