Skip to content

Commit 6e3e0a8

Browse files
committed
auto merge of #15834 : Kimundi/rust/moved_syntax_env, r=cmr
- Made custom syntax extensions capable of expanding custom macros by moving `SyntaxEnv` into `ExtCtx` - Added convenience method on `ExtCtx` for getting a macro expander. - Made a few things private to force only a single way to use them (through `ExtCtx`) - Removed some ancient commented-out code Closes #14946
2 parents aa0e35b + cef4378 commit 6e3e0a8

File tree

4 files changed

+254
-227
lines changed

4 files changed

+254
-227
lines changed

src/libregex_macros/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use syntax::ext::build::AstBuilder;
3434
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
3535
use syntax::parse::token;
3636
use syntax::print::pprust;
37+
use syntax::fold::Folder;
3738

3839
use rustc::plugin::Registry;
3940

@@ -615,7 +616,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
615616
/// Otherwise, logs an error with cx.span_err and returns None.
616617
fn parse(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Option<String> {
617618
let mut parser = cx.new_parser_from_tts(tts);
618-
let entry = cx.expand_expr(parser.parse_expr());
619+
let entry = cx.expander().fold_expr(parser.parse_expr());
619620
let regex = match entry.node {
620621
ast::ExprLit(lit) => {
621622
match lit.node {

src/libsyntax/ext/base.rs

+30-31
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ use parse::token;
2020
use parse::token::{InternedString, intern, str_to_ident};
2121
use util::small_vector::SmallVector;
2222
use ext::mtwt;
23+
use fold::Folder;
2324

2425
use std::collections::HashMap;
2526
use std::gc::{Gc, GC};
27+
use std::rc::Rc;
2628

2729
// new-style macro! tt code:
2830
//
@@ -104,9 +106,9 @@ pub type IdentMacroExpanderFn =
104106
/// just into the compiler's internal macro table, for `make_def`).
105107
pub trait MacResult {
106108
/// Define a new macro.
107-
// this particular flavor should go away; the idea that a macro might
108-
// expand into either a macro definition or an expression, depending
109-
// on what the context wants, is kind of silly.
109+
// this should go away; the idea that a macro might expand into
110+
// either a macro definition or an expression, depending on what
111+
// the context wants, is kind of silly.
110112
fn make_def(&self) -> Option<MacroDef> {
111113
None
112114
}
@@ -314,7 +316,7 @@ impl BlockInfo {
314316

315317
/// The base map of methods for expanding syntax extension
316318
/// AST nodes into full ASTs
317-
pub fn syntax_expander_table() -> SyntaxEnv {
319+
fn initial_syntax_expander_table() -> SyntaxEnv {
318320
// utility function to simplify creating NormalTT syntax extensions
319321
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
320322
NormalTT(box BasicMacroExpander {
@@ -431,7 +433,9 @@ pub struct ExtCtxt<'a> {
431433

432434
pub mod_path: Vec<ast::Ident> ,
433435
pub trace_mac: bool,
434-
pub exported_macros: Vec<Gc<ast::Item>>
436+
pub exported_macros: Vec<Gc<ast::Item>>,
437+
438+
pub syntax_env: SyntaxEnv,
435439
}
436440

437441
impl<'a> ExtCtxt<'a> {
@@ -445,22 +449,18 @@ impl<'a> ExtCtxt<'a> {
445449
ecfg: ecfg,
446450
trace_mac: false,
447451
exported_macros: Vec::new(),
452+
syntax_env: initial_syntax_expander_table(),
448453
}
449454
}
450455

451-
pub fn expand_expr(&mut self, mut e: Gc<ast::Expr>) -> Gc<ast::Expr> {
452-
loop {
453-
match e.node {
454-
ast::ExprMac(..) => {
455-
let mut expander = expand::MacroExpander {
456-
extsbox: syntax_expander_table(),
457-
cx: self,
458-
};
459-
e = expand::expand_expr(e, &mut expander);
460-
}
461-
_ => return e
462-
}
463-
}
456+
#[deprecated = "Replaced with `expander().fold_expr()`"]
457+
pub fn expand_expr(&mut self, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
458+
self.expander().fold_expr(e)
459+
}
460+
461+
/// Returns a `Folder` for deeply expanding all macros in a AST node.
462+
pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
463+
expand::MacroExpander { cx: self }
464464
}
465465

466466
pub fn new_parser_from_tts(&self, tts: &[ast::TokenTree])
@@ -570,7 +570,7 @@ impl<'a> ExtCtxt<'a> {
570570
pub fn expr_to_string(cx: &mut ExtCtxt, expr: Gc<ast::Expr>, err_msg: &str)
571571
-> Option<(InternedString, ast::StrStyle)> {
572572
// we want to be able to handle e.g. concat("foo", "bar")
573-
let expr = cx.expand_expr(expr);
573+
let expr = cx.expander().fold_expr(expr);
574574
match expr.node {
575575
ast::ExprLit(l) => match l.node {
576576
ast::LitStr(ref s, style) => return Some(((*s).clone(), style)),
@@ -627,7 +627,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
627627
let mut p = cx.new_parser_from_tts(tts);
628628
let mut es = Vec::new();
629629
while p.token != token::EOF {
630-
es.push(cx.expand_expr(p.parse_expr()));
630+
es.push(cx.expander().fold_expr(p.parse_expr()));
631631
if p.eat(&token::COMMA) {
632632
continue;
633633
}
@@ -642,10 +642,13 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
642642
/// In order to have some notion of scoping for macros,
643643
/// we want to implement the notion of a transformation
644644
/// environment.
645-
645+
///
646646
/// This environment maps Names to SyntaxExtensions.
647+
pub struct SyntaxEnv {
648+
chain: Vec<MapChainFrame> ,
649+
}
647650

648-
//impl question: how to implement it? Initially, the
651+
// impl question: how to implement it? Initially, the
649652
// env will contain only macros, so it might be painful
650653
// to add an empty frame for every context. Let's just
651654
// get it working, first....
@@ -657,15 +660,11 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
657660

658661
struct MapChainFrame {
659662
info: BlockInfo,
660-
map: HashMap<Name, SyntaxExtension>,
661-
}
662-
663-
pub struct SyntaxEnv {
664-
chain: Vec<MapChainFrame> ,
663+
map: HashMap<Name, Rc<SyntaxExtension>>,
665664
}
666665

667666
impl SyntaxEnv {
668-
pub fn new() -> SyntaxEnv {
667+
fn new() -> SyntaxEnv {
669668
let mut map = SyntaxEnv { chain: Vec::new() };
670669
map.push_frame();
671670
map
@@ -692,18 +691,18 @@ impl SyntaxEnv {
692691
unreachable!()
693692
}
694693

695-
pub fn find<'a>(&'a self, k: &Name) -> Option<&'a SyntaxExtension> {
694+
pub fn find(&self, k: &Name) -> Option<Rc<SyntaxExtension>> {
696695
for frame in self.chain.iter().rev() {
697696
match frame.map.find(k) {
698-
Some(v) => return Some(v),
697+
Some(v) => return Some(v.clone()),
699698
None => {}
700699
}
701700
}
702701
None
703702
}
704703

705704
pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
706-
self.find_escape_frame().map.insert(k, v);
705+
self.find_escape_frame().map.insert(k, Rc::new(v));
707706
}
708707

709708
pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {

0 commit comments

Comments
 (0)