114 lines
3 KiB
Rust
114 lines
3 KiB
Rust
use std::fmt;
|
|
|
|
use crate::symbol::Symbol;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub enum Ident {
|
|
/// `x`
|
|
Local(Symbol),
|
|
/// `^x`
|
|
Return(Symbol),
|
|
}
|
|
|
|
impl fmt::Display for Ident {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Ident::Local(name) => write!(f, "{name}"),
|
|
Ident::Return(name) => write!(f, "^{name}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub enum BinOp {
|
|
Add,
|
|
Sub,
|
|
Mul,
|
|
Div,
|
|
Mod,
|
|
Pow,
|
|
Eq,
|
|
Lt,
|
|
Le,
|
|
}
|
|
|
|
impl fmt::Display for BinOp {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let str = match self {
|
|
BinOp::Add => "+",
|
|
BinOp::Sub => "-",
|
|
BinOp::Mul => "*",
|
|
BinOp::Div => "/",
|
|
BinOp::Mod => "%",
|
|
BinOp::Pow => "**",
|
|
BinOp::Eq => "=",
|
|
BinOp::Lt => "<",
|
|
BinOp::Le => "<=",
|
|
};
|
|
write!(f, "{str}")
|
|
}
|
|
}
|
|
|
|
// TODO: great display repr for this for testing (yes it's allowed)
|
|
#[derive(Debug, Clone)]
|
|
pub enum Ast {
|
|
/// `x`, `^x`
|
|
Var(Ident),
|
|
/// `x := y; #=> y`
|
|
Set(Ident, Box<Ast>),
|
|
/// `fn ([a b] [c d]) ( ... )`
|
|
Fn {
|
|
inputs: Vec<Symbol>,
|
|
outputs: Vec<Symbol>,
|
|
body: Vec<Ast>,
|
|
},
|
|
/// `{^x; ^y := z}`
|
|
Map(Vec<Ast>),
|
|
/// `f x`
|
|
App(Box<Ast>, Box<Ast>),
|
|
/// `x + y` (only builtins, sorry)
|
|
BinOp(Box<Ast>, BinOp, Box<Ast>),
|
|
/// `3`
|
|
Num(f64),
|
|
/// `(println bla; 3) #=> 3`
|
|
Block(Vec<Ast>),
|
|
}
|
|
|
|
impl fmt::Display for Ast {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Ast::Var(ident) => write!(f, "{ident}"),
|
|
Ast::Set(ident, ast) => write!(f, "(set! {ident} {ast})"),
|
|
Ast::Fn {
|
|
inputs,
|
|
outputs,
|
|
body,
|
|
} => {
|
|
let body: Vec<_> = body.iter().map(|stmt| format!("{stmt}")).collect();
|
|
if body.is_empty() {
|
|
write!(f, "(fn ([{}] [{}]))", inputs.join(" "), outputs.join(" "),)
|
|
} else {
|
|
write!(
|
|
f,
|
|
"(fn ([{}] [{}]) {})",
|
|
inputs.join(" "),
|
|
outputs.join(" "),
|
|
body.join(" ")
|
|
)
|
|
}
|
|
}
|
|
Ast::Map(body) => {
|
|
let body: Vec<_> = body.iter().map(|stmt| format!("{stmt}")).collect();
|
|
write!(f, "{{{}}}", body.join(" "))
|
|
}
|
|
Ast::App(func, x) => write!(f, "({func} {x})"),
|
|
Ast::BinOp(lhs, op, rhs) => write!(f, "({lhs} {op} {rhs})"),
|
|
Ast::Num(n) => write!(f, "{n}"),
|
|
Ast::Block(body) => {
|
|
let body: Vec<_> = body.iter().map(|stmt| format!("{stmt}")).collect();
|
|
write!(f, "({})", body.join(" "))
|
|
}
|
|
}
|
|
}
|
|
}
|