diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-10-11 03:41:48 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-10-11 03:41:48 +0000 |
| commit | 31e0e12e6986ca369e9e27fa713c40b174c4d573 (patch) | |
| tree | 058816a4575cbfffab8d139e77aab7504fff9c0c /src/libsyntax/ext | |
| parent | d5281ef681195828173d4fe516b653ba0f9e9fbc (diff) | |
| download | rust-31e0e12e6986ca369e9e27fa713c40b174c4d573.tar.gz rust-31e0e12e6986ca369e9e27fa713c40b174c4d573.zip | |
Add support for undetermined macro invocations.
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 29 |
2 files changed, 37 insertions, 6 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 923d5d05439..f7c88073c9d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -522,10 +522,17 @@ pub trait Resolver { fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>); fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>; - fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option<Rc<SyntaxExtension>>; + fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool) + -> Result<Rc<SyntaxExtension>, Determinacy>; fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModifier>>; } +#[derive(Copy, Clone, Debug)] +pub enum Determinacy { + Determined, + Undetermined, +} + pub struct DummyResolver; impl Resolver for DummyResolver { @@ -539,8 +546,9 @@ impl Resolver for DummyResolver { fn find_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None } fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option<Rc<MultiItemModifier>> { None } - fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation) -> Option<Rc<SyntaxExtension>> { - None + fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation, _force: bool) + -> Result<Rc<SyntaxExtension>, Determinacy> { + Err(Determinacy::Determined) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index ab7ffe36673..363ceebf0f4 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -225,13 +225,36 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invocations.reverse(); let mut expansions = Vec::new(); - while let Some(invoc) = invocations.pop() { + let mut undetermined_invocations = Vec::new(); + let (mut progress, mut force) = (false, !self.monotonic); + loop { + let invoc = if let Some(invoc) = invocations.pop() { + invoc + } else if undetermined_invocations.is_empty() { + break + } else { + invocations = mem::replace(&mut undetermined_invocations, Vec::new()); + force = !mem::replace(&mut progress, false); + continue + }; + + let scope = + if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; + let ext = match self.cx.resolver.resolve_invoc(scope, &invoc, force) { + Ok(ext) => Some(ext), + Err(Determinacy::Determined) => None, + Err(Determinacy::Undetermined) => { + undetermined_invocations.push(invoc); + continue + } + }; + + progress = true; let ExpansionData { depth, mark, .. } = invoc.expansion_data; self.cx.current_expansion = invoc.expansion_data.clone(); - let scope = if self.monotonic { mark } else { orig_expansion_data.mark }; self.cx.current_expansion.mark = scope; - let expansion = match self.cx.resolver.resolve_invoc(scope, &invoc) { + let expansion = match ext { Some(ext) => self.expand_invoc(invoc, ext), None => invoc.expansion_kind.dummy(invoc.span()), }; |
