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) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										208
									
								
								src/parser.rs
									
									
									
									
									
								
							
							
						
						
									
										208
									
								
								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,76 +788,66 @@ 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(
 | 
					 | 
				
			||||||
            Op::Dot,
 | 
					 | 
				
			||||||
            vec![
 | 
					 | 
				
			||||||
                iter,
 | 
					 | 
				
			||||||
                Expr::Op(Op::Call, vec![Expr::Id("into_iter".into()).anno(cspan)]).anno(cspan),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .anno(cspan),
 | 
					 | 
				
			||||||
        vec![MatchArm(
 | 
					 | 
				
			||||||
            Pat::Name("#iter".into()),
 | 
					 | 
				
			||||||
            Expr::Op(
 | 
					            Expr::Op(
 | 
				
			||||||
                Op::Loop,
 | 
					                Op::Dot,
 | 
				
			||||||
                vec![
 | 
					                vec![
 | 
				
			||||||
                    Expr::Match(Box::new(Match(
 | 
					                    iter,
 | 
				
			||||||
                        Expr::Op(
 | 
					                    Expr::Op(Op::Call, vec![Expr::Id("into_iter".into()).anno(cspan)]).anno(cspan),
 | 
				
			||||||
                            Op::Dot,
 | 
					 | 
				
			||||||
                            vec![
 | 
					 | 
				
			||||||
                                Expr::Id("#iter".into()).anno(cspan),
 | 
					 | 
				
			||||||
                                Expr::Op(Op::Call, vec![Expr::Id("next".into()).anno(cspan)])
 | 
					 | 
				
			||||||
                                    .anno(cspan),
 | 
					 | 
				
			||||||
                            ],
 | 
					 | 
				
			||||||
                        )
 | 
					 | 
				
			||||||
                        .anno(cspan),
 | 
					 | 
				
			||||||
                        vec![
 | 
					 | 
				
			||||||
                            MatchArm(
 | 
					 | 
				
			||||||
                                Pat::Name("None".into()),
 | 
					 | 
				
			||||||
                                Expr::Op(Op::Break, vec![fail]).anno(fspan),
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                            MatchArm(
 | 
					 | 
				
			||||||
                                Pat::TupStruct(
 | 
					 | 
				
			||||||
                                    "Some".into(),
 | 
					 | 
				
			||||||
                                    Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                                pass,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                        ],
 | 
					 | 
				
			||||||
                    )))
 | 
					 | 
				
			||||||
                    .anno(pspan),
 | 
					 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					            .anno(cspan),
 | 
				
			||||||
 | 
					            Expr::Let(Box::new(Let(
 | 
				
			||||||
 | 
					                LetKind::Match,
 | 
				
			||||||
 | 
					                Pat::Name("#iter".into()),
 | 
				
			||||||
 | 
					                vec![
 | 
				
			||||||
 | 
					                    Expr::Op(
 | 
				
			||||||
 | 
					                        Op::Loop,
 | 
				
			||||||
 | 
					                        vec![
 | 
				
			||||||
 | 
					                            Expr::Op(
 | 
				
			||||||
 | 
					                                Op::Match,
 | 
				
			||||||
 | 
					                                vec![
 | 
				
			||||||
 | 
					                                    Expr::Op(
 | 
				
			||||||
 | 
					                                        Op::Dot,
 | 
				
			||||||
 | 
					                                        vec![
 | 
				
			||||||
 | 
					                                            Expr::Id("#iter".into()).anno(cspan),
 | 
				
			||||||
 | 
					                                            Expr::Op(
 | 
				
			||||||
 | 
					                                                Op::Call,
 | 
				
			||||||
 | 
					                                                vec![Expr::Id("next".into()).anno(cspan)],
 | 
				
			||||||
 | 
					                                            )
 | 
				
			||||||
 | 
					                                            .anno(cspan),
 | 
				
			||||||
 | 
					                                        ],
 | 
				
			||||||
 | 
					                                    )
 | 
				
			||||||
 | 
					                                    .anno(cspan),
 | 
				
			||||||
 | 
					                                    Expr::Let(Box::new(Let(
 | 
				
			||||||
 | 
					                                        LetKind::Match,
 | 
				
			||||||
 | 
					                                        Pat::Name("None".into()),
 | 
				
			||||||
 | 
					                                        vec![Expr::Op(Op::Break, vec![fail]).anno(fspan)],
 | 
				
			||||||
 | 
					                                    )))
 | 
				
			||||||
 | 
					                                    .anno(fspan),
 | 
				
			||||||
 | 
					                                    Expr::Let(Box::new(Let(
 | 
				
			||||||
 | 
					                                        LetKind::Match,
 | 
				
			||||||
 | 
					                                        Pat::TupStruct(
 | 
				
			||||||
 | 
					                                            "Some".into(),
 | 
				
			||||||
 | 
					                                            Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
 | 
				
			||||||
 | 
					                                        ),
 | 
				
			||||||
 | 
					                                        vec![pass],
 | 
				
			||||||
 | 
					                                    )))
 | 
				
			||||||
 | 
					                                    .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