ast: Break compatibility
- Turned `static` and `const` into scoped modifiers (like `pub` - Added anonymous record patterns
This commit is contained in:
@@ -30,8 +30,6 @@ impl ToLisp {
|
||||
fn bind_op(&self, op: BindOp) -> &'static str {
|
||||
match op {
|
||||
BindOp::Let => "let",
|
||||
BindOp::Const => "const",
|
||||
BindOp::Static => "static",
|
||||
BindOp::Type => "type",
|
||||
BindOp::Fn => "fn",
|
||||
BindOp::Mod => "mod",
|
||||
@@ -51,6 +49,7 @@ impl ToLisp {
|
||||
PatOp::Rest => "rest",
|
||||
PatOp::RangeEx => "range-ex",
|
||||
PatOp::RangeIn => "range-in",
|
||||
PatOp::Record => "record",
|
||||
PatOp::Tuple => "tuple",
|
||||
PatOp::Slice => "slice",
|
||||
PatOp::ArRep => "ar-rep",
|
||||
@@ -75,6 +74,8 @@ impl ToLisp {
|
||||
Op::Call => "call",
|
||||
Op::Pub => "pub",
|
||||
Op::Loop => "loop",
|
||||
Op::Const => "const",
|
||||
Op::Static => "static",
|
||||
Op::Match => "match",
|
||||
Op::If => "if",
|
||||
Op::While => "while",
|
||||
@@ -201,7 +202,7 @@ impl<'a> Visit<'a> for ToLisp {
|
||||
Pat::MetId(id) => print!("(replace {id})"),
|
||||
Pat::Name(name) => print!("{name}"),
|
||||
Pat::Path(path) => path.visit_in(self)?,
|
||||
Pat::NamedStruct(path, pat) => {
|
||||
Pat::NamedRecord(path, pat) => {
|
||||
print!("(struct-pat ");
|
||||
path.visit_in(self)?;
|
||||
print!(" ");
|
||||
|
||||
20
src/ast.rs
20
src/ast.rs
@@ -81,8 +81,10 @@ pub enum Op {
|
||||
Call, // Expr ( Expr,* )
|
||||
|
||||
Pub, // pub Expr
|
||||
Const, // const Expr
|
||||
Static, // static Expr
|
||||
Loop, // loop Expr
|
||||
Match, // match Expr { <Let(Match, ..)>,* }
|
||||
Match, // match Expr { <Bind(Match, ..)>,* }
|
||||
If, // if Expr Expr (else Expr)?
|
||||
While, // while Expr Expr (else Expr)?
|
||||
Break, // break Expr
|
||||
@@ -176,8 +178,6 @@ pub enum Use {
|
||||
/// 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
|
||||
@@ -199,10 +199,6 @@ pub struct Bind<A: Annotation = Span>(
|
||||
pub enum BindOp {
|
||||
/// A `let Pat (= Expr (else Expr)?)?` binding
|
||||
Let,
|
||||
/// A `const Pat = Expr` binding
|
||||
Const,
|
||||
/// A `static Pat = Expr` binding
|
||||
Static,
|
||||
/// A type-alias binding
|
||||
Type,
|
||||
/// A `fn Pat Expr` binding
|
||||
@@ -251,7 +247,7 @@ pub enum Pat {
|
||||
/// Matches against a named const value
|
||||
Path(Path),
|
||||
/// Matches a Struct Expression `Ident { Pat }`
|
||||
NamedStruct(Path, Box<Pat>),
|
||||
NamedRecord(Path, Box<Pat>),
|
||||
/// Matches a Tuple Struct Expression `Ident ( Pat )`
|
||||
NamedTuple(Path, Box<Pat>),
|
||||
/// Matches a literal value by equality comparison
|
||||
@@ -277,15 +273,17 @@ pub enum PatOp {
|
||||
RangeEx,
|
||||
/// Matches an inclusive bounded range (`0..=100`)
|
||||
RangeIn,
|
||||
/// Matches the elements of a tuple
|
||||
/// Matches the elements of a record or struct { a, b, c }
|
||||
Record,
|
||||
/// Matches the elements of a tuple ( a, b, c )
|
||||
Tuple,
|
||||
/// Matches the elements of a slice or array
|
||||
/// Matches the elements of a slice or array [ a, b, c ]
|
||||
Slice,
|
||||
/// Matches a constant-size slice with repeating elements
|
||||
ArRep,
|
||||
/// Matches a type annotation or struct member
|
||||
Typed,
|
||||
/// Matches a function signature
|
||||
/// Changes the binding mode to "function-body"
|
||||
Fn,
|
||||
/// Matches one of a list of alternatives
|
||||
Alt,
|
||||
|
||||
@@ -81,6 +81,8 @@ impl Display for Op {
|
||||
Op::Index => "",
|
||||
Op::Call => "",
|
||||
Op::Pub => "pub ",
|
||||
Op::Const => "const ",
|
||||
Op::Static => "static ",
|
||||
Op::Loop => "loop ",
|
||||
Op::Match => "match ",
|
||||
Op::If => "if ",
|
||||
@@ -182,7 +184,7 @@ impl<A: Annotation> Display for Bind<A> {
|
||||
f.delimit(fmt!("{pat} "), "").list(exprs, ",!? ")
|
||||
}
|
||||
BindOp::Struct | BindOp::Enum => match pat {
|
||||
Pat::NamedStruct(name, bind) => match bind.as_ref() {
|
||||
Pat::NamedRecord(name, bind) => match bind.as_ref() {
|
||||
Pat::Op(PatOp::Tuple, parts) => f
|
||||
.delimit_indented(fmt!("{name} {{"), "}")
|
||||
.list_wrap("\n", parts, ",\n", ",\n"),
|
||||
@@ -211,8 +213,6 @@ impl Display for BindOp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
Self::Let => "let ",
|
||||
Self::Const => "const ",
|
||||
Self::Static => "static ",
|
||||
Self::Type => "type ",
|
||||
Self::Struct => "struct ",
|
||||
Self::Enum => "enum ",
|
||||
@@ -250,18 +250,22 @@ impl Display for Pat {
|
||||
Self::MetId(name) => write!(f, "`{name}"),
|
||||
Self::Name(name) => name.fmt(f),
|
||||
Self::Path(path) => path.fmt(f),
|
||||
Self::NamedStruct(name, bind) => match bind.as_ref() {
|
||||
Self::NamedRecord(name, bind) => match bind.as_ref() {
|
||||
Pat::Op(PatOp::Tuple, parts) => {
|
||||
f.delimit(fmt!("{name} {{ "), " }").list(parts, ", ")
|
||||
}
|
||||
other => write!(f, "{name} {{ {other} }}"),
|
||||
},
|
||||
Self::NamedTuple(name, bind) => write!(f, "{name} {bind}"),
|
||||
Self::Op(PatOp::Record, pats) => f.delimit("{ ", " }").list(pats, ", "),
|
||||
Self::Op(PatOp::Tuple, pats) => f.delimit("(", ")").list(pats, ", "),
|
||||
Self::Op(PatOp::Slice, pats) => f.delimit("[", "]").list(pats, ", "),
|
||||
Self::Op(op @ PatOp::ArRep, pats) => f.delimit("[", "]").list(pats, op),
|
||||
Self::Op(op @ (PatOp::Typed | PatOp::Fn), pats) => f.list(pats, op),
|
||||
Self::Op(op @ PatOp::Alt, pats) => f.delimit("<", ">").list(pats, op),
|
||||
Self::Op(op @ (PatOp::Typed | PatOp::Fn), pats) => match pats.as_slice() {
|
||||
[fun] => write!(f, "fn {fun}"), // TODO: reconsider this
|
||||
pats => f.list(pats, op),
|
||||
},
|
||||
Self::Op(op @ PatOp::Alt, pats) => f.list(pats, op),
|
||||
Self::Op(op, pats) => match pats.as_slice() {
|
||||
[] => op.fmt(f),
|
||||
[rest] => write!(f, "{op}{rest}"),
|
||||
@@ -281,6 +285,7 @@ impl Display for PatOp {
|
||||
Self::Rest => "..",
|
||||
Self::RangeEx => "..",
|
||||
Self::RangeIn => "..=",
|
||||
Self::Record => ", ",
|
||||
Self::Tuple => ", ",
|
||||
Self::Slice => ", ",
|
||||
Self::ArRep => "[;]",
|
||||
|
||||
@@ -149,8 +149,8 @@ impl<A: Annotation> Foldable<A> for Pat {
|
||||
Self::MetId(name) => Self::MetId(name.fold_in(folder)?),
|
||||
Self::Name(name) => Self::Name(name.fold_in(folder)?),
|
||||
Self::Path(path) => Self::Path(path.fold_in(folder)?),
|
||||
Self::NamedStruct(path, pat) => {
|
||||
Self::NamedStruct(path.fold_in(folder)?, pat.fold_in(folder)?)
|
||||
Self::NamedRecord(path, pat) => {
|
||||
Self::NamedRecord(path.fold_in(folder)?, pat.fold_in(folder)?)
|
||||
}
|
||||
Self::NamedTuple(path, pat) => {
|
||||
Self::NamedTuple(path.fold_in(folder)?, pat.fold_in(folder)?)
|
||||
|
||||
@@ -174,8 +174,8 @@ impl<A: Annotation> Match<A> for Pat {
|
||||
(Pat::Name(_), _) => false,
|
||||
(Pat::Path(_), Pat::Path(_)) => true,
|
||||
(Pat::Path(_), _) => false,
|
||||
(Pat::NamedStruct(_, pat), Pat::NamedStruct(_, expr)) => Match::recurse(sub, pat, expr),
|
||||
(Pat::NamedStruct(..), _) => false,
|
||||
(Pat::NamedRecord(_, pat), Pat::NamedRecord(_, expr)) => Match::recurse(sub, pat, expr),
|
||||
(Pat::NamedRecord(..), _) => false,
|
||||
(Pat::NamedTuple(_, pat), Pat::NamedTuple(_, expr)) => Match::recurse(sub, pat, expr),
|
||||
(Pat::NamedTuple(..), _) => false,
|
||||
(Pat::Lit(pat), Pat::Lit(expr)) => pat == expr,
|
||||
@@ -193,7 +193,7 @@ impl<A: Annotation> Match<A> for Pat {
|
||||
*self = expr.clone();
|
||||
}
|
||||
}
|
||||
Pat::NamedStruct(_, expr) => expr.apply(sub),
|
||||
Pat::NamedRecord(_, expr) => expr.apply(sub),
|
||||
Pat::NamedTuple(_, expr) => expr.apply(sub),
|
||||
Pat::Op(_, pats) => pats.apply(sub),
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ impl<'a> Walk<'a> for Pat {
|
||||
Self::MetId(id) => id.visit_in(v),
|
||||
Self::Name(name) => name.visit_in(v),
|
||||
Self::Path(path) => path.visit_in(v),
|
||||
Self::NamedStruct(path, pat) | Self::NamedTuple(path, pat) => {
|
||||
Self::NamedRecord(path, pat) | Self::NamedTuple(path, pat) => {
|
||||
path.visit_in(v)?;
|
||||
pat.visit_in(v)
|
||||
}
|
||||
|
||||
@@ -101,6 +101,8 @@ fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
|
||||
TKind::Use => (Ps::Use, Prec::Max),
|
||||
|
||||
TKind::Pub => (Ps::Op(Op::Pub), Prec::Body),
|
||||
TKind::Const => (Ps::Op(Op::Const), Prec::Body),
|
||||
TKind::Static => (Ps::Op(Op::Static), Prec::Body),
|
||||
TKind::For => (Ps::For, Prec::Body),
|
||||
TKind::Match => (Ps::Op(Op::Match), Prec::Body),
|
||||
TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
|
||||
@@ -109,8 +111,6 @@ fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
|
||||
| TKind::Mod
|
||||
| TKind::Impl
|
||||
| TKind::Let
|
||||
| TKind::Const
|
||||
| TKind::Static
|
||||
| TKind::Type
|
||||
| TKind::Struct
|
||||
| TKind::Enum => (Ps::Def, Prec::Body),
|
||||
@@ -440,8 +440,6 @@ fn from_bind(p: &mut Parser<'_>) -> PResult<(BindOp, PPrec, Option<TKind>, Optio
|
||||
let bk = match p.peek()?.kind {
|
||||
// Token Operator Pat prec Body Token Body prec Else prec
|
||||
TKind::Let => (BindOp::Let, PPrec::Tuple, Some(TKind::Eq), Some(Prec::Tuple), Some(Prec::Body)),
|
||||
TKind::Const => (BindOp::Const, PPrec::Tuple, Some(TKind::Eq), Some(Prec::Tuple), None),
|
||||
TKind::Static => (BindOp::Static, PPrec::Tuple, Some(TKind::Eq), Some(Prec::Tuple), None),
|
||||
TKind::Type => (BindOp::Type, PPrec::Tuple, Some(TKind::Eq), Some(Prec::Extend), None),
|
||||
TKind::Struct => (BindOp::Struct, PPrec::Tuple, None, None, None),
|
||||
TKind::Enum => (BindOp::Enum, PPrec::Tuple, None, None, None),
|
||||
|
||||
@@ -73,12 +73,12 @@ impl<'t> Parse<'t> for Pat {
|
||||
|
||||
// Prefix
|
||||
let mut head = match tok.kind {
|
||||
TKind::Fn => return p.consume().parse(Prec::Fn),
|
||||
TKind::True | TKind::False | TKind::Character | TKind::Integer | TKind::String => {
|
||||
Pat::Lit(p.parse(())?)
|
||||
}
|
||||
TKind::Bar => p.consume().parse(level)?,
|
||||
TKind::Bang => p.consume().then(Pat::Never),
|
||||
TKind::Fn => Pat::Op(PatOp::Fn, vec![p.consume().parse(Prec::Typed)?]),
|
||||
TKind::Amp => Pat::Op(PatOp::Ref, vec![p.consume().parse(Prec::Max)?]),
|
||||
TKind::Star => Pat::Op(PatOp::Ptr, vec![p.consume().parse(Prec::Max)?]),
|
||||
TKind::Mut => Pat::Op(PatOp::Mut, vec![p.consume().parse(Prec::Max)?]),
|
||||
@@ -94,7 +94,7 @@ impl<'t> Parse<'t> for Pat {
|
||||
// TODO: make these postfix.
|
||||
match p.peek().map(Token::kind) {
|
||||
Ok(TKind::LParen) => Pat::NamedTuple(path, p.parse(Prec::Typed)?),
|
||||
Ok(TKind::LCurly) if level <= Prec::Tuple.next() => Pat::NamedStruct(
|
||||
Ok(TKind::LCurly) if level <= Prec::Tuple.next() => Pat::NamedRecord(
|
||||
path,
|
||||
p.consume()
|
||||
.opt(Prec::Tuple, TKind::RCurly)?
|
||||
@@ -130,6 +130,11 @@ impl<'t> Parse<'t> for Pat {
|
||||
_ => vec![],
|
||||
},
|
||||
),
|
||||
TKind::LCurly => Pat::Op(
|
||||
PatOp::Record,
|
||||
p.consume()
|
||||
.list(vec![], Prec::Typed, TKind::Comma, TKind::RCurly)?,
|
||||
),
|
||||
TKind::LParen => Pat::Op(
|
||||
PatOp::Tuple,
|
||||
p.consume()
|
||||
@@ -145,9 +150,9 @@ impl<'t> Parse<'t> for Pat {
|
||||
{
|
||||
let kind = tok.kind;
|
||||
head = match op {
|
||||
PatOp::Typed => Pat::Op(PatOp::Typed, vec![head, p.consume().parse(prec.next())?]),
|
||||
PatOp::Fn => Pat::Op(PatOp::Fn, vec![head, p.consume().parse(Prec::Fn.next())?]),
|
||||
op @ (PatOp::RangeEx | PatOp::RangeIn) => Pat::Op(
|
||||
PatOp::Typed => Pat::Op(op, vec![head, p.consume().parse(prec.next())?]),
|
||||
PatOp::Fn => Pat::Op(op, vec![head, p.consume().parse(Prec::Fn.next())?]),
|
||||
PatOp::RangeEx | PatOp::RangeIn => Pat::Op(
|
||||
op,
|
||||
match p.consume().peek().map(Token::kind) {
|
||||
Ok(TKind::Integer | TKind::Character | TKind::Identifier) => {
|
||||
@@ -156,7 +161,7 @@ impl<'t> Parse<'t> for Pat {
|
||||
_ => vec![head],
|
||||
},
|
||||
),
|
||||
op => Pat::Op(op, p.consume().list_bare(vec![head], prec.next(), kind)?),
|
||||
_ => Pat::Op(op, p.consume().list_bare(vec![head], prec.next(), kind)?),
|
||||
}
|
||||
}
|
||||
Ok(head)
|
||||
|
||||
Reference in New Issue
Block a user