#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Position(usize);
impl Position {
#[must_use]
pub fn value(&self) -> usize {
self.0
}
}
impl From<usize> for Position {
fn from(value: usize) -> Self {
Self(value)
}
}
impl std::fmt::Display for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct VarName(String);
impl VarName {
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<String> for VarName {
fn from(value: String) -> Self {
Self(value)
}
}
impl From<&str> for VarName {
fn from(value: &str) -> Self {
Self(value.to_owned())
}
}
impl std::fmt::Display for VarName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expr {
Var(VarName),
Lam {
param: VarName,
body: Box<Expr>,
},
App {
func: Box<Expr>,
arg: Box<Expr>,
},
Let {
name: VarName,
value: Box<Expr>,
body: Box<Expr>,
},
Fix {
name: VarName,
body: Box<Expr>,
},
Ref {
inner: Box<Expr>,
},
Deref {
inner: Box<Expr>,
},
Assign {
target: Box<Expr>,
value: Box<Expr>,
},
Seq {
first: Box<Expr>,
second: Box<Expr>,
},
}
impl Expr {
#[must_use]
pub fn var(name: impl Into<VarName>) -> Self {
Self::Var(name.into())
}
#[must_use]
pub fn lam(param: impl Into<VarName>, body: Self) -> Self {
Self::Lam {
param: param.into(),
body: Box::new(body),
}
}
#[must_use]
pub fn app(func: Self, arg: Self) -> Self {
Self::App {
func: Box::new(func),
arg: Box::new(arg),
}
}
#[must_use]
pub fn bind(name: impl Into<VarName>, value: Self, body: Self) -> Self {
Self::Let {
name: name.into(),
value: Box::new(value),
body: Box::new(body),
}
}
#[must_use]
pub fn fix(name: impl Into<VarName>, body: Self) -> Self {
Self::Fix {
name: name.into(),
body: Box::new(body),
}
}
#[must_use]
pub fn alloc(inner: Self) -> Self {
Self::Ref {
inner: Box::new(inner),
}
}
#[must_use]
pub fn deref(inner: Self) -> Self {
Self::Deref {
inner: Box::new(inner),
}
}
#[must_use]
pub fn assign(target: Self, value: Self) -> Self {
Self::Assign {
target: Box::new(target),
value: Box::new(value),
}
}
#[must_use]
pub fn seq(first: Self, second: Self) -> Self {
Self::Seq {
first: Box::new(first),
second: Box::new(second),
}
}
}
impl std::fmt::Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Var(name) => write!(f, "{name}"),
Self::Lam { param, body } => write!(f, "(\\{param}. {body})"),
Self::App { func, arg } => write!(f, "({func} {arg})"),
Self::Let { name, value, body } => {
write!(f, "(let {name} = {value} in {body})")
}
Self::Fix { name, body } => write!(f, "(fix {name}. {body})"),
Self::Ref { inner } => write!(f, "(ref {inner})"),
Self::Deref { inner } => write!(f, "(!{inner})"),
Self::Assign { target, value } => write!(f, "({target} := {value})"),
Self::Seq { first, second } => write!(f, "({first} ; {second})"),
}
}
}