diff --git a/src/ast.rs b/src/ast.rs index d2201c4..5d4d2b6 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -40,12 +40,14 @@ pub enum Literal { /// A character literal: 'a', '\u{1f988}' Char(char), /// An integer literal: 0, 123, 0x10 - Int(u128), + Int(u128, u32), /// A string literal: Str(String), } -/// Binding patterns for each kind of matchable [Ty] +/// Binding patterns for each kind of matchable value. +/// +/// This covers both patterns in Match expressions, and type annotations. #[derive(Clone, Debug, PartialEq, Eq)] pub enum Pat { /// Matches anything without binding @@ -57,13 +59,11 @@ pub enum Pat { /// Matches against a named const value Path(FqPath), /// Matches a Struct Expression `Ident { Pat }` - Struct(FqPath, Box), + NamedStruct(FqPath, Box), /// Matches a Tuple Struct Expression `Ident ( Pat )` - TupStruct(FqPath, Box), + NamedTuple(FqPath, Box), /// Matches a literal value by equality comparison Lit(Literal), - /// Matches a typed pattern - Typed(Box, Ty), /// Matches a compound pattern Op(PatOp, Vec), } @@ -83,34 +83,22 @@ pub enum PatOp { Tuple, /// Matches the elements of a slice or array Slice, + /// Matches a type annotation or struct member + Typed, + /// Matches a function signature + Fn, /// Matches one of a list of alternatives Alt, } -/// In-universe types -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Ty { - /// `_` - Infer, - /// `(Identifier :: )* Identifier` - Named(FqPath), - /// `&Ty` - Ref(Box), - /// `(..Tys)` - Tuple(Vec), - /// `[Ty]` - Slice(Box), - /// `[Ty; _]` - Array(Box, Box), - /// `[..Args, Rety]` - Fn(Vec), -} - /// A pattern binding /// ```ignore /// let Pat (= Expr (else Expr)?)? /// const Pat (= Expr (else Expr)?)? /// static Pat (= Expr (else Expr)?)? +/// fn Pat Expr +/// mod Pat Expr +/// impl Pat Expr /// Pat => Expr // in match /// `````` #[derive(Clone, Debug, PartialEq, Eq)] @@ -124,17 +112,16 @@ pub enum BindKind { Const, /// A `static Pat = Expr` binding Static, + /// A `fn Pat Expr` binding + Fn, + /// A `mod Pat Expr` binding + Mod, + /// An `impl Pat Expr` binding + Impl, /// A `Pat => Expr` binding Match, } -/// A function definition -/// ```ignore -/// fn Ident? (Pat) Expr -/// ``` -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Fn(pub Option, pub Pat, pub Ty, pub Anno, A>); - /// A make (constructor) expression /// ```ignore /// Expr { (Ident (: Expr)?),* } @@ -149,12 +136,9 @@ pub struct Make(pub Anno, A>, pub Vec>) #[derive(Clone, Debug, PartialEq, Eq)] pub struct MakeArm(pub String, pub Option, A>>); -/// An inline namespace -/// ```ignore -/// mod Ty Expr -/// ``` +/// A record-type definition #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Mod(pub Ty, pub Anno, A>); +pub struct Typedef(pub TypedefKind, pub Pat); /// The type of type being defined #[derive(Clone, Debug, PartialEq, Eq)] @@ -164,10 +148,6 @@ pub enum TypedefKind { Enum, } -/// A record-type definition -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Typedef(pub TypedefKind, pub Pat); - /// Expressions: The beating heart of Dough #[derive(Clone, Debug, PartialEq, Eq)] pub enum Expr { @@ -177,16 +157,13 @@ pub enum Expr { MetId(String), /// A literal bool, string, char, or int Lit(Literal), - /// (let | const | static) Pat (= expr (else expr)?)? + /// `(let | const | static) Pat (= expr (else expr)?)?` | + /// `(fn | mod | impl) Pat Expr` Bind(Box>), /// (struct | enum | type) Pat Struct(Box), - /// `| Pat | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr` - Fn(Box>), /// Expr { (Ident (: Expr)?),* } Make(Box>), - /// mod Ty Expr - Mod(Box>), /// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr Op(Op, Vec>), } @@ -311,7 +288,10 @@ impl Display for Literal { match self { Self::Bool(v) => v.fmt(f), Self::Char(c) => write!(f, "'{}'", c.escape_debug()), - Self::Int(i) => i.fmt(f), + Self::Int(i, 2) => write!(f, "0b{i:b}"), + Self::Int(i, 8) => write!(f, "0o{i:o}"), + Self::Int(i, 16) => write!(f, "0x{i:x}"), + Self::Int(i, _) => i.fmt(f), Self::Str(s) => write!(f, "\"{}\"", s.escape_debug()), } } @@ -330,28 +310,21 @@ impl Display for Anno { } } -impl Display for Fn { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self(Some(name), pat, rety, expr) => write!(f, "fn {name} {pat} -> {rety} {expr}"), - Self(None, pat, rety, expr) => write!(f, "|{pat}| -> {rety} {expr}"), - } - } -} - impl Display for Bind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self(op, pat, exprs) = self; - if let BindKind::Match = op { - return f.delimit(fmt!("{pat} => "), "").list(exprs, ",!? "); - } - - match exprs.as_slice() { - [] => write!(f, "{op} {pat}"), - [value] => write!(f, "{op} {pat} = {value}"), - [value, fail] => write!(f, "{op} {pat} = {value} else {fail}"), - other => f.delimit(fmt!("{op}?! {pat} ("), ")").list(other, ", "), + match op { + BindKind::Match => f.delimit(fmt!("{pat} => "), "").list(exprs, ",!? "), + BindKind::Fn | BindKind::Mod | BindKind::Impl => { + f.delimit(fmt!("{op}{pat} "), "").list(exprs, ",!? ") + } + _ => match exprs.as_slice() { + [] => write!(f, "{op}{pat}"), + [value] => write!(f, "{op}{pat} = {value}"), + [value, fail] => write!(f, "{op} {pat} = {value} else {fail}"), + other => f.delimit(fmt!("{op}{pat} ("), ")").list(other, ", "), + }, } } } @@ -359,9 +332,12 @@ impl Display for Bind { impl Display for BindKind { 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::Let => "let ", + Self::Const => "const ", + Self::Static => "static ", + Self::Fn => "fn ", + Self::Mod => "mod ", + Self::Impl => "impl ", Self::Match => "| ", }) } @@ -374,13 +350,6 @@ impl Display for Make { } } -impl Display for Mod { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self(ty, expr) = self; - write!(f, "mod {ty} {expr}") - } -} - impl Display for Typedef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self(kind, pat) = self; @@ -390,7 +359,7 @@ impl Display for Typedef { TypedefKind::Enum => "enum ", })?; match pat { - Pat::Struct(name, bind) => match bind.as_ref() { + Pat::NamedStruct(name, bind) => match bind.as_ref() { Pat::Op(PatOp::Tuple, parts) => f .delimit_indented(fmt!("{name} {{"), "}") .list_wrap("\n", parts, ",\n", ",\n"), @@ -410,8 +379,6 @@ impl Display for Expr { Self::Bind(v) => v.fmt(f), Self::Struct(v) => v.fmt(f), Self::Make(v) => v.fmt(f), - Self::Mod(v) => v.fmt(f), - Self::Fn(v) => v.fmt(f), Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() { [cond, pass, Anno(Expr::Op(Op::Tuple, e), _)] if e.is_empty() => { @@ -539,16 +506,16 @@ impl Display for Pat { Self::MetId(name) => write!(f, "`{name}"), Self::Name(name) => name.fmt(f), Self::Path(path) => path.fmt(f), - Self::Struct(name, bind) => match bind.as_ref() { + Self::NamedStruct(name, bind) => match bind.as_ref() { Pat::Op(PatOp::Tuple, parts) => { f.delimit(fmt!("{name} {{ "), " }").list(parts, ", ") } other => write!(f, "{name} {{ {other} }}"), }, - Self::TupStruct(name, bind) => write!(f, "{name} {bind}"), - Self::Typed(pat, ty) => write!(f, "{pat}: {ty}"), + Self::NamedTuple(name, bind) => write!(f, "{name} {bind}"), Self::Op(PatOp::Tuple, pats) => f.delimit("(", ")").list(pats, ", "), Self::Op(PatOp::Slice, pats) => f.delimit("[", "]").list(pats, ", "), + 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, pats) => match pats.as_slice() { [] => op.fmt(f), @@ -562,36 +529,19 @@ impl Display for Pat { impl Display for PatOp { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match self { + Self::Ref => "&", Self::Rest => "..", Self::RangeEx => "..", Self::RangeIn => "..=", - Self::Ref => "&", Self::Tuple => ", ", Self::Slice => ", ", + Self::Typed => ": ", + Self::Fn => " -> ", Self::Alt => " | ", }) } } -impl Display for Ty { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Infer => "_".fmt(f), - Self::Named(name) => name.fmt(f), - Self::Ref(ty) => write!(f, "&{ty}"), - Self::Tuple(items) => f.delimit('(', ')').list(items, ", "), - Self::Slice(ty) => write!(f, "[{ty}]"), - Self::Array(ty, n) => write!(f, "[{ty}; {n}]"), - Self::Fn(items) => match items.as_slice() { - [] => write!(f, "fn ()"), - [args @ .., rety] => f - .delimit(fmt!("fn ("), fmt!(") -> {rety}")) - .list(args, ", "), - }, - } - } -} - impl TryFrom> for Pat { type Error = Expr; diff --git a/src/ast/macro_matcher.rs b/src/ast/macro_matcher.rs index 25e85b7..453f3a5 100644 --- a/src/ast/macro_matcher.rs +++ b/src/ast/macro_matcher.rs @@ -78,24 +78,6 @@ impl + Annotation, A: Annotation> Match for Anno { } } -impl Match for Fn { - fn recurse(sub: &mut Subst, pat: &Self, expr: &Self) -> bool { - let ( - Self(pat_id, pat_arg, _pat_rety, pat_body), - Self(expr_id, expr_arg, _expr_rety, expr_body), - ) = (pat, expr); - pat_id == expr_id - && Match::recurse(sub, pat_arg, expr_arg) - && Match::recurse(sub, pat_body, expr_body) - } - - fn apply(&mut self, sub: &Subst) { - let Self(_, pat, _rety, body) = self; - pat.apply(sub); - body.apply(sub); - } -} - impl Match for Bind { fn recurse(sub: &mut Subst, pat: &Self, expr: &Self) -> bool { let (Self(pat_kind, pat_pat, pat_expr), Self(expr_kind, expr_pat, expr_expr)) = (pat, expr); @@ -124,20 +106,6 @@ impl Match for crate::ast::Make { } } -impl Match for Mod { - fn recurse(sub: &mut Subst, pat: &Self, expr: &Self) -> bool { - let (Self(_pat_ty, pat_expr), Self(_expr_ty, expr_expr)) = (pat, expr); - // TODO: unify types for ast matching - // Match::recurse(sub, pat_ty, expr_ty) && - Match::recurse(sub, pat_expr, expr_expr) - } - - fn apply(&mut self, sub: &Subst) { - let Mod(_ty, expr) = self; - expr.apply(sub); - } -} - impl Match for Typedef { fn recurse(sub: &mut Subst, pat: &Self, expr: &Self) -> bool { let (Self(pat_kind, pat_pat), Self(expr_kind, expr_pat)) = (pat, expr); @@ -165,10 +133,6 @@ impl Match for Expr { (Expr::Struct(_), _) => false, (Expr::Make(pat), Expr::Make(expr)) => Match::recurse(sub, pat, expr), (Expr::Make(..), _) => 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), - (Expr::Fn(..), _) => false, (Expr::Op(pat_op, pat_exprs), Expr::Op(expr_op, expr_exprs)) => { Match::recurse(sub, pat_op, expr_op) && Match::recurse(sub, pat_exprs, expr_exprs) } @@ -187,8 +151,6 @@ impl Match for Expr { Expr::Bind(expr) => expr.apply(sub), Expr::Struct(expr) => expr.apply(sub), Expr::Make(expr) => expr.apply(sub), - Expr::Mod(expr) => expr.apply(sub), - Expr::Fn(expr) => expr.apply(sub), Expr::Op(op, exprs) => { op.apply(sub); exprs.apply(sub); @@ -220,14 +182,12 @@ impl Match for Pat { (Pat::Name(_), _) => false, (Pat::Path(_), Pat::Path(_)) => true, (Pat::Path(_), _) => false, - (Pat::Struct(_, pat), Pat::Struct(_, expr)) => Match::recurse(sub, pat, expr), - (Pat::Struct(..), _) => false, - (Pat::TupStruct(_, pat), Pat::TupStruct(_, expr)) => Match::recurse(sub, pat, expr), - (Pat::TupStruct(..), _) => false, + (Pat::NamedStruct(_, pat), Pat::NamedStruct(_, expr)) => Match::recurse(sub, pat, expr), + (Pat::NamedStruct(..), _) => false, + (Pat::NamedTuple(_, pat), Pat::NamedTuple(_, expr)) => Match::recurse(sub, pat, expr), + (Pat::NamedTuple(..), _) => false, (Pat::Lit(pat), Pat::Lit(expr)) => pat == expr, (Pat::Lit(_), _) => false, - (Pat::Typed(pat, _), Pat::Typed(expr, _)) => Match::recurse(sub, pat, expr), - (Pat::Typed(..), _) => false, (Pat::Op(_, pat), Pat::Op(_, expr)) => Match::recurse(sub, pat, expr), (Pat::Op(..), _) => false, } @@ -241,27 +201,13 @@ impl Match for Pat { *self = expr.clone() } } - Pat::Struct(_, expr) => expr.apply(sub), - Pat::TupStruct(_, expr) => expr.apply(sub), - Pat::Typed(pat, ty) => { - pat.apply(sub); - ty.apply(sub); - } + Pat::NamedStruct(_, expr) => expr.apply(sub), + Pat::NamedTuple(_, expr) => expr.apply(sub), Pat::Op(_, pats) => pats.apply(sub), } } } -impl Match for Ty { - fn apply(&mut self, sub: &Subst) { - todo!("Apply subst {sub:?} for {self}.") - } - - fn recurse(sub: &mut Subst, pat: &Self, expr: &Self) -> bool { - todo!("Construct subst {sub:?} from {pat} and {expr}.") - } -} - impl Match for Op { fn recurse(_: &mut Subst, pat: &Self, expr: &Self) -> bool { pat == expr diff --git a/src/main.rs b/src/main.rs index 8470210..dab82c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ //! Tests the lexer use doughlang::{ - ast::{Anno, Pat, Ty}, + ast::{Anno, Pat}, parser::PPrec, }; #[allow(unused_imports)] @@ -45,10 +45,6 @@ fn main() -> Result<(), Box> { pats()?; Ok(Response::Deny) } - "ty" => { - tys()?; - Ok(Response::Deny) - } "macro" => { if let Err(e) = subst() { println!("\x1b[31m{e}\x1b[0m"); @@ -141,29 +137,6 @@ fn pats() -> Result<(), Box> { Ok(()) } -fn tys() -> Result<(), Box> { - clear(); - read_and("\x1b[94m", ".>", " >", |line| { - let mut parser = Parser::new(Lexer::new(line)); - if line.trim().is_empty() { - return Ok(Response::Break); - } - loop { - match parser.parse::(()) { - Err(ParseError::FromLexer(LexError { res: EOF, .. })) => { - break Ok(Response::Accept); - } - Err(e) => { - println!("\x1b[31m{e}\x1b[0m"); - break Ok(Response::Deny); - } - Ok(v) => println!("{v}\n{v:#?}"), - } - } - })?; - Ok(()) -} - fn subst() -> Result<(), Box> { let mut rl = repline::Repline::new("\x1b[35mexp", " >", "?>"); let exp = rl.read()?; diff --git a/src/parser.rs b/src/parser.rs index f68f427..27d124c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -271,18 +271,13 @@ impl<'t> Parse<'t> for Literal { Ok(match tok.kind { TKind::True => p.consume().then(Literal::Bool(true)), TKind::False => p.consume().then(Literal::Bool(false)), - TKind::Character => Literal::Char({ - let Token { lexeme, .. } = p.take().expect("should have Token"); - lexeme.char().expect("char token should have char") - }), - TKind::Integer => Literal::Int({ - let Token { lexeme, .. } = p.take().expect("should have Token"); - lexeme.int().expect("integer token should have int") - }), - TKind::String => Literal::Str({ - let Token { lexeme, .. } = p.take().expect("should have Token"); - lexeme.string().expect("string token should have string") - }), + TKind::Character | TKind::Integer | TKind::String => { + match p.take().expect("should have Token").lexeme { + Lexeme::String(str) => Literal::Str(str), + Lexeme::Integer(int, base) => Literal::Int(int, base), + Lexeme::Char(chr) => Literal::Char(chr), + } + } other => Err(ParseError::NotLiteral(other, tok.span))?, }) } @@ -295,6 +290,7 @@ pub enum PPrec { Tuple, Typed, Range, + Fn, Max, } @@ -305,14 +301,14 @@ impl PPrec { Self::Alt => Self::Tuple, Self::Tuple => Self::Typed, Self::Typed => Self::Range, - Self::Range => Self::Max, + Self::Range => Self::Fn, + Self::Fn => Self::Max, Self::Max => Self::Max, } } } enum PatPs { - Typed, Op(PatOp), } @@ -320,8 +316,9 @@ fn pat_from_infix(token: &Token) -> Option<(PatPs, PPrec)> { Some(match token.kind { TKind::DotDot => (PatPs::Op(PatOp::RangeEx), PPrec::Range), TKind::DotDotEq => (PatPs::Op(PatOp::RangeIn), PPrec::Range), - TKind::Colon => (PatPs::Typed, PPrec::Typed), + TKind::Colon => (PatPs::Op(PatOp::Typed), PPrec::Typed), TKind::Comma => (PatPs::Op(PatOp::Tuple), PPrec::Tuple), + TKind::Arrow => (PatPs::Op(PatOp::Fn), PPrec::Fn), TKind::Bar => (PatPs::Op(PatOp::Alt), PPrec::Alt), _ => None?, }) @@ -335,6 +332,7 @@ impl<'t> Parse<'t> for Pat { // Prefix let mut head = match tok.kind { + TKind::Fn => return p.consume().parse(PPrec::Fn), TKind::True | TKind::False | TKind::Character | TKind::Integer | TKind::String => { Pat::Lit(p.parse(())?) } @@ -350,8 +348,8 @@ impl<'t> Parse<'t> for Pat { let mut path: FqPath = p.parse(())?; // TODO: make these postfix. match p.peek().map(|t| t.kind) { - Ok(TKind::LParen) => Pat::TupStruct(path, p.parse(PPrec::Typed)?), - Ok(TKind::LCurly) => Pat::Struct( + Ok(TKind::LParen) => Pat::NamedTuple(path, p.parse(PPrec::Typed)?), + Ok(TKind::LCurly) if level <= PPrec::Tuple => Pat::NamedStruct( path, p.consume() .opt(PPrec::Alt, TKind::RCurly)? @@ -406,7 +404,12 @@ impl<'t> Parse<'t> for Pat { { let kind = tok.kind; head = match op { - PatPs::Typed => Pat::Typed(head.into(), p.consume().parse(())?), + PatPs::Op(PatOp::Typed) => { + Pat::Op(PatOp::Typed, vec![head, p.consume().parse(PPrec::Max)?]) + } + PatPs::Op(PatOp::Fn) => { + Pat::Op(PatOp::Fn, vec![head, p.consume().parse(PPrec::Fn.next())?]) + } PatPs::Op(op @ (PatOp::RangeEx | PatOp::RangeIn)) => Pat::Op( op, match p.consume().peek().map(|t| t.kind) { @@ -423,59 +426,59 @@ impl<'t> Parse<'t> for Pat { } } -impl<'t> Parse<'t> for Ty { - type Prec = (); +// impl<'t> Parse<'t> for Ty { +// type Prec = (); - fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult - where Self: Sized { - let &Token { kind, span, .. } = p.peek()?; +// fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult +// where Self: Sized { +// let &Token { kind, span, .. } = p.peek()?; - // TODO: this is a kinda jank way of error reporting - let head = match kind { - TKind::Identifier => match p.peek()?.lexeme.str() { - Some("_") => p.consume().then(Ty::Infer), - _ => Ty::Named(p.parse(())?), - }, - TKind::Amp => Ty::Ref(p.consume().parse(())?), - TKind::AmpAmp => Ty::Ref(Box::new(Ty::Ref(p.consume().parse(())?))), - TKind::LBrack => { - let ty = p.consume().parse(level)?; - match p.next()? { - Token { kind: TKind::Semi, .. } => { - let ty = Ty::Array(ty, p.parse(Prec::Binary.next())?); - p.expect(TKind::RBrack)?; - ty - } - Token { kind: TKind::RBrack, .. } => Ty::Slice(ty), - tok => Err(ParseError::NotType(tok.kind, tok.span))?, - } - } - TKind::Fn => { - p.consume(); - match p.parse(())? { - Ty::Fn(args) => Ty::Fn(args), - other @ Ty::Tuple(_) => Ty::Fn(vec![other, Ty::Tuple(vec![])]), - other => Ty::Fn(vec![other, Ty::Tuple(vec![])]), - } - } - TKind::LParen => { - Ty::Tuple(p.consume().list(vec![], (), TKind::Comma, TKind::RParen)?) - } - _ => Err(ParseError::NotType(kind, span))?, - }; +// // TODO: this is a kinda jank way of error reporting +// let head = match kind { +// TKind::Identifier => match p.peek()?.lexeme.str() { +// Some("_") => p.consume().then(Ty::Infer), +// _ => Ty::Named(p.parse(())?), +// }, +// TKind::Amp => Ty::Ref(p.consume().parse(())?), +// TKind::AmpAmp => Ty::Ref(Box::new(Ty::Ref(p.consume().parse(())?))), +// TKind::LBrack => { +// let ty = p.consume().parse(level)?; +// match p.next()? { +// Token { kind: TKind::Semi, .. } => { +// let ty = Ty::Array(ty, p.parse(Prec::Binary.next())?); +// p.expect(TKind::RBrack)?; +// ty +// } +// Token { kind: TKind::RBrack, .. } => Ty::Slice(ty), +// tok => Err(ParseError::NotType(tok.kind, tok.span))?, +// } +// } +// TKind::Fn => { +// p.consume(); +// match p.parse(())? { +// Ty::Fn(args) => Ty::Fn(args), +// other @ Ty::Tuple(_) => Ty::Fn(vec![other, Ty::Tuple(vec![])]), +// other => Ty::Fn(vec![other, Ty::Tuple(vec![])]), +// } +// } +// TKind::LParen => { +// Ty::Tuple(p.consume().list(vec![], (), TKind::Comma, TKind::RParen)?) +// } +// _ => Err(ParseError::NotType(kind, span))?, +// }; - Ok(match p.next_if(TKind::Arrow).allow_eof()? { - Some(Ok(_)) => Ty::Fn(vec![ - match head { - args @ Ty::Tuple(_) => args, - arg => Ty::Tuple(vec![arg]), - }, - p.parse(())?, - ]), - _ => head, - }) - } -} +// Ok(match p.next_if(TKind::Arrow).allow_eof()? { +// Some(Ok(_)) => Ty::Fn(vec![ +// match head { +// args @ Ty::Tuple(_) => args, +// arg => Ty::Tuple(vec![arg]), +// }, +// p.parse(())?, +// ]), +// _ => head, +// }) +// } +// } /// Organizes the precedence hierarchy for syntactic elements #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -669,73 +672,57 @@ impl<'t> Parse<'t> for Typedef { fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult { let tok = p.next()?; match tok.kind { - TKind::Enum => Ok(Self(TypedefKind::Enum, p.parse(PPrec::Alt)?)), + TKind::Enum => Ok(Self(TypedefKind::Enum, p.parse(PPrec::Tuple)?)), TKind::Struct => Ok(Self(TypedefKind::Struct, p.parse(PPrec::Tuple)?)), _ => Err(ParseError::NotType(tok.kind, tok.span)), } } } -impl<'t> Parse<'t> for Fn { - type Prec = (); - - fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult { - match p.consume().next_if(TKind::Identifier)? { - Ok(Token { lexeme, .. }) => Ok(Self( - lexeme.string(), - p.parse(PPrec::Tuple)?, - p.opt_if((), TKind::Arrow)?.unwrap_or(Ty::Tuple(vec![])), - p.parse(Prec::Body.next())?, - )), - _ => Ok(Self( - None, - Pat::Op( - PatOp::Tuple, - p.expect(TKind::LParen)?.list( - vec![], - PPrec::Tuple, - TKind::Comma, - TKind::RParen, - )?, - ), - p.opt_if((), TKind::Arrow)?.unwrap_or(Ty::Tuple(vec![])), - p.parse(Prec::Body.next())?, - )), - } - } -} - impl<'t> Parse<'t> for Bind { type Prec = BindKind; fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult { - if let BindKind::Match = level { - // |? Pat => Expr - p.next_if(TKind::Bar)?.ok(); // and discard - return Ok(Self( + match level { + BindKind::Match => { + // |? Pat => Expr + p.next_if(TKind::Bar)?.ok(); // and discard + Ok(Self( + level, + p.parse(PPrec::Alt)?, + vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?], + )) + } + BindKind::Mod => Ok(Self( level, - p.parse(PPrec::Min)?, - vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?], - )); - } + p.consume().parse(PPrec::Max)?, + vec![p.parse(Prec::Body.next())?], + )), + BindKind::Fn => Ok(Self( + level, + p.consume().parse(PPrec::Fn)?, + vec![p.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![])); + } - // 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(level, pat, vec![body])); + } - // = 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(level, pat, vec![body])); + // else Expr + Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?])) + } } - - // else Expr - Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?])) } } @@ -753,16 +740,6 @@ impl<'t> Parse<'t> for MakeArm { } } -impl<'t> Parse<'t> for Mod { - type Prec = (); - - fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult { - let ty = p.consume().parse(())?; - let body = p.parse(Prec::Body.value())?; - Ok(Mod(ty, body)) - } -} - fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult { // for Pat let pat = p.consume().parse(PPrec::Tuple)?; @@ -830,7 +807,7 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult { .anno(fspan), Expr::Bind(Box::new(Bind( BindKind::Match, - Pat::TupStruct( + Pat::NamedTuple( "Some".into(), Box::new(Pat::Op(PatOp::Tuple, vec![pat])), ), @@ -876,12 +853,31 @@ 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::Typedef => Expr::Struct(p.parse(())?), Ps::Let => Expr::Bind(p.parse(BindKind::Let)?), Ps::Const => Expr::Bind(p.parse(BindKind::Const)?), Ps::Static => Expr::Bind(p.parse(BindKind::Static)?), + Ps::Mod => Expr::Bind(p.parse(BindKind::Mod)?), + Ps::Fn => Expr::Bind(p.parse(BindKind::Fn)?), + Ps::Lambda | Ps::Lambda0 => { + p.consume(); + + let args = if op == Ps::Lambda { + p.opt(PPrec::Tuple, TKind::Bar)? + .unwrap_or(Pat::Op(PatOp::Tuple, vec![])) + } else { + Pat::Op(PatOp::Tuple, vec![]) + }; + + let rety = p.opt_if(PPrec::Max, TKind::Arrow)?.unwrap_or(Pat::Ignore); + + Expr::Bind(Box::new(Bind( + BindKind::Fn, + Pat::Op(PatOp::Fn, vec![args, rety]), + vec![p.parse(Prec::Body.next())?], + ))) + } Ps::For => parse_for(p, ())?, - Ps::Typedef => Expr::Struct(p.parse(())?), - Ps::Mod => Expr::Mod(p.parse(())?), Ps::Op(Op::Match) => parse_match(p)?, Ps::Op(Op::Meta) => Expr::Op( Op::Meta, @@ -917,21 +913,6 @@ impl<'t> Parse<'t> for Expr { ]; Expr::Op(op, exprs) } - Ps::Fn => Expr::Fn(p.parse(())?), - Ps::Lambda => Expr::Fn(Box::new(Fn( - None, - p.consume() - .opt(PPrec::Tuple, TKind::Bar)? - .unwrap_or(Pat::Op(PatOp::Tuple, vec![])), - p.opt_if((), TKind::Arrow)?.unwrap_or(Ty::Infer), - p.parse(Prec::Body.next())?, - ))), - Ps::Lambda0 => Expr::Fn(Box::new(Fn( - None, - Pat::Op(PatOp::Tuple, vec![]), - p.consume().opt_if((), TKind::Arrow)?.unwrap_or(Ty::Infer), - p.parse(Prec::Body.next())?, - ))), Ps::DoubleRef => p.consume().parse(prec.next()).map(|Anno(expr, span)| { Expr::Op( Op::Refer,