ast: fn main, structification

parser: unified post/infix, context-full grammar
repl: modes
This commit is contained in:
2025-09-21 02:57:20 -04:00
parent 434fa225e7
commit 8640ec4261
4 changed files with 342 additions and 151 deletions

View File

@@ -58,7 +58,7 @@ pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>
/// (Pat |)* Pat? => Expr
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MatchArm<A: Annotation = Span>(pub Vec<Pat>, pub Anno<Expr<A>, A>);
pub struct MatchArm<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
/// In-universe types
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -77,6 +77,22 @@ pub enum Ty {
Fn(Vec<Ty>),
}
/// A `const` binding (which defines its name before executing)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Const<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
/// A function definition `fn Ident? (Pat,*) Expr`
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Fn<A: Annotation = Span>(pub Option<String>, pub Pat, pub Anno<Expr<A>, A>);
/// A `let` binding: `let Pat (= Expr)?`
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Let<A: Annotation = Span>(pub Pat, pub Option<Anno<Expr<A>, A>>);
/// `match Expr { MatchArm,* }``
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Match<A: Annotation = Span>(pub Anno<Expr<A>, A>, pub Vec<MatchArm<A>>);
/// Expressions: The beating heart of Dough
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr<A: Annotation = Span> {
@@ -87,15 +103,15 @@ pub enum Expr<A: Annotation = Span> {
/// A literal bool, string, char, or int
Lit(Literal),
/// let Pat<NoTopAlt> = expr
Let(Pat, Option<Box<Anno<Self, A>>>),
Let(Box<Let<A>>),
/// `const Pat<NoTopAlt> (= Expr)?` (Basically let rec)
Const(Pat, Box<Anno<Self, A>>),
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn (Pat,*) Expr`
Fn(Pat, Box<Anno<Self, A>>),
Const(Box<Const<A>>),
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr`
Fn(Box<Fn<A>>),
/// Expr { (Ident (: Expr)?),* }
Make(Box<Anno<Self, A>>, Vec<MakeArm<A>>),
/// match Expr { MatchArm,* }
Match(Box<Anno<Self, A>>, Vec<MatchArm<A>>),
Match(Box<Match<A>>),
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
Op(Op, Vec<Anno<Self, A>>),
}
@@ -205,22 +221,52 @@ impl<T: Display + Annotation, A: Annotation> Display for Anno<T, A> {
}
}
impl<A: Annotation> Display for Const<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(pat, expr) = self;
write!(f, "const {pat} = {expr}")
}
}
impl<A: Annotation> Display for Fn<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self(Some(name), pat, expr) => write!(f, "fn {name} {pat} {expr}"),
Self(None, pat, expr) => write!(f, "|{pat}| {expr}"),
}
}
}
impl<A: Annotation> Display for Let<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self(pat, Some(expr)) => write!(f, "let {pat} = {expr}"),
Self(pat, None) => write!(f, "let ({pat})"),
}
}
}
impl<A: Annotation> Display for Match<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(expr, match_arms) = self;
f.delimit_indented(fmt!("match {expr} {{"), "}")
.list_wrap("\n", match_arms, ",\n", ",\n")
}
}
impl<A: Annotation> Display for Expr<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Id(id) => id.fmt(f),
Self::MetId(id) => write!(f, "`{id}"),
Self::Lit(literal) => literal.fmt(f),
Self::Let(pat, Some(expr)) => write!(f, "let {pat} = {expr}"),
Self::Let(pat, None) => write!(f, "let ({pat})"),
Self::Const(pat, expr) => write!(f, "const {pat} = {expr}"),
Self::Let(v) => v.fmt(f),
Self::Const(v) => v.fmt(f),
Self::Make(expr, make_arms) => {
f.delimit(fmt!("({expr} {{"), "})").list(make_arms, ", ")
}
Self::Match(expr, match_arms) => f
.delimit_indented(fmt!("match {expr} {{"), "}")
.list_wrap("\n", match_arms, ",\n", ",\n"),
Self::Fn(pat, expr) => write!(f, "fn {pat} {expr}"),
Self::Match(v) => v.fmt(f),
Self::Fn(v) => v.fmt(f),
Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
[cond, pass, fail] => write!(f, "{op}{cond} {pass} else {fail}"),
@@ -315,8 +361,8 @@ impl<A: Annotation> Display for MakeArm<A> {
impl<A: Annotation> Display for MatchArm<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(pats, expr) = self;
f.delimit("", fmt!(" => {expr}")).list(pats, " | ")
let Self(pat, expr) = self;
write!(f, "{pat} => {expr}")
}
}