ast: Add use, tackle remaining low-hanging fruit

This commit is contained in:
2025-10-21 07:09:12 -04:00
parent 9cccac5910
commit ccb6bef6d9
5 changed files with 106 additions and 64 deletions

View File

@@ -45,6 +45,19 @@ pub enum Literal {
Str(String),
}
/// A compound import declaration
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Use {
/// "*"
Glob,
/// Identifier
Name(String),
/// Identifier :: Use
Path(String, Box<Use>),
/// { Use, * }
Tree(Vec<Use>),
}
/// Binding patterns for each kind of matchable value.
///
/// This covers both patterns in Match expressions, and type annotations.
@@ -71,6 +84,8 @@ pub enum Pat {
/// Operators on lists of patterns
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PatOp {
/// Changes the binding mode to "mutable"
Mut,
/// Matches the dereference of a pointer (`&pat`)
Ref,
/// Matches a partial decomposition (`..rest`) or upper-bounded range (`..100`)
@@ -83,6 +98,8 @@ pub enum PatOp {
Tuple,
/// Matches the elements of a slice or array
Slice,
/// Matches a constant-size slice with repeating elements
Arrep,
/// Matches a type annotation or struct member
Typed,
/// Matches a function signature
@@ -96,6 +113,7 @@ pub enum PatOp {
/// let Pat (= Expr (else Expr)?)?
/// const Pat (= Expr (else Expr)?)?
/// static Pat (= Expr (else Expr)?)?
/// type Pat (= Expr)?
/// fn Pat Expr
/// mod Pat Expr
/// impl Pat Expr
@@ -112,6 +130,8 @@ pub enum BindKind {
Const,
/// A `static Pat = Expr` binding
Static,
/// A type-alias binding
Type,
/// A `fn Pat Expr` binding
Fn,
/// A `mod Pat Expr` binding
@@ -143,7 +163,6 @@ pub struct Typedef(pub TypedefKind, pub Pat);
/// The type of type being defined
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TypedefKind {
Alias,
Struct,
Enum,
}
@@ -157,6 +176,8 @@ pub enum Expr<A: Annotation = Span> {
MetId(String),
/// A literal bool, string, char, or int
Lit(Literal),
/// use Use
Use(Use),
/// `(let | const | static) Pat::NoTopAlt (= expr (else expr)?)?` |
/// `(fn | mod | impl) Pat::Fn Expr`
Bind(Box<Bind<A>>),
@@ -310,6 +331,23 @@ impl<T: Display + Annotation, A: Annotation> Display for Anno<T, A> {
}
}
impl Display for Use {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Glob => "*".fmt(f),
Self::Name(name) => name.fmt(f),
Self::Path(segment, rest) => write!(f, "{segment}::{rest}"),
Self::Tree(items) => match items.len() {
0 => "{}".fmt(f),
1..=3 => f.delimit("{ ", " }").list(items, ", "),
_ => f
.delimit_indented("{", "}")
.list_wrap("\n", items, ",\n", ",\n"),
},
}
}
}
impl<A: Annotation> Display for Bind<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(op, pat, exprs) = self;
@@ -335,6 +373,7 @@ impl Display for BindKind {
Self::Let => "let ",
Self::Const => "const ",
Self::Static => "static ",
Self::Type => "type ",
Self::Fn => "fn ",
Self::Mod => "mod ",
Self::Impl => "impl ",
@@ -354,7 +393,6 @@ impl Display for Typedef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self(kind, pat) = self;
f.write_str(match kind {
TypedefKind::Alias => "type ",
TypedefKind::Struct => "struct ",
TypedefKind::Enum => "enum ",
})?;
@@ -376,6 +414,7 @@ impl<A: Annotation> Display for Expr<A> {
Self::Id(id) => id.fmt(f),
Self::MetId(id) => write!(f, "`{id}"),
Self::Lit(literal) => literal.fmt(f),
Self::Use(v) => write!(f, "use {v}"),
Self::Bind(v) => v.fmt(f),
Self::Struct(v) => v.fmt(f),
Self::Make(v) => v.fmt(f),
@@ -515,6 +554,7 @@ impl Display for Pat {
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::Arrep, pats) => f.delimit("[", "]").list(pats, op),
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() {
@@ -529,12 +569,14 @@ 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::Mut => "mut ",
Self::Ref => "&",
Self::Rest => "..",
Self::RangeEx => "..",
Self::RangeIn => "..=",
Self::Tuple => ", ",
Self::Slice => ", ",
Self::Arrep => "; ",
Self::Typed => ": ",
Self::Fn => " -> ",
Self::Alt => " | ",