diff --git a/src/ast.rs b/src/ast.rs index 35e57eb..4b57644 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -111,14 +111,19 @@ pub enum Ty { /// let Pat (= Expr)? /// `````` #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Let(pub Pat, pub Vec, A>>); +pub struct Let(pub LetKind, pub Pat, pub Vec, A>>); -/// A `const` binding (which defines its name before executing) -/// ```ignore -/// const Pat = Expr -/// ``` #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Const(pub Pat, pub Anno, 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 /// ```ignore @@ -127,20 +132,6 @@ pub struct Const(pub Pat, pub Anno, A>); #[derive(Clone, Debug, PartialEq, Eq)] pub struct Fn(pub Option, pub Pat, pub Ty, pub Anno, A>); -/// A match expression -/// ```ignore -/// match Expr { MatchArm,* } -/// ``` -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Match(pub Anno, A>, pub Vec>); - -/// The "arms" of a match expression -/// ```ignore -/// Pat => Expr -/// ``` -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct MatchArm(pub Pat, pub Anno, A>); - /// A make (constructor) expression /// ```ignore /// Expr { (Ident (: Expr)?),* } @@ -185,16 +176,12 @@ pub enum Expr { Lit(Literal), /// let Pat = expr Let(Box>), - /// `const Pat (= Expr)?` (Basically let rec) - Const(Box>), /// (struct | enum | type) Pat Struct(Box), /// `| Pat | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr` Fn(Box>), /// Expr { (Ident (: Expr)?),* } Make(Box>), - /// match Expr { MatchArm,* } - Match(Box>), /// mod Ty Expr Mod(Box>), /// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr @@ -259,6 +246,7 @@ pub enum Op { Pub, // pub Expr Loop, // loop Expr + Match, // match Expr { ,* } If, // if Expr Expr (else Expr)? While, // while Expr Expr (else Expr)? Break, // break Expr @@ -339,13 +327,6 @@ impl Display for Anno { } } -impl Display for Const { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self(pat, expr) = self; - write!(f, "const {pat} = {expr}") - } -} - impl Display for Fn { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -357,21 +338,29 @@ impl Display for Fn { impl Display for Let { 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() { - [] => write!(f, "let {pat}"), - [value] => write!(f, "let {pat} = {value}"), - [value, fail] => write!(f, "let {pat} = {value} else {fail}"), - other => f.delimit(fmt!("let! {pat} ("), ")").list(other, ", "), + [] => 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, ", "), } } } -impl Display for Match { +impl Display for LetKind { 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") + f.write_str(match self { + Self::Let => "let", + Self::Const => "const", + Self::Static => "static", + Self::Match => "| ", + }) } } @@ -416,10 +405,8 @@ impl Display for Expr { Self::MetId(id) => write!(f, "`{id}"), Self::Lit(literal) => literal.fmt(f), Self::Let(v) => v.fmt(f), - Self::Const(v) => v.fmt(f), Self::Struct(v) => v.fmt(f), Self::Make(v) => v.fmt(f), - Self::Match(v) => v.fmt(f), Self::Mod(v) => v.fmt(f), Self::Fn(v) => v.fmt(f), @@ -430,6 +417,12 @@ impl Display for Expr { [cond, pass, fail] => write!(f, "{op}{cond} {pass} else {fail}"), 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::ArRep, exprs) => f.delimit("[", "]").list(exprs, "; "), Self::Op(Op::Block, exprs) => f @@ -479,6 +472,7 @@ impl Display for Op { Op::Call => "", Op::Pub => "pub ", Op::Loop => "loop ", + Op::Match => "match ", Op::If => "if ", Op::While => "while ", Op::Break => "break ", @@ -534,13 +528,6 @@ impl Display for MakeArm { } } -impl Display for MatchArm { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self(pat, expr) = self; - write!(f, "{pat} => {expr}") - } -} - impl Display for Pat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -550,7 +537,9 @@ impl Display for Pat { Self::Name(name) => name.fmt(f), Self::Path(path) => path.fmt(f), 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} }}"), }, Self::TupStruct(name, bind) => write!(f, "{name} {bind}"), diff --git a/src/ast/macro_matcher.rs b/src/ast/macro_matcher.rs index cb728a1..0d4a3d7 100644 --- a/src/ast/macro_matcher.rs +++ b/src/ast/macro_matcher.rs @@ -78,19 +78,6 @@ impl + Annotation, A: Annotation> Match for Anno { } } -impl Match for Const { - fn recurse(sub: &mut Subst, 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) { - let Self(pat, expr) = self; - pat.apply(sub); - expr.apply(sub); - } -} - impl Match for Fn { fn recurse(sub: &mut Subst, pat: &Self, expr: &Self) -> bool { let ( @@ -111,25 +98,14 @@ impl Match for Fn { impl Match for Let { fn recurse(sub: &mut Subst, 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) + let (Self(pat_kind, pat_pat, pat_expr), Self(expr_kind, expr_pat, expr_expr)) = (pat, 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) { - let Self(pat, expr) = self; - pat.apply(sub); - expr.apply(sub); - } -} - -impl Match for crate::ast::Match { - fn recurse(sub: &mut Subst, 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) { - let Self(pat, expr) = self; + let Self(_, pat, expr) = self; pat.apply(sub); expr.apply(sub); } @@ -185,14 +161,10 @@ impl Match for Expr { (Expr::Lit(_), _) => false, (Expr::Let(pat), Expr::Let(expr)) => Match::recurse(sub, pat, expr), (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(_), _) => false, (Expr::Make(pat), Expr::Make(expr)) => Match::recurse(sub, pat, expr), (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(..), _) => false, (Expr::Fn(pat), Expr::Fn(expr)) => Match::recurse(sub, pat, expr), @@ -213,10 +185,8 @@ impl Match for Expr { } Expr::Id(_) | Expr::Lit(_) => {} Expr::Let(expr) => expr.apply(sub), - Expr::Const(expr) => expr.apply(sub), Expr::Struct(expr) => expr.apply(sub), Expr::Make(expr) => expr.apply(sub), - Expr::Match(expr) => expr.apply(sub), Expr::Mod(expr) => expr.apply(sub), Expr::Fn(expr) => expr.apply(sub), Expr::Op(op, exprs) => { @@ -239,18 +209,6 @@ impl Match for MakeArm { } } -impl Match for MatchArm { - fn recurse(sub: &mut Subst, 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) { - let Self(pats, expr) = self; - pats.apply(sub); - expr.apply(sub); - } -} - impl Match for Pat { fn recurse(sub: &mut Subst, pat: &Self, expr: &Self) -> bool { match (pat, expr) { diff --git a/src/parser.rs b/src/parser.rs index 62f17a6..dfcf0d2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -5,7 +5,7 @@ use crate::{ span::Span, 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)] pub enum ParseError { @@ -546,8 +546,9 @@ pub enum Ps { Id, // Identifier Mid, // MetaIdentifier Lit, // Literal - Let, // let Pat = Expr + Let, // let Pat = Expr (else Expr)? Const, // const Pat = Expr + Static, // static Pat = Expr Typedef, // struct { Pat } | struct ( Pat ) For, // for Pat in Expr Expr else Expr Fn, // fn ( Pat,* ) Expr @@ -555,7 +556,6 @@ pub enum Ps { Lambda, // | Pat,* | Expr DoubleRef, // && Expr Make, // Expr{ Expr,* } - Match, // match Expr { MatchArm,* } Mod, // mod Ty Expr ImplicitDo, // An implicit 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::For => (Ps::For, 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::Module => (Ps::Mod, Prec::Body), 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 { - Ok(Self( - p.consume().parse(PPrec::Tuple)?, - p.expect(TKind::Eq)?.parse(Prec::Tuple.value())?, - )) - } -} - impl<'t> Parse<'t> for Typedef { type Prec = (); @@ -717,46 +706,36 @@ impl<'t> Parse<'t> for Fn { } impl<'t> Parse<'t> for Let { - type Prec = (); + type Prec = LetKind; - fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult { - 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(pat, vec![])); + fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult { + if let LetKind::Match = level { + // |? Pat => Expr + 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())?; if p.next_if(TKind::Else) .allow_eof()? .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())?])) - } -} - -impl<'t> Parse<'t> for Match { - type Prec = (); - - fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult { - 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 { - p.next_if(TKind::Bar)?.ok(); // and discard - Ok(MatchArm( - p.parse(PPrec::Min)?, - p.expect(TKind::FatArrow)?.parse(level)?, - )) + // else Expr + Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?])) } } @@ -809,76 +788,66 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult { }, } */ - // 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)?; - - // let mut subst = Subst:: { exp: Default::default(), pat: Default::default() }; - // 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()), + Ok(Expr::Op( + Op::Match, + vec![ Expr::Op( - Op::Loop, + Op::Dot, vec![ - Expr::Match(Box::new(Match( - 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), - 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), + iter, + Expr::Op(Op::Call, vec![Expr::Id("into_iter".into()).anno(cspan)]).anno(cspan), ], ) + .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), - )], - )))) + ], + )) } impl<'t> Parse<'t> for Expr { @@ -907,12 +876,13 @@ impl<'t> Parse<'t> for Expr { Ps::Id => Expr::Id(p.parse(())?), Ps::Mid => Expr::MetId(p.consume().next()?.lexeme.to_string()), 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::Const => Expr::Const(p.parse(())?), Ps::Typedef => Expr::Struct(p.parse(())?), - Ps::Match => Expr::Match(p.parse(())?), Ps::Mod => Expr::Mod(p.parse(())?), + Ps::Op(Op::Match) => parse_match(p)?, Ps::Op(Op::Meta) => Expr::Op( Op::Meta, vec![ @@ -1049,6 +1019,20 @@ fn parse_array<'t>(p: &mut Parser<'t>) -> PResult { }) } +fn parse_match<'t>(p: &mut Parser<'t>) -> PResult { + 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

{ type Prec = P::Prec; fn parse(p: &mut Parser<'t>, level: P::Prec) -> PResult