AST: merge let, const, static, match_arm into one binder
This commit is contained in:
89
src/ast.rs
89
src/ast.rs
@@ -111,14 +111,19 @@ pub enum Ty {
|
|||||||
/// let Pat (= Expr)?
|
/// let Pat (= Expr)?
|
||||||
/// ``````
|
/// ``````
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Let<A: Annotation = Span>(pub Pat, pub Vec<Anno<Expr<A>, A>>);
|
pub struct Let<A: Annotation = Span>(pub LetKind, pub Pat, pub Vec<Anno<Expr<A>, A>>);
|
||||||
|
|
||||||
/// A `const` binding (which defines its name before executing)
|
|
||||||
/// ```ignore
|
|
||||||
/// const Pat = Expr
|
|
||||||
/// ```
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Const<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
pub enum LetKind {
|
||||||
|
/// A `let Pat (= Expr (else Expr)?)?` binding
|
||||||
|
Let,
|
||||||
|
/// A `const Pat = Expr` binding
|
||||||
|
Const,
|
||||||
|
/// A `static Pat = Expr` binding
|
||||||
|
Static,
|
||||||
|
/// A `Pat => Expr` binding
|
||||||
|
Match,
|
||||||
|
}
|
||||||
|
|
||||||
/// A function definition
|
/// A function definition
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
@@ -127,20 +132,6 @@ pub struct Const<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
|||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Fn<A: Annotation = Span>(pub Option<String>, pub Pat, pub Ty, pub Anno<Expr<A>, A>);
|
pub struct Fn<A: Annotation = Span>(pub Option<String>, pub Pat, pub Ty, pub Anno<Expr<A>, A>);
|
||||||
|
|
||||||
/// A match expression
|
|
||||||
/// ```ignore
|
|
||||||
/// match Expr { MatchArm,* }
|
|
||||||
/// ```
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct Match<A: Annotation = Span>(pub Anno<Expr<A>, A>, pub Vec<MatchArm<A>>);
|
|
||||||
|
|
||||||
/// The "arms" of a match expression
|
|
||||||
/// ```ignore
|
|
||||||
/// Pat => Expr
|
|
||||||
/// ```
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct MatchArm<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
|
||||||
|
|
||||||
/// A make (constructor) expression
|
/// A make (constructor) expression
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// Expr { (Ident (: Expr)?),* }
|
/// Expr { (Ident (: Expr)?),* }
|
||||||
@@ -185,16 +176,12 @@ pub enum Expr<A: Annotation = Span> {
|
|||||||
Lit(Literal),
|
Lit(Literal),
|
||||||
/// let Pat<NoTopAlt> = expr
|
/// let Pat<NoTopAlt> = expr
|
||||||
Let(Box<Let<A>>),
|
Let(Box<Let<A>>),
|
||||||
/// `const Pat<NoTopAlt> (= Expr)?` (Basically let rec)
|
|
||||||
Const(Box<Const<A>>),
|
|
||||||
/// (struct | enum | type) Pat<NoTopAlt>
|
/// (struct | enum | type) Pat<NoTopAlt>
|
||||||
Struct(Box<Typedef>),
|
Struct(Box<Typedef>),
|
||||||
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr`
|
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr`
|
||||||
Fn(Box<Fn<A>>),
|
Fn(Box<Fn<A>>),
|
||||||
/// Expr { (Ident (: Expr)?),* }
|
/// Expr { (Ident (: Expr)?),* }
|
||||||
Make(Box<Make<A>>),
|
Make(Box<Make<A>>),
|
||||||
/// match Expr { MatchArm,* }
|
|
||||||
Match(Box<Match<A>>),
|
|
||||||
/// mod Ty Expr
|
/// mod Ty Expr
|
||||||
Mod(Box<Mod<A>>),
|
Mod(Box<Mod<A>>),
|
||||||
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
|
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
|
||||||
@@ -259,6 +246,7 @@ pub enum Op {
|
|||||||
|
|
||||||
Pub, // pub Expr
|
Pub, // pub Expr
|
||||||
Loop, // loop Expr
|
Loop, // loop Expr
|
||||||
|
Match, // match Expr { <Let(Match, ..)>,* }
|
||||||
If, // if Expr Expr (else Expr)?
|
If, // if Expr Expr (else Expr)?
|
||||||
While, // while Expr Expr (else Expr)?
|
While, // while Expr Expr (else Expr)?
|
||||||
Break, // break Expr
|
Break, // break Expr
|
||||||
@@ -339,13 +327,6 @@ 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> {
|
impl<A: Annotation> Display for Fn<A> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@@ -357,21 +338,29 @@ impl<A: Annotation> Display for Fn<A> {
|
|||||||
|
|
||||||
impl<A: Annotation> Display for Let<A> {
|
impl<A: Annotation> Display for Let<A> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let Self(pat, exprs) = self;
|
let Self(op, pat, exprs) = self;
|
||||||
|
|
||||||
|
if let LetKind::Match = op {
|
||||||
|
return f.delimit(fmt!("{pat} => "), "").list(exprs, ",!? ");
|
||||||
|
}
|
||||||
|
|
||||||
match exprs.as_slice() {
|
match exprs.as_slice() {
|
||||||
[] => write!(f, "let {pat}"),
|
[] => write!(f, "{op} {pat}"),
|
||||||
[value] => write!(f, "let {pat} = {value}"),
|
[value] => write!(f, "{op} {pat} = {value}"),
|
||||||
[value, fail] => write!(f, "let {pat} = {value} else {fail}"),
|
[value, fail] => write!(f, "{op} {pat} = {value} else {fail}"),
|
||||||
other => f.delimit(fmt!("let! {pat} ("), ")").list(other, ", "),
|
other => f.delimit(fmt!("{op}?! {pat} ("), ")").list(other, ", "),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Annotation> Display for Match<A> {
|
impl Display for LetKind {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let Self(expr, match_arms) = self;
|
f.write_str(match self {
|
||||||
f.delimit_indented(fmt!("match {expr} {{"), "}")
|
Self::Let => "let",
|
||||||
.list_wrap("\n", match_arms, ",\n", ",\n")
|
Self::Const => "const",
|
||||||
|
Self::Static => "static",
|
||||||
|
Self::Match => "| ",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,10 +405,8 @@ impl<A: Annotation> Display for Expr<A> {
|
|||||||
Self::MetId(id) => write!(f, "`{id}"),
|
Self::MetId(id) => write!(f, "`{id}"),
|
||||||
Self::Lit(literal) => literal.fmt(f),
|
Self::Lit(literal) => literal.fmt(f),
|
||||||
Self::Let(v) => v.fmt(f),
|
Self::Let(v) => v.fmt(f),
|
||||||
Self::Const(v) => v.fmt(f),
|
|
||||||
Self::Struct(v) => v.fmt(f),
|
Self::Struct(v) => v.fmt(f),
|
||||||
Self::Make(v) => v.fmt(f),
|
Self::Make(v) => v.fmt(f),
|
||||||
Self::Match(v) => v.fmt(f),
|
|
||||||
Self::Mod(v) => v.fmt(f),
|
Self::Mod(v) => v.fmt(f),
|
||||||
Self::Fn(v) => v.fmt(f),
|
Self::Fn(v) => v.fmt(f),
|
||||||
|
|
||||||
@@ -430,6 +417,12 @@ impl<A: Annotation> Display for Expr<A> {
|
|||||||
[cond, pass, fail] => write!(f, "{op}{cond} {pass} else {fail}"),
|
[cond, pass, fail] => write!(f, "{op}{cond} {pass} else {fail}"),
|
||||||
other => f.delimit(fmt!("({op}, "), ")").list(other, ", "),
|
other => f.delimit(fmt!("({op}, "), ")").list(other, ", "),
|
||||||
},
|
},
|
||||||
|
Self::Op(op @ Op::Match, exprs) => match exprs.as_slice() {
|
||||||
|
[scrutinee, arms @ ..] => f
|
||||||
|
.delimit_indented(fmt!("{op}{scrutinee} {{"), "}")
|
||||||
|
.list_wrap("\n", arms, ",\n", ",\n"),
|
||||||
|
[] => write!(f, "{op} () {{}}"), // invalid, but whatever.
|
||||||
|
},
|
||||||
Self::Op(Op::Array, exprs) => f.delimit("[", "]").list(exprs, ", "),
|
Self::Op(Op::Array, exprs) => f.delimit("[", "]").list(exprs, ", "),
|
||||||
Self::Op(Op::ArRep, exprs) => f.delimit("[", "]").list(exprs, "; "),
|
Self::Op(Op::ArRep, exprs) => f.delimit("[", "]").list(exprs, "; "),
|
||||||
Self::Op(Op::Block, exprs) => f
|
Self::Op(Op::Block, exprs) => f
|
||||||
@@ -479,6 +472,7 @@ impl Display for Op {
|
|||||||
Op::Call => "",
|
Op::Call => "",
|
||||||
Op::Pub => "pub ",
|
Op::Pub => "pub ",
|
||||||
Op::Loop => "loop ",
|
Op::Loop => "loop ",
|
||||||
|
Op::Match => "match ",
|
||||||
Op::If => "if ",
|
Op::If => "if ",
|
||||||
Op::While => "while ",
|
Op::While => "while ",
|
||||||
Op::Break => "break ",
|
Op::Break => "break ",
|
||||||
@@ -534,13 +528,6 @@ 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(pat, expr) = self;
|
|
||||||
write!(f, "{pat} => {expr}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Pat {
|
impl Display for Pat {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@@ -550,7 +537,9 @@ impl Display for Pat {
|
|||||||
Self::Name(name) => name.fmt(f),
|
Self::Name(name) => name.fmt(f),
|
||||||
Self::Path(path) => path.fmt(f),
|
Self::Path(path) => path.fmt(f),
|
||||||
Self::Struct(name, bind) => match bind.as_ref() {
|
Self::Struct(name, bind) => match bind.as_ref() {
|
||||||
Pat::Op(PatOp::Tuple, parts) => f.delimit(fmt!("{name} {{ "), " }").list(parts, ", "),
|
Pat::Op(PatOp::Tuple, parts) => {
|
||||||
|
f.delimit(fmt!("{name} {{ "), " }").list(parts, ", ")
|
||||||
|
}
|
||||||
other => write!(f, "{name} {{ {other} }}"),
|
other => write!(f, "{name} {{ {other} }}"),
|
||||||
},
|
},
|
||||||
Self::TupStruct(name, bind) => write!(f, "{name} {bind}"),
|
Self::TupStruct(name, bind) => write!(f, "{name} {bind}"),
|
||||||
|
|||||||
@@ -78,19 +78,6 @@ impl<M: Match<A> + Annotation, A: Annotation> Match<A> for Anno<M, A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Annotation> Match<A> for Const<A> {
|
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
|
||||||
let (Self(pat_pat, pat_expr), Self(expr_pat, expr_expr)) = (pat, expr);
|
|
||||||
Match::recurse(sub, pat_pat, expr_pat) && Match::recurse(sub, pat_expr, expr_expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply(&mut self, sub: &Subst<A>) {
|
|
||||||
let Self(pat, expr) = self;
|
|
||||||
pat.apply(sub);
|
|
||||||
expr.apply(sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A: Annotation> Match<A> for Fn<A> {
|
impl<A: Annotation> Match<A> for Fn<A> {
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
let (
|
let (
|
||||||
@@ -111,25 +98,14 @@ impl<A: Annotation> Match<A> for Fn<A> {
|
|||||||
|
|
||||||
impl<A: Annotation> Match<A> for Let<A> {
|
impl<A: Annotation> Match<A> for Let<A> {
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
let (Self(pat_pat, pat_expr), Self(expr_pat, expr_expr)) = (pat, expr);
|
let (Self(pat_kind, pat_pat, pat_expr), Self(expr_kind, expr_pat, expr_expr)) = (pat, expr);
|
||||||
Match::recurse(sub, pat_pat, expr_pat) && Match::recurse(sub, pat_expr, expr_expr)
|
pat_kind == expr_kind
|
||||||
|
&& Match::recurse(sub, pat_pat, expr_pat)
|
||||||
|
&& Match::recurse(sub, pat_expr, expr_expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(&mut self, sub: &Subst<A>) {
|
fn apply(&mut self, sub: &Subst<A>) {
|
||||||
let Self(pat, expr) = self;
|
let Self(_, pat, expr) = self;
|
||||||
pat.apply(sub);
|
|
||||||
expr.apply(sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A: Annotation> Match<A> for crate::ast::Match<A> {
|
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
|
||||||
let (Self(pat_expr, pat_arms), Self(expr_expr, expr_arms)) = (pat, expr);
|
|
||||||
Match::recurse(sub, pat_expr, expr_expr) && Match::recurse(sub, pat_arms, expr_arms)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply(&mut self, sub: &Subst<A>) {
|
|
||||||
let Self(pat, expr) = self;
|
|
||||||
pat.apply(sub);
|
pat.apply(sub);
|
||||||
expr.apply(sub);
|
expr.apply(sub);
|
||||||
}
|
}
|
||||||
@@ -185,14 +161,10 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
|||||||
(Expr::Lit(_), _) => false,
|
(Expr::Lit(_), _) => false,
|
||||||
(Expr::Let(pat), Expr::Let(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Let(pat), Expr::Let(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Let(..), _) => false,
|
(Expr::Let(..), _) => false,
|
||||||
(Expr::Const(pat), Expr::Const(expr)) => Match::recurse(sub, pat, expr),
|
|
||||||
(Expr::Const(..), _) => false,
|
|
||||||
(Expr::Struct(pat), Expr::Struct(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Struct(pat), Expr::Struct(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Struct(_), _) => false,
|
(Expr::Struct(_), _) => false,
|
||||||
(Expr::Make(pat), Expr::Make(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Make(pat), Expr::Make(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Make(..), _) => false,
|
(Expr::Make(..), _) => false,
|
||||||
(Expr::Match(pat), Expr::Match(expr)) => Match::recurse(sub, pat, expr),
|
|
||||||
(Expr::Match(..), _) => false,
|
|
||||||
(Expr::Mod(pat), Expr::Mod(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Mod(pat), Expr::Mod(expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Expr::Mod(..), _) => false,
|
(Expr::Mod(..), _) => false,
|
||||||
(Expr::Fn(pat), Expr::Fn(expr)) => Match::recurse(sub, pat, expr),
|
(Expr::Fn(pat), Expr::Fn(expr)) => Match::recurse(sub, pat, expr),
|
||||||
@@ -213,10 +185,8 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
|||||||
}
|
}
|
||||||
Expr::Id(_) | Expr::Lit(_) => {}
|
Expr::Id(_) | Expr::Lit(_) => {}
|
||||||
Expr::Let(expr) => expr.apply(sub),
|
Expr::Let(expr) => expr.apply(sub),
|
||||||
Expr::Const(expr) => expr.apply(sub),
|
|
||||||
Expr::Struct(expr) => expr.apply(sub),
|
Expr::Struct(expr) => expr.apply(sub),
|
||||||
Expr::Make(expr) => expr.apply(sub),
|
Expr::Make(expr) => expr.apply(sub),
|
||||||
Expr::Match(expr) => expr.apply(sub),
|
|
||||||
Expr::Mod(expr) => expr.apply(sub),
|
Expr::Mod(expr) => expr.apply(sub),
|
||||||
Expr::Fn(expr) => expr.apply(sub),
|
Expr::Fn(expr) => expr.apply(sub),
|
||||||
Expr::Op(op, exprs) => {
|
Expr::Op(op, exprs) => {
|
||||||
@@ -239,18 +209,6 @@ impl<A: Annotation> Match<A> for MakeArm<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Annotation> Match<A> for MatchArm<A> {
|
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
|
||||||
Match::recurse(sub, &pat.0, &expr.0) && Match::recurse(sub, &pat.1, &expr.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply(&mut self, sub: &Subst<A>) {
|
|
||||||
let Self(pats, expr) = self;
|
|
||||||
pats.apply(sub);
|
|
||||||
expr.apply(sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A: Annotation> Match<A> for Pat {
|
impl<A: Annotation> Match<A> for Pat {
|
||||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
match (pat, expr) {
|
match (pat, expr) {
|
||||||
|
|||||||
158
src/parser.rs
158
src/parser.rs
@@ -5,7 +5,7 @@ use crate::{
|
|||||||
span::Span,
|
span::Span,
|
||||||
token::{Lexeme, TKind, Token},
|
token::{Lexeme, TKind, Token},
|
||||||
};
|
};
|
||||||
use std::{error::Error, fmt::Display, vec};
|
use std::{error::Error, fmt::Display, iter, vec};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
@@ -546,8 +546,9 @@ pub enum Ps {
|
|||||||
Id, // Identifier
|
Id, // Identifier
|
||||||
Mid, // MetaIdentifier
|
Mid, // MetaIdentifier
|
||||||
Lit, // Literal
|
Lit, // Literal
|
||||||
Let, // let Pat = Expr
|
Let, // let Pat = Expr (else Expr)?
|
||||||
Const, // const Pat = Expr
|
Const, // const Pat = Expr
|
||||||
|
Static, // static Pat = Expr
|
||||||
Typedef, // struct { Pat } | struct ( Pat )
|
Typedef, // struct { Pat } | struct ( Pat )
|
||||||
For, // for Pat in Expr Expr else Expr
|
For, // for Pat in Expr Expr else Expr
|
||||||
Fn, // fn ( Pat,* ) Expr
|
Fn, // fn ( Pat,* ) Expr
|
||||||
@@ -555,7 +556,6 @@ pub enum Ps {
|
|||||||
Lambda, // | Pat,* | Expr
|
Lambda, // | Pat,* | Expr
|
||||||
DoubleRef, // && Expr
|
DoubleRef, // && Expr
|
||||||
Make, // Expr{ Expr,* }
|
Make, // Expr{ Expr,* }
|
||||||
Match, // match Expr { MatchArm,* }
|
|
||||||
Mod, // mod Ty Expr
|
Mod, // mod Ty Expr
|
||||||
ImplicitDo, // An implicit semicolon
|
ImplicitDo, // An implicit semicolon
|
||||||
ExplicitDo, // An explicit leading semicolon
|
ExplicitDo, // An explicit leading semicolon
|
||||||
@@ -577,7 +577,7 @@ fn from_prefix(token: &Token) -> PResult<(Ps, Prec)> {
|
|||||||
TKind::Public => (Ps::Op(Op::Pub), Prec::Body),
|
TKind::Public => (Ps::Op(Op::Pub), Prec::Body),
|
||||||
TKind::For => (Ps::For, Prec::Body),
|
TKind::For => (Ps::For, Prec::Body),
|
||||||
TKind::Fn => (Ps::Fn, Prec::Body),
|
TKind::Fn => (Ps::Fn, Prec::Body),
|
||||||
TKind::Match => (Ps::Match, Prec::Body),
|
TKind::Match => (Ps::Op(Op::Match), Prec::Body),
|
||||||
TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
|
TKind::Macro => (Ps::Op(Op::Macro), Prec::Assign),
|
||||||
TKind::Module => (Ps::Mod, Prec::Body),
|
TKind::Module => (Ps::Mod, Prec::Body),
|
||||||
TKind::Let => (Ps::Let, Prec::Tuple),
|
TKind::Let => (Ps::Let, Prec::Tuple),
|
||||||
@@ -663,17 +663,6 @@ fn from_infix(token: &Token) -> PResult<(Ps, Prec)> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Const {
|
|
||||||
type Prec = ();
|
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
|
||||||
Ok(Self(
|
|
||||||
p.consume().parse(PPrec::Tuple)?,
|
|
||||||
p.expect(TKind::Eq)?.parse(Prec::Tuple.value())?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Typedef {
|
impl<'t> Parse<'t> for Typedef {
|
||||||
type Prec = ();
|
type Prec = ();
|
||||||
|
|
||||||
@@ -717,46 +706,36 @@ impl<'t> Parse<'t> for Fn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Let {
|
impl<'t> Parse<'t> for Let {
|
||||||
type Prec = ();
|
type Prec = LetKind;
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self> {
|
||||||
let pat = p.consume().parse(PPrec::Tuple)?;
|
if let LetKind::Match = level {
|
||||||
if p.next_if(TKind::Eq).allow_eof()?.is_none_or(|v| v.is_err()) {
|
// |? Pat => Expr
|
||||||
return Ok(Self(pat, vec![]));
|
p.next_if(TKind::Bar)?.ok(); // and discard
|
||||||
|
return Ok(Self(
|
||||||
|
level,
|
||||||
|
p.parse(PPrec::Min)?,
|
||||||
|
vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let Pat
|
||||||
|
let pat = p.consume().parse(PPrec::Tuple)?;
|
||||||
|
if p.next_if(TKind::Eq).allow_eof()?.is_none_or(|v| v.is_err()) {
|
||||||
|
return Ok(Self(level, pat, vec![]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// = Expr
|
||||||
let body = p.parse(Prec::Tuple.value())?;
|
let body = p.parse(Prec::Tuple.value())?;
|
||||||
if p.next_if(TKind::Else)
|
if p.next_if(TKind::Else)
|
||||||
.allow_eof()?
|
.allow_eof()?
|
||||||
.is_none_or(|v| v.is_err())
|
.is_none_or(|v| v.is_err())
|
||||||
{
|
{
|
||||||
return Ok(Self(pat, vec![body]));
|
return Ok(Self(level, pat, vec![body]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self(pat, vec![body, p.parse(Prec::Body.next())?]))
|
// else Expr
|
||||||
}
|
Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?]))
|
||||||
}
|
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Match {
|
|
||||||
type Prec = ();
|
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
|
||||||
Ok(Self(p.consume().parse(Prec::Logical.value())?, {
|
|
||||||
p.expect(TKind::LCurly)?;
|
|
||||||
p.list(vec![], Prec::Body.next(), TKind::Comma, TKind::RCurly)?
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'t> Parse<'t> for MatchArm {
|
|
||||||
type Prec = usize;
|
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, level: usize) -> PResult<Self> {
|
|
||||||
p.next_if(TKind::Bar)?.ok(); // and discard
|
|
||||||
Ok(MatchArm(
|
|
||||||
p.parse(PPrec::Min)?,
|
|
||||||
p.expect(TKind::FatArrow)?.parse(level)?,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,33 +788,10 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// let mut tmp_p = Parser::new(Lexer::new(
|
|
||||||
// "match `iter.into_iter() {
|
|
||||||
// `iterator => loop match `iterator.next() {
|
|
||||||
// None => break `fail,
|
|
||||||
// Some(`pat) => `pass,
|
|
||||||
// },
|
|
||||||
// }",
|
|
||||||
// ));
|
|
||||||
|
|
||||||
// let mut template: Expr = tmp_p.parse(Prec::MIN)?;
|
Ok(Expr::Op(
|
||||||
|
Op::Match,
|
||||||
// let mut subst = Subst::<Span> { exp: Default::default(), pat: Default::default() };
|
vec![
|
||||||
// subst.exp.extend([
|
|
||||||
// ("iterator".into(), Expr::Id("#iter".into())),
|
|
||||||
// ("iter".into(), iter.0),
|
|
||||||
// ("fail".into(), fail.0),
|
|
||||||
// ("pass".into(), pass.0),
|
|
||||||
// ]);
|
|
||||||
// subst.pat.extend([
|
|
||||||
// ("iterator".into(), Pat::Name("#iter".into())),
|
|
||||||
// ("pat".into(), pat),
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// template.apply(&subst);
|
|
||||||
// Ok(template)
|
|
||||||
|
|
||||||
Ok(Expr::Match(Box::new(Match(
|
|
||||||
Expr::Op(
|
Expr::Op(
|
||||||
Op::Dot,
|
Op::Dot,
|
||||||
vec![
|
vec![
|
||||||
@@ -844,41 +800,54 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
.anno(cspan),
|
.anno(cspan),
|
||||||
vec![MatchArm(
|
Expr::Let(Box::new(Let(
|
||||||
|
LetKind::Match,
|
||||||
Pat::Name("#iter".into()),
|
Pat::Name("#iter".into()),
|
||||||
|
vec![
|
||||||
Expr::Op(
|
Expr::Op(
|
||||||
Op::Loop,
|
Op::Loop,
|
||||||
vec![
|
vec![
|
||||||
Expr::Match(Box::new(Match(
|
Expr::Op(
|
||||||
|
Op::Match,
|
||||||
|
vec![
|
||||||
Expr::Op(
|
Expr::Op(
|
||||||
Op::Dot,
|
Op::Dot,
|
||||||
vec![
|
vec![
|
||||||
Expr::Id("#iter".into()).anno(cspan),
|
Expr::Id("#iter".into()).anno(cspan),
|
||||||
Expr::Op(Op::Call, vec![Expr::Id("next".into()).anno(cspan)])
|
Expr::Op(
|
||||||
|
Op::Call,
|
||||||
|
vec![Expr::Id("next".into()).anno(cspan)],
|
||||||
|
)
|
||||||
.anno(cspan),
|
.anno(cspan),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.anno(cspan),
|
.anno(cspan),
|
||||||
vec![
|
Expr::Let(Box::new(Let(
|
||||||
MatchArm(
|
LetKind::Match,
|
||||||
Pat::Name("None".into()),
|
Pat::Name("None".into()),
|
||||||
Expr::Op(Op::Break, vec![fail]).anno(fspan),
|
vec![Expr::Op(Op::Break, vec![fail]).anno(fspan)],
|
||||||
),
|
)))
|
||||||
MatchArm(
|
.anno(fspan),
|
||||||
|
Expr::Let(Box::new(Let(
|
||||||
|
LetKind::Match,
|
||||||
Pat::TupStruct(
|
Pat::TupStruct(
|
||||||
"Some".into(),
|
"Some".into(),
|
||||||
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
|
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
|
||||||
),
|
),
|
||||||
pass,
|
vec![pass],
|
||||||
),
|
|
||||||
],
|
|
||||||
)))
|
)))
|
||||||
.anno(pspan),
|
.anno(pspan),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.anno(pspan),
|
.anno(pspan),
|
||||||
)],
|
],
|
||||||
))))
|
)
|
||||||
|
.anno(pspan),
|
||||||
|
],
|
||||||
|
)))
|
||||||
|
.anno(pspan),
|
||||||
|
],
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Expr {
|
impl<'t> Parse<'t> for Expr {
|
||||||
@@ -907,12 +876,13 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
Ps::Id => Expr::Id(p.parse(())?),
|
Ps::Id => Expr::Id(p.parse(())?),
|
||||||
Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string()),
|
Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string()),
|
||||||
Ps::Lit => Expr::Lit(p.parse(())?),
|
Ps::Lit => Expr::Lit(p.parse(())?),
|
||||||
Ps::Let => Expr::Let(p.parse(())?),
|
Ps::Let => Expr::Let(p.parse(LetKind::Let)?),
|
||||||
|
Ps::Const => Expr::Let(p.parse(LetKind::Const)?),
|
||||||
|
Ps::Static => Expr::Let(p.parse(LetKind::Static)?),
|
||||||
Ps::For => parse_for(p, ())?,
|
Ps::For => parse_for(p, ())?,
|
||||||
Ps::Const => Expr::Const(p.parse(())?),
|
|
||||||
Ps::Typedef => Expr::Struct(p.parse(())?),
|
Ps::Typedef => Expr::Struct(p.parse(())?),
|
||||||
Ps::Match => Expr::Match(p.parse(())?),
|
|
||||||
Ps::Mod => Expr::Mod(p.parse(())?),
|
Ps::Mod => Expr::Mod(p.parse(())?),
|
||||||
|
Ps::Op(Op::Match) => parse_match(p)?,
|
||||||
Ps::Op(Op::Meta) => Expr::Op(
|
Ps::Op(Op::Meta) => Expr::Op(
|
||||||
Op::Meta,
|
Op::Meta,
|
||||||
vec![
|
vec![
|
||||||
@@ -1049,6 +1019,20 @@ fn parse_array<'t>(p: &mut Parser<'t>) -> PResult<Expr> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_match<'t>(p: &mut Parser<'t>) -> PResult<Expr> {
|
||||||
|
let scrutinee = p.consume().parse(Prec::Logical.value())?;
|
||||||
|
|
||||||
|
let arms = p
|
||||||
|
.expect(TKind::LCurly)?
|
||||||
|
.list(vec![], LetKind::Match, TKind::Comma, TKind::RCurly)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|Anno(arm, span)| Anno(Expr::Let(Box::new(arm)), span));
|
||||||
|
|
||||||
|
let expr = Expr::Op(Op::Match, iter::once(scrutinee).chain(arms).collect());
|
||||||
|
|
||||||
|
Ok(expr)
|
||||||
|
}
|
||||||
|
|
||||||
impl<'t, P: Parse<'t> + Annotation> Parse<'t> for Anno<P> {
|
impl<'t, P: Parse<'t> + Annotation> Parse<'t> for Anno<P> {
|
||||||
type Prec = P::Prec;
|
type Prec = P::Prec;
|
||||||
fn parse(p: &mut Parser<'t>, level: P::Prec) -> PResult<Self>
|
fn parse(p: &mut Parser<'t>, level: P::Prec) -> PResult<Self>
|
||||||
|
|||||||
Reference in New Issue
Block a user