From a836de32c7cca75e5255695db561577ee1ea4c37 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 20 Dec 2025 06:09:31 -0500 Subject: [PATCH] Use: add alias `use foo as bar` form --- examples/to-lisp.rs | 1 + src/ast.rs | 4 +++- src/ast/display.rs | 1 + src/ast/fold.rs | 1 + src/ast/visit.rs | 4 ++++ src/parser.rs | 13 +++++++++++-- 6 files changed, 21 insertions(+), 3 deletions(-) diff --git a/examples/to-lisp.rs b/examples/to-lisp.rs index 742b16c..a804d9d 100644 --- a/examples/to-lisp.rs +++ b/examples/to-lisp.rs @@ -178,6 +178,7 @@ impl<'a> Visit<'a> for ToLisp { match item { Use::Glob => print!("(use-glob)"), Use::Name(name) => name.visit_in(self)?, + Use::Alias(name, alias) => print!("(use-alias {name} {alias})"), Use::Path(name, tree) => { print!("(use-path {name} "); tree.visit_in(self)?; diff --git a/src/ast.rs b/src/ast.rs index 074afbb..450dc05 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -42,7 +42,7 @@ pub enum Expr { Lit(Literal), /// use Use Use(Use), - /// `(let | const | static) Pat::NoTopAlt (= expr (else expr)?)?` | + /// `let Pat::NoTopAlt (= expr (else expr)?)?` | /// `(fn | mod | impl) Pat::Fn Expr` Bind(Box>), /// Expr { (Ident (: Expr)?),* } @@ -169,6 +169,8 @@ pub enum Use { Glob, /// Identifier Name(String), + /// Identifier as Identifier + Alias(String, String), /// Identifier :: Use Path(String, Box), /// { Use, * } diff --git a/src/ast/display.rs b/src/ast/display.rs index 3cd3364..3d3b2ec 100644 --- a/src/ast/display.rs +++ b/src/ast/display.rs @@ -158,6 +158,7 @@ impl Display for Use { match self { Self::Glob => "*".fmt(f), Self::Name(name) => name.fmt(f), + Self::Alias(name, alias) => write!(f, "{name} as {alias}"), Self::Path(segment, rest) => write!(f, "{segment}::{rest}"), Self::Tree(items) => match items.len() { 0 => "{}".fmt(f), diff --git a/src/ast/fold.rs b/src/ast/fold.rs index 2391823..c00860c 100644 --- a/src/ast/fold.rs +++ b/src/ast/fold.rs @@ -131,6 +131,7 @@ impl Foldable for Use { Ok(match self { Self::Glob => Self::Glob, Self::Name(name) => Self::Name(name), + Self::Alias(name, alias) => Self::Alias(name, alias), Self::Path(name, rest) => Self::Path(name, rest.fold_in(folder)?), Self::Tree(items) => Self::Tree(items.fold_in(folder)?), }) diff --git a/src/ast/visit.rs b/src/ast/visit.rs index 016df6b..9f1b98c 100644 --- a/src/ast/visit.rs +++ b/src/ast/visit.rs @@ -89,6 +89,10 @@ impl<'a> Walk<'a> for Use { match self { Self::Glob => Ok(()), Self::Name(name) => name.visit_in(v), + Self::Alias(name, alias) => { + name.visit_in(v)?; + alias.visit_in(v) + } Self::Path(name, rest) => { name.visit_in(v)?; rest.visit_in(v) diff --git a/src/parser.rs b/src/parser.rs index 986f763..bc8d059 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -235,8 +235,17 @@ impl<'t> Parse<'t> for Use { TKind::Star => p.then(Use::Glob), TKind::Identifier => { let name = tok.lexeme.string().expect("should have String"); - match p.next_if(TKind::ColonColon).allow_eof()? { - Some(Ok(_)) => Use::Path(name, p.parse(())?), + match p.peek().map(Token::kind).allow_eof()? { + Some(TKind::ColonColon) => Use::Path(name, p.consume().parse(())?), + Some(TKind::As) => Use::Alias( + name, + p.consume() + .next_if(TKind::Identifier)? + .map_err(|e| ParseError::Expected(TKind::Identifier, e, p.span()))? + .lexeme + .string() + .expect("Identifier should have string"), + ), _ => Use::Name(name), } }