ast: Merge Ty into Pat, merge Mod and Fn into Bind

This commit is contained in:
2025-10-20 04:24:21 -04:00
parent 22094f4862
commit b80a3a55c3
4 changed files with 188 additions and 338 deletions

View File

@@ -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<Pat>),
NamedStruct(FqPath, Box<Pat>),
/// Matches a Tuple Struct Expression `Ident ( Pat )`
TupStruct(FqPath, Box<Pat>),
NamedTuple(FqPath, Box<Pat>),
/// Matches a literal value by equality comparison
Lit(Literal),
/// Matches a typed pattern
Typed(Box<Pat>, Ty),
/// Matches a compound pattern
Op(PatOp, Vec<Pat>),
}
@@ -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<Ty>),
/// `(..Tys)`
Tuple(Vec<Ty>),
/// `[Ty]`
Slice(Box<Ty>),
/// `[Ty; _]`
Array(Box<Ty>, Box<Expr>),
/// `[..Args, Rety]`
Fn(Vec<Ty>),
}
/// 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<A: Annotation = Span>(pub Option<String>, pub Pat, pub Ty, pub Anno<Expr<A>, A>);
/// A make (constructor) expression
/// ```ignore
/// Expr { (Ident (: Expr)?),* }
@@ -149,12 +136,9 @@ pub struct Make<A: Annotation = Span>(pub Anno<Expr<A>, A>, pub Vec<MakeArm<A>>)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>>);
/// An inline namespace
/// ```ignore
/// mod Ty Expr
/// ```
/// A record-type definition
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Mod<A: Annotation = Span>(pub Ty, pub Anno<Expr<A>, 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<A: Annotation = Span> {
@@ -177,16 +157,13 @@ pub enum Expr<A: Annotation = Span> {
MetId(String),
/// A literal bool, string, char, or int
Lit(Literal),
/// (let | const | static) Pat<NoTopAlt> (= expr (else expr)?)?
/// `(let | const | static) Pat<NoTopAlt> (= expr (else expr)?)?` |
/// `(fn | mod | impl) Pat<Fn> Expr`
Bind(Box<Bind<A>>),
/// (struct | enum | type) Pat<NoTopAlt>
Struct(Box<Typedef>),
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr`
Fn(Box<Fn<A>>),
/// Expr { (Ident (: Expr)?),* }
Make(Box<Make<A>>),
/// mod Ty Expr
Mod(Box<Mod<A>>),
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
Op(Op, Vec<Anno<Self, A>>),
}
@@ -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<T: Display + Annotation, A: Annotation> Display for Anno<T, A> {
}
}
impl<A: Annotation> Display for Fn<A> {
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<A: Annotation> Display for Bind<A> {
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 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() {
_ => 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, ", "),
other => f.delimit(fmt!("{op}{pat} ("), ")").list(other, ", "),
},
}
}
}
@@ -362,6 +335,9 @@ impl Display for BindKind {
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<A: Annotation> Display for Make<A> {
}
}
impl<A: Annotation> Display for Mod<A> {
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<A: Annotation> Display for Expr<A> {
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<A: Annotation> TryFrom<Expr<A>> for Pat {
type Error = Expr<A>;

View File

@@ -78,24 +78,6 @@ impl<M: Match<A> + Annotation, A: Annotation> Match<A> for Anno<M, A> {
}
}
impl<A: Annotation> Match<A> for Fn<A> {
fn recurse(sub: &mut Subst<A>, 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<A>) {
let Self(_, pat, _rety, body) = self;
pat.apply(sub);
body.apply(sub);
}
}
impl<A: Annotation> Match<A> for Bind<A> {
fn recurse(sub: &mut Subst<A>, 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<A: Annotation> Match<A> for crate::ast::Make<A> {
}
}
impl<A: Annotation> Match<A> for Mod<A> {
fn recurse(sub: &mut Subst<A>, 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<A>) {
let Mod(_ty, expr) = self;
expr.apply(sub);
}
}
impl<A: Annotation> Match<A> for Typedef {
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
let (Self(pat_kind, pat_pat), Self(expr_kind, expr_pat)) = (pat, expr);
@@ -165,10 +133,6 @@ impl<A: Annotation> Match<A> for Expr<A> {
(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<A: Annotation> Match<A> for Expr<A> {
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<A: Annotation> Match<A> 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<A: Annotation> Match<A> 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<A: Annotation> Match<A> for Ty {
fn apply(&mut self, sub: &Subst<A>) {
todo!("Apply subst {sub:?} for {self}.")
}
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
todo!("Construct subst {sub:?} from {pat} and {expr}.")
}
}
impl<A: Annotation> Match<A> for Op {
fn recurse(_: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
pat == expr

View File

@@ -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<dyn Error>> {
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<dyn Error>> {
Ok(())
}
fn tys() -> Result<(), Box<dyn Error>> {
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::<Ty>(()) {
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<dyn Error>> {
let mut rl = repline::Repline::new("\x1b[35mexp", " >", "?>");
let exp = rl.read()?;

View File

@@ -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<Self>
where Self: Sized {
let &Token { kind, span, .. } = p.peek()?;
// fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self>
// 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,56 +672,38 @@ impl<'t> Parse<'t> for Typedef {
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
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<Self> {
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<Self> {
if let BindKind::Match = level {
match level {
BindKind::Match => {
// |? Pat => Expr
p.next_if(TKind::Bar)?.ok(); // and discard
return Ok(Self(
Ok(Self(
level,
p.parse(PPrec::Min)?,
p.parse(PPrec::Alt)?,
vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?],
));
))
}
BindKind::Mod => Ok(Self(
level,
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()) {
@@ -738,6 +723,8 @@ impl<'t> Parse<'t> for Bind {
Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?]))
}
}
}
}
impl<'t> Parse<'t> for MakeArm {
type Prec = ();
@@ -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<Self> {
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<Expr> {
// for Pat
let pat = p.consume().parse(PPrec::Tuple)?;
@@ -830,7 +807,7 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
.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,