ast: Merge Ty into Pat, merge Mod and Fn into Bind
This commit is contained in:
152
src/ast.rs
152
src/ast.rs
@@ -40,12 +40,14 @@ pub enum Literal {
|
|||||||
/// A character literal: 'a', '\u{1f988}'
|
/// A character literal: 'a', '\u{1f988}'
|
||||||
Char(char),
|
Char(char),
|
||||||
/// An integer literal: 0, 123, 0x10
|
/// An integer literal: 0, 123, 0x10
|
||||||
Int(u128),
|
Int(u128, u32),
|
||||||
/// A string literal:
|
/// A string literal:
|
||||||
Str(String),
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Pat {
|
pub enum Pat {
|
||||||
/// Matches anything without binding
|
/// Matches anything without binding
|
||||||
@@ -57,13 +59,11 @@ pub enum Pat {
|
|||||||
/// Matches against a named const value
|
/// Matches against a named const value
|
||||||
Path(FqPath),
|
Path(FqPath),
|
||||||
/// Matches a Struct Expression `Ident { Pat }`
|
/// Matches a Struct Expression `Ident { Pat }`
|
||||||
Struct(FqPath, Box<Pat>),
|
NamedStruct(FqPath, Box<Pat>),
|
||||||
/// Matches a Tuple Struct Expression `Ident ( Pat )`
|
/// Matches a Tuple Struct Expression `Ident ( Pat )`
|
||||||
TupStruct(FqPath, Box<Pat>),
|
NamedTuple(FqPath, Box<Pat>),
|
||||||
/// Matches a literal value by equality comparison
|
/// Matches a literal value by equality comparison
|
||||||
Lit(Literal),
|
Lit(Literal),
|
||||||
/// Matches a typed pattern
|
|
||||||
Typed(Box<Pat>, Ty),
|
|
||||||
/// Matches a compound pattern
|
/// Matches a compound pattern
|
||||||
Op(PatOp, Vec<Pat>),
|
Op(PatOp, Vec<Pat>),
|
||||||
}
|
}
|
||||||
@@ -83,34 +83,22 @@ pub enum PatOp {
|
|||||||
Tuple,
|
Tuple,
|
||||||
/// Matches the elements of a slice or array
|
/// Matches the elements of a slice or array
|
||||||
Slice,
|
Slice,
|
||||||
|
/// Matches a type annotation or struct member
|
||||||
|
Typed,
|
||||||
|
/// Matches a function signature
|
||||||
|
Fn,
|
||||||
/// Matches one of a list of alternatives
|
/// Matches one of a list of alternatives
|
||||||
Alt,
|
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
|
/// A pattern binding
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// let Pat (= Expr (else Expr)?)?
|
/// let Pat (= Expr (else Expr)?)?
|
||||||
/// const Pat (= Expr (else Expr)?)?
|
/// const Pat (= Expr (else Expr)?)?
|
||||||
/// static Pat (= Expr (else Expr)?)?
|
/// static Pat (= Expr (else Expr)?)?
|
||||||
|
/// fn Pat Expr
|
||||||
|
/// mod Pat Expr
|
||||||
|
/// impl Pat Expr
|
||||||
/// Pat => Expr // in match
|
/// Pat => Expr // in match
|
||||||
/// ``````
|
/// ``````
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@@ -124,17 +112,16 @@ pub enum BindKind {
|
|||||||
Const,
|
Const,
|
||||||
/// A `static Pat = Expr` binding
|
/// A `static Pat = Expr` binding
|
||||||
Static,
|
Static,
|
||||||
|
/// A `fn Pat Expr` binding
|
||||||
|
Fn,
|
||||||
|
/// A `mod Pat Expr` binding
|
||||||
|
Mod,
|
||||||
|
/// An `impl Pat Expr` binding
|
||||||
|
Impl,
|
||||||
/// A `Pat => Expr` binding
|
/// A `Pat => Expr` binding
|
||||||
Match,
|
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
|
/// A make (constructor) expression
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// Expr { (Ident (: Expr)?),* }
|
/// 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)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>>);
|
pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>>);
|
||||||
|
|
||||||
/// An inline namespace
|
/// A record-type definition
|
||||||
/// ```ignore
|
|
||||||
/// mod Ty Expr
|
|
||||||
/// ```
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[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
|
/// The type of type being defined
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@@ -164,10 +148,6 @@ pub enum TypedefKind {
|
|||||||
Enum,
|
Enum,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A record-type definition
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct Typedef(pub TypedefKind, pub Pat);
|
|
||||||
|
|
||||||
/// Expressions: The beating heart of Dough
|
/// Expressions: The beating heart of Dough
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Expr<A: Annotation = Span> {
|
pub enum Expr<A: Annotation = Span> {
|
||||||
@@ -177,16 +157,13 @@ pub enum Expr<A: Annotation = Span> {
|
|||||||
MetId(String),
|
MetId(String),
|
||||||
/// A literal bool, string, char, or int
|
/// A literal bool, string, char, or int
|
||||||
Lit(Literal),
|
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>>),
|
Bind(Box<Bind<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`
|
|
||||||
Fn(Box<Fn<A>>),
|
|
||||||
/// Expr { (Ident (: Expr)?),* }
|
/// Expr { (Ident (: Expr)?),* }
|
||||||
Make(Box<Make<A>>),
|
Make(Box<Make<A>>),
|
||||||
/// mod Ty Expr
|
|
||||||
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
|
||||||
Op(Op, Vec<Anno<Self, A>>),
|
Op(Op, Vec<Anno<Self, A>>),
|
||||||
}
|
}
|
||||||
@@ -311,7 +288,10 @@ impl Display for Literal {
|
|||||||
match self {
|
match self {
|
||||||
Self::Bool(v) => v.fmt(f),
|
Self::Bool(v) => v.fmt(f),
|
||||||
Self::Char(c) => write!(f, "'{}'", c.escape_debug()),
|
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()),
|
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> {
|
impl<A: Annotation> Display for Bind<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(op, pat, exprs) = self;
|
let Self(op, pat, exprs) = self;
|
||||||
|
|
||||||
if let BindKind::Match = op {
|
match op {
|
||||||
return f.delimit(fmt!("{pat} => "), "").list(exprs, ",!? ");
|
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}"),
|
_ => match exprs.as_slice() {
|
||||||
[value] => write!(f, "{op} {pat} = {value}"),
|
[] => write!(f, "{op}{pat}"),
|
||||||
[value, fail] => write!(f, "{op} {pat} = {value} else {fail}"),
|
[value] => write!(f, "{op}{pat} = {value}"),
|
||||||
other => f.delimit(fmt!("{op}?! {pat} ("), ")").list(other, ", "),
|
[value, fail] => write!(f, "{op} {pat} = {value} else {fail}"),
|
||||||
|
other => f.delimit(fmt!("{op}{pat} ("), ")").list(other, ", "),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,9 +332,12 @@ impl<A: Annotation> Display for Bind<A> {
|
|||||||
impl Display for BindKind {
|
impl Display for BindKind {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.write_str(match self {
|
f.write_str(match self {
|
||||||
Self::Let => "let",
|
Self::Let => "let ",
|
||||||
Self::Const => "const",
|
Self::Const => "const ",
|
||||||
Self::Static => "static",
|
Self::Static => "static ",
|
||||||
|
Self::Fn => "fn ",
|
||||||
|
Self::Mod => "mod ",
|
||||||
|
Self::Impl => "impl ",
|
||||||
Self::Match => "| ",
|
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 {
|
impl Display for Typedef {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let Self(kind, pat) = self;
|
let Self(kind, pat) = self;
|
||||||
@@ -390,7 +359,7 @@ impl Display for Typedef {
|
|||||||
TypedefKind::Enum => "enum ",
|
TypedefKind::Enum => "enum ",
|
||||||
})?;
|
})?;
|
||||||
match pat {
|
match pat {
|
||||||
Pat::Struct(name, bind) => match bind.as_ref() {
|
Pat::NamedStruct(name, bind) => match bind.as_ref() {
|
||||||
Pat::Op(PatOp::Tuple, parts) => f
|
Pat::Op(PatOp::Tuple, parts) => f
|
||||||
.delimit_indented(fmt!("{name} {{"), "}")
|
.delimit_indented(fmt!("{name} {{"), "}")
|
||||||
.list_wrap("\n", parts, ",\n", ",\n"),
|
.list_wrap("\n", parts, ",\n", ",\n"),
|
||||||
@@ -410,8 +379,6 @@ impl<A: Annotation> Display for Expr<A> {
|
|||||||
Self::Bind(v) => v.fmt(f),
|
Self::Bind(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::Mod(v) => v.fmt(f),
|
|
||||||
Self::Fn(v) => v.fmt(f),
|
|
||||||
|
|
||||||
Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
|
Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
|
||||||
[cond, pass, Anno(Expr::Op(Op::Tuple, e), _)] if e.is_empty() => {
|
[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::MetId(name) => write!(f, "`{name}"),
|
||||||
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::NamedStruct(name, bind) => match bind.as_ref() {
|
||||||
Pat::Op(PatOp::Tuple, parts) => {
|
Pat::Op(PatOp::Tuple, parts) => {
|
||||||
f.delimit(fmt!("{name} {{ "), " }").list(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::NamedTuple(name, bind) => write!(f, "{name} {bind}"),
|
||||||
Self::Typed(pat, ty) => write!(f, "{pat}: {ty}"),
|
|
||||||
Self::Op(PatOp::Tuple, pats) => f.delimit("(", ")").list(pats, ", "),
|
Self::Op(PatOp::Tuple, pats) => f.delimit("(", ")").list(pats, ", "),
|
||||||
Self::Op(PatOp::Slice, 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 @ PatOp::Alt, pats) => f.delimit("<", ">").list(pats, op),
|
||||||
Self::Op(op, pats) => match pats.as_slice() {
|
Self::Op(op, pats) => match pats.as_slice() {
|
||||||
[] => op.fmt(f),
|
[] => op.fmt(f),
|
||||||
@@ -562,36 +529,19 @@ impl Display for Pat {
|
|||||||
impl Display for PatOp {
|
impl Display for PatOp {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.write_str(match self {
|
f.write_str(match self {
|
||||||
|
Self::Ref => "&",
|
||||||
Self::Rest => "..",
|
Self::Rest => "..",
|
||||||
Self::RangeEx => "..",
|
Self::RangeEx => "..",
|
||||||
Self::RangeIn => "..=",
|
Self::RangeIn => "..=",
|
||||||
Self::Ref => "&",
|
|
||||||
Self::Tuple => ", ",
|
Self::Tuple => ", ",
|
||||||
Self::Slice => ", ",
|
Self::Slice => ", ",
|
||||||
|
Self::Typed => ": ",
|
||||||
|
Self::Fn => " -> ",
|
||||||
Self::Alt => " | ",
|
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 {
|
impl<A: Annotation> TryFrom<Expr<A>> for Pat {
|
||||||
type Error = Expr<A>;
|
type Error = Expr<A>;
|
||||||
|
|
||||||
|
|||||||
@@ -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> {
|
impl<A: Annotation> Match<A> for Bind<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_kind, pat_pat, pat_expr), Self(expr_kind, expr_pat, expr_expr)) = (pat, expr);
|
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 {
|
impl<A: Annotation> Match<A> for Typedef {
|
||||||
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_kind, pat_pat), Self(expr_kind, expr_pat)) = (pat, expr);
|
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::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::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)) => {
|
(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)
|
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::Bind(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::Mod(expr) => expr.apply(sub),
|
|
||||||
Expr::Fn(expr) => expr.apply(sub),
|
|
||||||
Expr::Op(op, exprs) => {
|
Expr::Op(op, exprs) => {
|
||||||
op.apply(sub);
|
op.apply(sub);
|
||||||
exprs.apply(sub);
|
exprs.apply(sub);
|
||||||
@@ -220,14 +182,12 @@ impl<A: Annotation> Match<A> for Pat {
|
|||||||
(Pat::Name(_), _) => false,
|
(Pat::Name(_), _) => false,
|
||||||
(Pat::Path(_), Pat::Path(_)) => true,
|
(Pat::Path(_), Pat::Path(_)) => true,
|
||||||
(Pat::Path(_), _) => false,
|
(Pat::Path(_), _) => false,
|
||||||
(Pat::Struct(_, pat), Pat::Struct(_, expr)) => Match::recurse(sub, pat, expr),
|
(Pat::NamedStruct(_, pat), Pat::NamedStruct(_, expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Pat::Struct(..), _) => false,
|
(Pat::NamedStruct(..), _) => false,
|
||||||
(Pat::TupStruct(_, pat), Pat::TupStruct(_, expr)) => Match::recurse(sub, pat, expr),
|
(Pat::NamedTuple(_, pat), Pat::NamedTuple(_, expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Pat::TupStruct(..), _) => false,
|
(Pat::NamedTuple(..), _) => false,
|
||||||
(Pat::Lit(pat), Pat::Lit(expr)) => pat == expr,
|
(Pat::Lit(pat), Pat::Lit(expr)) => pat == expr,
|
||||||
(Pat::Lit(_), _) => false,
|
(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(_, pat), Pat::Op(_, expr)) => Match::recurse(sub, pat, expr),
|
||||||
(Pat::Op(..), _) => false,
|
(Pat::Op(..), _) => false,
|
||||||
}
|
}
|
||||||
@@ -241,27 +201,13 @@ impl<A: Annotation> Match<A> for Pat {
|
|||||||
*self = expr.clone()
|
*self = expr.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pat::Struct(_, expr) => expr.apply(sub),
|
Pat::NamedStruct(_, expr) => expr.apply(sub),
|
||||||
Pat::TupStruct(_, expr) => expr.apply(sub),
|
Pat::NamedTuple(_, expr) => expr.apply(sub),
|
||||||
Pat::Typed(pat, ty) => {
|
|
||||||
pat.apply(sub);
|
|
||||||
ty.apply(sub);
|
|
||||||
}
|
|
||||||
Pat::Op(_, pats) => pats.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 {
|
impl<A: Annotation> Match<A> for Op {
|
||||||
fn recurse(_: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
fn recurse(_: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||||
pat == expr
|
pat == expr
|
||||||
|
|||||||
29
src/main.rs
29
src/main.rs
@@ -1,6 +1,6 @@
|
|||||||
//! Tests the lexer
|
//! Tests the lexer
|
||||||
use doughlang::{
|
use doughlang::{
|
||||||
ast::{Anno, Pat, Ty},
|
ast::{Anno, Pat},
|
||||||
parser::PPrec,
|
parser::PPrec,
|
||||||
};
|
};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
@@ -45,10 +45,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
pats()?;
|
pats()?;
|
||||||
Ok(Response::Deny)
|
Ok(Response::Deny)
|
||||||
}
|
}
|
||||||
"ty" => {
|
|
||||||
tys()?;
|
|
||||||
Ok(Response::Deny)
|
|
||||||
}
|
|
||||||
"macro" => {
|
"macro" => {
|
||||||
if let Err(e) = subst() {
|
if let Err(e) = subst() {
|
||||||
println!("\x1b[31m{e}\x1b[0m");
|
println!("\x1b[31m{e}\x1b[0m");
|
||||||
@@ -141,29 +137,6 @@ fn pats() -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
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>> {
|
fn subst() -> Result<(), Box<dyn Error>> {
|
||||||
let mut rl = repline::Repline::new("\x1b[35mexp", " >", "?>");
|
let mut rl = repline::Repline::new("\x1b[35mexp", " >", "?>");
|
||||||
let exp = rl.read()?;
|
let exp = rl.read()?;
|
||||||
|
|||||||
279
src/parser.rs
279
src/parser.rs
@@ -271,18 +271,13 @@ impl<'t> Parse<'t> for Literal {
|
|||||||
Ok(match tok.kind {
|
Ok(match tok.kind {
|
||||||
TKind::True => p.consume().then(Literal::Bool(true)),
|
TKind::True => p.consume().then(Literal::Bool(true)),
|
||||||
TKind::False => p.consume().then(Literal::Bool(false)),
|
TKind::False => p.consume().then(Literal::Bool(false)),
|
||||||
TKind::Character => Literal::Char({
|
TKind::Character | TKind::Integer | TKind::String => {
|
||||||
let Token { lexeme, .. } = p.take().expect("should have Token");
|
match p.take().expect("should have Token").lexeme {
|
||||||
lexeme.char().expect("char token should have char")
|
Lexeme::String(str) => Literal::Str(str),
|
||||||
}),
|
Lexeme::Integer(int, base) => Literal::Int(int, base),
|
||||||
TKind::Integer => Literal::Int({
|
Lexeme::Char(chr) => Literal::Char(chr),
|
||||||
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")
|
|
||||||
}),
|
|
||||||
other => Err(ParseError::NotLiteral(other, tok.span))?,
|
other => Err(ParseError::NotLiteral(other, tok.span))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -295,6 +290,7 @@ pub enum PPrec {
|
|||||||
Tuple,
|
Tuple,
|
||||||
Typed,
|
Typed,
|
||||||
Range,
|
Range,
|
||||||
|
Fn,
|
||||||
Max,
|
Max,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,14 +301,14 @@ impl PPrec {
|
|||||||
Self::Alt => Self::Tuple,
|
Self::Alt => Self::Tuple,
|
||||||
Self::Tuple => Self::Typed,
|
Self::Tuple => Self::Typed,
|
||||||
Self::Typed => Self::Range,
|
Self::Typed => Self::Range,
|
||||||
Self::Range => Self::Max,
|
Self::Range => Self::Fn,
|
||||||
|
Self::Fn => Self::Max,
|
||||||
Self::Max => Self::Max,
|
Self::Max => Self::Max,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PatPs {
|
enum PatPs {
|
||||||
Typed,
|
|
||||||
Op(PatOp),
|
Op(PatOp),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,8 +316,9 @@ fn pat_from_infix(token: &Token) -> Option<(PatPs, PPrec)> {
|
|||||||
Some(match token.kind {
|
Some(match token.kind {
|
||||||
TKind::DotDot => (PatPs::Op(PatOp::RangeEx), PPrec::Range),
|
TKind::DotDot => (PatPs::Op(PatOp::RangeEx), PPrec::Range),
|
||||||
TKind::DotDotEq => (PatPs::Op(PatOp::RangeIn), 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::Comma => (PatPs::Op(PatOp::Tuple), PPrec::Tuple),
|
||||||
|
TKind::Arrow => (PatPs::Op(PatOp::Fn), PPrec::Fn),
|
||||||
TKind::Bar => (PatPs::Op(PatOp::Alt), PPrec::Alt),
|
TKind::Bar => (PatPs::Op(PatOp::Alt), PPrec::Alt),
|
||||||
_ => None?,
|
_ => None?,
|
||||||
})
|
})
|
||||||
@@ -335,6 +332,7 @@ impl<'t> Parse<'t> for Pat {
|
|||||||
|
|
||||||
// Prefix
|
// Prefix
|
||||||
let mut head = match tok.kind {
|
let mut head = match tok.kind {
|
||||||
|
TKind::Fn => return p.consume().parse(PPrec::Fn),
|
||||||
TKind::True | TKind::False | TKind::Character | TKind::Integer | TKind::String => {
|
TKind::True | TKind::False | TKind::Character | TKind::Integer | TKind::String => {
|
||||||
Pat::Lit(p.parse(())?)
|
Pat::Lit(p.parse(())?)
|
||||||
}
|
}
|
||||||
@@ -350,8 +348,8 @@ impl<'t> Parse<'t> for Pat {
|
|||||||
let mut path: FqPath = p.parse(())?;
|
let mut path: FqPath = p.parse(())?;
|
||||||
// TODO: make these postfix.
|
// TODO: make these postfix.
|
||||||
match p.peek().map(|t| t.kind) {
|
match p.peek().map(|t| t.kind) {
|
||||||
Ok(TKind::LParen) => Pat::TupStruct(path, p.parse(PPrec::Typed)?),
|
Ok(TKind::LParen) => Pat::NamedTuple(path, p.parse(PPrec::Typed)?),
|
||||||
Ok(TKind::LCurly) => Pat::Struct(
|
Ok(TKind::LCurly) if level <= PPrec::Tuple => Pat::NamedStruct(
|
||||||
path,
|
path,
|
||||||
p.consume()
|
p.consume()
|
||||||
.opt(PPrec::Alt, TKind::RCurly)?
|
.opt(PPrec::Alt, TKind::RCurly)?
|
||||||
@@ -406,7 +404,12 @@ impl<'t> Parse<'t> for Pat {
|
|||||||
{
|
{
|
||||||
let kind = tok.kind;
|
let kind = tok.kind;
|
||||||
head = match op {
|
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(
|
PatPs::Op(op @ (PatOp::RangeEx | PatOp::RangeIn)) => Pat::Op(
|
||||||
op,
|
op,
|
||||||
match p.consume().peek().map(|t| t.kind) {
|
match p.consume().peek().map(|t| t.kind) {
|
||||||
@@ -423,59 +426,59 @@ impl<'t> Parse<'t> for Pat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> Parse<'t> for Ty {
|
// impl<'t> Parse<'t> for Ty {
|
||||||
type Prec = ();
|
// type Prec = ();
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self>
|
// fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self>
|
||||||
where Self: Sized {
|
// where Self: Sized {
|
||||||
let &Token { kind, span, .. } = p.peek()?;
|
// let &Token { kind, span, .. } = p.peek()?;
|
||||||
|
|
||||||
// TODO: this is a kinda jank way of error reporting
|
// // TODO: this is a kinda jank way of error reporting
|
||||||
let head = match kind {
|
// let head = match kind {
|
||||||
TKind::Identifier => match p.peek()?.lexeme.str() {
|
// TKind::Identifier => match p.peek()?.lexeme.str() {
|
||||||
Some("_") => p.consume().then(Ty::Infer),
|
// Some("_") => p.consume().then(Ty::Infer),
|
||||||
_ => Ty::Named(p.parse(())?),
|
// _ => Ty::Named(p.parse(())?),
|
||||||
},
|
// },
|
||||||
TKind::Amp => Ty::Ref(p.consume().parse(())?),
|
// TKind::Amp => Ty::Ref(p.consume().parse(())?),
|
||||||
TKind::AmpAmp => Ty::Ref(Box::new(Ty::Ref(p.consume().parse(())?))),
|
// TKind::AmpAmp => Ty::Ref(Box::new(Ty::Ref(p.consume().parse(())?))),
|
||||||
TKind::LBrack => {
|
// TKind::LBrack => {
|
||||||
let ty = p.consume().parse(level)?;
|
// let ty = p.consume().parse(level)?;
|
||||||
match p.next()? {
|
// match p.next()? {
|
||||||
Token { kind: TKind::Semi, .. } => {
|
// Token { kind: TKind::Semi, .. } => {
|
||||||
let ty = Ty::Array(ty, p.parse(Prec::Binary.next())?);
|
// let ty = Ty::Array(ty, p.parse(Prec::Binary.next())?);
|
||||||
p.expect(TKind::RBrack)?;
|
// p.expect(TKind::RBrack)?;
|
||||||
ty
|
// ty
|
||||||
}
|
// }
|
||||||
Token { kind: TKind::RBrack, .. } => Ty::Slice(ty),
|
// Token { kind: TKind::RBrack, .. } => Ty::Slice(ty),
|
||||||
tok => Err(ParseError::NotType(tok.kind, tok.span))?,
|
// tok => Err(ParseError::NotType(tok.kind, tok.span))?,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
TKind::Fn => {
|
// TKind::Fn => {
|
||||||
p.consume();
|
// p.consume();
|
||||||
match p.parse(())? {
|
// match p.parse(())? {
|
||||||
Ty::Fn(args) => Ty::Fn(args),
|
// Ty::Fn(args) => Ty::Fn(args),
|
||||||
other @ Ty::Tuple(_) => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
|
// other @ Ty::Tuple(_) => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
|
||||||
other => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
|
// other => Ty::Fn(vec![other, Ty::Tuple(vec![])]),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
TKind::LParen => {
|
// TKind::LParen => {
|
||||||
Ty::Tuple(p.consume().list(vec![], (), TKind::Comma, TKind::RParen)?)
|
// Ty::Tuple(p.consume().list(vec![], (), TKind::Comma, TKind::RParen)?)
|
||||||
}
|
// }
|
||||||
_ => Err(ParseError::NotType(kind, span))?,
|
// _ => Err(ParseError::NotType(kind, span))?,
|
||||||
};
|
// };
|
||||||
|
|
||||||
Ok(match p.next_if(TKind::Arrow).allow_eof()? {
|
// Ok(match p.next_if(TKind::Arrow).allow_eof()? {
|
||||||
Some(Ok(_)) => Ty::Fn(vec![
|
// Some(Ok(_)) => Ty::Fn(vec![
|
||||||
match head {
|
// match head {
|
||||||
args @ Ty::Tuple(_) => args,
|
// args @ Ty::Tuple(_) => args,
|
||||||
arg => Ty::Tuple(vec![arg]),
|
// arg => Ty::Tuple(vec![arg]),
|
||||||
},
|
// },
|
||||||
p.parse(())?,
|
// p.parse(())?,
|
||||||
]),
|
// ]),
|
||||||
_ => head,
|
// _ => head,
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Organizes the precedence hierarchy for syntactic elements
|
/// Organizes the precedence hierarchy for syntactic elements
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[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<Self> {
|
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||||
let tok = p.next()?;
|
let tok = p.next()?;
|
||||||
match tok.kind {
|
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)?)),
|
TKind::Struct => Ok(Self(TypedefKind::Struct, p.parse(PPrec::Tuple)?)),
|
||||||
_ => Err(ParseError::NotType(tok.kind, tok.span)),
|
_ => 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 {
|
impl<'t> Parse<'t> for Bind {
|
||||||
type Prec = BindKind;
|
type Prec = BindKind;
|
||||||
|
|
||||||
fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self> {
|
fn parse(p: &mut Parser<'t>, level: Self::Prec) -> PResult<Self> {
|
||||||
if let BindKind::Match = level {
|
match level {
|
||||||
// |? Pat => Expr
|
BindKind::Match => {
|
||||||
p.next_if(TKind::Bar)?.ok(); // and discard
|
// |? Pat => Expr
|
||||||
return Ok(Self(
|
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,
|
level,
|
||||||
p.parse(PPrec::Min)?,
|
p.consume().parse(PPrec::Max)?,
|
||||||
vec![p.expect(TKind::FatArrow)?.parse(Prec::Body.next())?],
|
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
|
// = Expr
|
||||||
let pat = p.consume().parse(PPrec::Tuple)?;
|
let body = p.parse(Prec::Tuple.value())?;
|
||||||
if p.next_if(TKind::Eq).allow_eof()?.is_none_or(|v| v.is_err()) {
|
if p.next_if(TKind::Else)
|
||||||
return Ok(Self(level, pat, vec![]));
|
.allow_eof()?
|
||||||
}
|
.is_none_or(|v| v.is_err())
|
||||||
|
{
|
||||||
|
return Ok(Self(level, pat, vec![body]));
|
||||||
|
}
|
||||||
|
|
||||||
// = Expr
|
// else Expr
|
||||||
let body = p.parse(Prec::Tuple.value())?;
|
Ok(Self(level, pat, vec![body, p.parse(Prec::Body.next())?]))
|
||||||
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())?]))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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> {
|
fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
||||||
// for Pat
|
// for Pat
|
||||||
let pat = p.consume().parse(PPrec::Tuple)?;
|
let pat = p.consume().parse(PPrec::Tuple)?;
|
||||||
@@ -830,7 +807,7 @@ fn parse_for<'t>(p: &mut Parser<'t>, _level: ()) -> PResult<Expr> {
|
|||||||
.anno(fspan),
|
.anno(fspan),
|
||||||
Expr::Bind(Box::new(Bind(
|
Expr::Bind(Box::new(Bind(
|
||||||
BindKind::Match,
|
BindKind::Match,
|
||||||
Pat::TupStruct(
|
Pat::NamedTuple(
|
||||||
"Some".into(),
|
"Some".into(),
|
||||||
Box::new(Pat::Op(PatOp::Tuple, vec![pat])),
|
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::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::Typedef => Expr::Struct(p.parse(())?),
|
||||||
Ps::Let => Expr::Bind(p.parse(BindKind::Let)?),
|
Ps::Let => Expr::Bind(p.parse(BindKind::Let)?),
|
||||||
Ps::Const => Expr::Bind(p.parse(BindKind::Const)?),
|
Ps::Const => Expr::Bind(p.parse(BindKind::Const)?),
|
||||||
Ps::Static => Expr::Bind(p.parse(BindKind::Static)?),
|
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::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::Match) => parse_match(p)?,
|
||||||
Ps::Op(Op::Meta) => Expr::Op(
|
Ps::Op(Op::Meta) => Expr::Op(
|
||||||
Op::Meta,
|
Op::Meta,
|
||||||
@@ -917,21 +913,6 @@ impl<'t> Parse<'t> for Expr {
|
|||||||
];
|
];
|
||||||
Expr::Op(op, exprs)
|
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)| {
|
Ps::DoubleRef => p.consume().parse(prec.next()).map(|Anno(expr, span)| {
|
||||||
Expr::Op(
|
Expr::Op(
|
||||||
Op::Refer,
|
Op::Refer,
|
||||||
|
|||||||
Reference in New Issue
Block a user