///|
using @debug {trait Debug, type Repr}
///|
fn ordinary_application_name_args(expr : Expr) -> (String, Array[Expr])? {
match application_parts(expr) {
Some((head, args)) =>
match head {
Expr::FunctionHead(name) | Expr::UndefinedFunction(name) =>
Some((name, args))
_ => None
}
None => None
}
}
///|
fn derivative_call_args(inner : Expr, deriv_args : Array[Expr]) -> Array[Expr] {
let out : Array[Expr] = [inner]
let pair_count = deriv_args.length() / 2
for i in 0.. out.push(wrt)
_ => out.push(Expr::Tuple([wrt, order]))
}
}
out
}
///|
fn wrap_call_repr(name : String, args : Array[Expr]) -> String {
let rendered_args = args.map(arg => to_repr(arg).to_string())
let suffix = if rendered_args.is_empty() {
""
} else {
" " + rendered_args.join(" ")
}
"(call \{name}\{suffix})"
}
///|
fn wrap_variadic_repr(head : String, args : Array[Expr]) -> String {
if args.is_empty() {
"(\{head})"
} else {
let rendered = args.map(arg => to_repr(arg).to_string()).join(" ")
"(\{head} \{rendered})"
}
}
///|
fn wrap_apply_repr(head : Expr, args : Array[Expr]) -> String {
let rendered_args = args.map(arg => to_repr(arg).to_string())
let suffix = if rendered_args.is_empty() {
""
} else {
" " + rendered_args.join(" ")
}
"(apply \{to_repr(head).to_string()}\{suffix})"
}
///|
pub impl Debug for Expr with to_repr(self) {
let rendered = match ordinary_application_name_args(self) {
Some((name, args)) => wrap_call_repr(name, args)
None =>
match expr_form(self) {
ExprForm::Number(n) => n.to_string()
ExprForm::Float(f) => f.to_string()
ExprForm::ComplexFloat(z) => z.to_string()
ExprForm::NumberSymbol(kind) => "const:\{number_symbol_name(kind)}"
ExprForm::Symbol(name) => "sym:\{name}"
ExprForm::Dummy(name, id) => "dummy:\{dummy_display_name(name)}#\{id}"
ExprForm::Wild(name, _, _) => "wild:\{wild_display_name(name)}"
ExprForm::WildFunction(name, _) =>
"wild_function:\{wild_display_name(name)}"
ExprForm::IdentityFunction => "(call IdentityFunction)"
ExprForm::FunctionHead(name) => "fhead:\{name}"
ExprForm::UndefinedFunction(name) => "ufunc:\{name}"
ExprForm::Boolean(true) => "sym:True"
ExprForm::Boolean(false) => "sym:False"
ExprForm::Add(args) => wrap_variadic_repr("+", args)
ExprForm::Mul(args) => wrap_variadic_repr("*", args)
ExprForm::Pow(base, exp) =>
"(^ \{to_repr(base).to_string()} \{to_repr(exp).to_string()})"
ExprForm::Mod(lhs, rhs) => wrap_call_repr("Mod", [lhs, rhs])
ExprForm::Tuple(args) => wrap_call_repr("Tuple", args)
ExprForm::Dict(items) => {
let args : Array[Expr] = []
for item in items {
let (key, value) = item
args.push(Expr::Tuple([key, value]))
}
wrap_call_repr("Dict", args)
}
ExprForm::Relational(op, lhs, rhs) => {
let name = match op {
RelOp::Eq => "Eq"
RelOp::Ne => "Ne"
RelOp::Lt => "Lt"
RelOp::Le => "Le"
RelOp::Gt => "Gt"
RelOp::Ge => "Ge"
}
wrap_call_repr(name, [lhs, rhs])
}
ExprForm::Derivative(inner, deriv_args) =>
wrap_call_repr("Derivative", derivative_call_args(inner, deriv_args))
ExprForm::Subs(inner, variable, value) =>
wrap_call_repr("Subs", [inner, variable, value])
ExprForm::Lambda(vars, body) => wrap_call_repr("Lambda", [vars, body])
ExprForm::Apply(head, args) =>
match function_head_name(head) {
Some(name) => wrap_call_repr(name, args)
None => wrap_apply_repr(head, args)
}
}
}
Repr::literal(rendered)
}