syntax: Merge ALL definitions into Bind, and allow type variable introducers at every Bind

This commit is contained in:
2025-10-28 02:27:56 -04:00
parent a29adeeef3
commit 0bf5a41498
4 changed files with 116 additions and 122 deletions

View File

@@ -114,30 +114,26 @@ pub enum PatOp {
Alt,
}
/// A record-type definition
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Typedef(pub TypedefKind, pub Pat);
/// The type of type being defined
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TypedefKind {
Struct,
Enum,
}
/// A pattern binding
/// ```ignore
/// let Pat (= Expr (else Expr)?)?
/// const Pat (= Expr (else Expr)?)?
/// static Pat (= Expr (else Expr)?)?
/// type Pat (= Expr)?
/// struct Pat
/// enum Pat
/// fn Pat Expr
/// mod Pat Expr
/// impl Pat Expr
/// Pat => Expr // in match
/// ``````
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Bind<A: Annotation = Span>(pub BindKind, pub Pat, pub Vec<Anno<Expr<A>, A>>);
pub struct Bind<A: Annotation = Span>(
pub BindKind,
pub Vec<FqPath>,
pub Pat,
pub Vec<Anno<Expr<A>, A>>,
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BindKind {
@@ -149,6 +145,10 @@ pub enum BindKind {
Static,
/// A type-alias binding
Type,
/// A struct definition
Struct,
/// An enum definition
Enum,
/// A `fn Pat Expr` binding
Fn,
/// A `mod Pat Expr` binding
@@ -176,6 +176,8 @@ pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>
/// Expressions: The beating heart of Dough
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr<A: Annotation = Span> {
/// Omitted by semicolon insertion-elision rules
Omitted,
/// An identifier
Id(FqPath),
/// An escaped token for macro binding
@@ -187,8 +189,6 @@ pub enum Expr<A: Annotation = Span> {
/// `(let | const | static) Pat::NoTopAlt (= expr (else expr)?)?` |
/// `(fn | mod | impl) Pat::Fn Expr`
Bind(Box<Bind<A>>),
/// (struct | enum | type) Pat::NoTopAlt
Struct(Box<Typedef>),
/// Expr { (Ident (: Expr)?),* }
Make(Box<Make<A>>),
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
@@ -212,13 +212,14 @@ pub enum Op {
Index, // Expr [ Expr,* ]
Call, // Expr ( Expr,* )
Pub, // pub Expr
Loop, // loop Expr
Match, // match Expr { <Let(Match, ..)>,* }
If, // if Expr Expr (else Expr)?
While, // while Expr Expr (else Expr)?
Break, // break Expr
Return, // return Expr
Pub, // pub Expr
Loop, // loop Expr
Match, // match Expr { <Let(Match, ..)>,* }
If, // if Expr Expr (else Expr)?
While, // while Expr Expr (else Expr)?
Break, // break Expr
Return, // return Expr
Continue, // continue
Dot, // Expr . Expr
@@ -356,18 +357,31 @@ impl Display for Use {
impl<A: Annotation> Display for Bind<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(op, pat, exprs) = self;
let Self(op, gens, pat, exprs) = self;
op.fmt(f)?;
if !gens.is_empty() {
f.delimit("<", "> ").list(gens, ", ")?;
}
match op {
BindKind::Match => f.delimit(fmt!("{pat} => "), "").list(exprs, ",!? "),
BindKind::Fn | BindKind::Mod | BindKind::Impl => {
f.delimit(fmt!("{op}{pat} "), "").list(exprs, ",!? ")
f.delimit(fmt!("{pat} "), "").list(exprs, ",!? ")
}
BindKind::Struct | BindKind::Enum => match pat {
Pat::NamedStruct(name, bind) => match bind.as_ref() {
Pat::Op(PatOp::Tuple, parts) => f
.delimit_indented(fmt!("{name} {{"), "}")
.list_wrap("\n", parts, ",\n", ",\n"),
other => write!(f, "{name} {{ {other} }}"),
},
_ => pat.fmt(f),
},
_ => match exprs.as_slice() {
[] => write!(f, "{op}{pat}"),
[value] => write!(f, "{op}{pat} = {value}"),
[value, fail] => write!(f, "{op} {pat} = {value} else {fail}"),
other => f.delimit(fmt!("{op}{pat} ("), ")").list(other, ", "),
[] => write!(f, "{pat}"),
[value] => write!(f, "{pat} = {value}"),
[value, fail] => write!(f, "{pat} = {value} else {fail}"),
other => f.delimit(fmt!("{pat} ("), ")").list(other, ", "),
},
}
}
@@ -380,10 +394,12 @@ impl Display for BindKind {
Self::Const => "const ",
Self::Static => "static ",
Self::Type => "type ",
Self::Struct => "struct ",
Self::Enum => "enum ",
Self::Fn => "fn ",
Self::Mod => "mod ",
Self::Impl => "impl ",
Self::Match => "| ",
Self::Match => "",
})
}
}
@@ -395,34 +411,15 @@ impl<A: Annotation> Display for Make<A> {
}
}
impl Display for Typedef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(kind, pat) = self;
f.write_str(match kind {
TypedefKind::Struct => "struct ",
TypedefKind::Enum => "enum ",
})?;
match pat {
Pat::NamedStruct(name, bind) => match bind.as_ref() {
Pat::Op(PatOp::Tuple, parts) => f
.delimit_indented(fmt!("{name} {{"), "}")
.list_wrap("\n", parts, ",\n", ",\n"),
other => write!(f, "{name} {{ {other} }}"),
},
_ => pat.fmt(f),
}
}
}
impl<A: Annotation> Display for Expr<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Omitted => "/* omitted */".fmt(f),
Self::Id(id) => id.fmt(f),
Self::MetId(id) => write!(f, "`{id}"),
Self::Lit(literal) => literal.fmt(f),
Self::Use(v) => write!(f, "use {v}"),
Self::Bind(v) => v.fmt(f),
Self::Struct(v) => v.fmt(f),
Self::Make(v) => v.fmt(f),
Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
@@ -446,7 +443,7 @@ impl<A: Annotation> Display for Expr<A> {
Self::Op(Op::Tuple, exprs) => f.delimit("(", ")").list(exprs, ", "),
Self::Op(Op::Group, exprs) => f.list(exprs, ", "),
Self::Op(Op::Meta, exprs) => match exprs.as_slice() {
[meta, expr @ ..] => f.delimit(fmt!("#[{meta}] "), "").list(expr, ","),
[meta, expr @ ..] => f.delimit(fmt!("#[{meta}]\n"), "").list(expr, ","),
[] => write!(f, "#[]"),
},
@@ -492,6 +489,7 @@ impl Display for Op {
Op::While => "while ",
Op::Break => "break ",
Op::Return => "return ",
Op::Continue => "continue",
Op::Dot => ".",
Op::RangeEx => "..",
Op::RangeIn => "..=",