diff --git a/src/compiler/generator.rs b/src/compiler/generator.rs index b36a52a..cfed3f0 100644 --- a/src/compiler/generator.rs +++ b/src/compiler/generator.rs @@ -1547,11 +1547,11 @@ pub fn reduce(e: &AstNode, ctx: &mut Scope, settings: &CompileSettings) -> Resul ), )), Token::Symbol(name) => Ok(Some( - ctx.resolve_symbol(name) + ctx.resolve_symbol(name, true) .with_context(|| make_ast_error(e))?, )), Token::IndexedSymbol { name, index } => { - let symbol = ctx.resolve_symbol(name)?; + let symbol = ctx.resolve_symbol(name, true)?; if let Expression::ArrayColumn { handle, domain, @@ -1568,7 +1568,7 @@ pub fn reduce(e: &AstNode, ctx: &mut Scope, settings: &CompileSettings) -> Resul let name = handle.as_handle().ith(i.try_into().unwrap()).to_string(); // Resolve it properly this time. Ok(Some( - ctx.resolve_symbol_with_path(&name) + ctx.resolve_symbol_with_path(&name, true) .with_context(|| make_ast_error(e))?, )) } else { @@ -1619,18 +1619,21 @@ pub fn reduce(e: &AstNode, ctx: &mut Scope, settings: &CompileSettings) -> Resul _ => Ok(None), }, Token::DefInterleaving { target, froms } => { - let target_handle = - if let Expression::Column { handle, .. } = ctx.resolve_symbol(&target.name)?.e() { - handle.to_owned() - } else { - unreachable!() - }; + let target_handle = if let Expression::Column { handle, .. } = + ctx.resolve_symbol(&target.name, true)?.e() + { + handle.to_owned() + } else { + unreachable!() + }; let mut from_handles = Vec::new(); for from in froms { match &from.class { Token::Symbol(name) => { - if let Expression::Column { handle, .. } = ctx.resolve_symbol(name)?.e() { + if let Expression::Column { handle, .. } = + ctx.resolve_symbol(name, true)?.e() + { from_handles.push(handle.clone()); } else { bail!("{} is not a column", name.white().bold()); @@ -1638,7 +1641,7 @@ pub fn reduce(e: &AstNode, ctx: &mut Scope, settings: &CompileSettings) -> Resul } Token::IndexedSymbol { name, index } => { if let Expression::ArrayColumn { handle, domain, .. } = - ctx.resolve_symbol(name)?.e() + ctx.resolve_symbol(name, true)?.e() { let index_usize = reduce(index, ctx, settings)? .and_then(|n| n.pure_eval().ok()) @@ -1875,7 +1878,7 @@ pub(crate) fn reduce_toplevel( // TODO is this needed? to.iter() - .map(|f| ctx.resolve_symbol(&f.name)) + .map(|f| ctx.resolve_symbol(&f.name, true)) .collect::, errors::symbols::Error>>() .with_context(|| anyhow!("while defining permutation"))?; let suffix = hash_strings(froms.iter().map(|f| f.as_handle().name.clone())); diff --git a/src/compiler/parser/definitions.rs b/src/compiler/parser/definitions.rs index c305265..d8d889a 100644 --- a/src/compiler/parser/definitions.rs +++ b/src/compiler/parser/definitions.rs @@ -220,8 +220,11 @@ fn reduce(e: &AstNode, ctx: &mut Scope, settings: &CompileSettings) -> Result<() ) } Token::DefAlias(from, to) => { + // NOTE: false here (for used) is needed to prevent this + // symbol resolution from marking the column being aliased + // as used. let _ = ctx - .resolve_symbol(to) + .resolve_symbol(to, false) .with_context(|| anyhow!("while defining alias `{}`", from))?; ctx.insert_alias(from, to) diff --git a/src/compiler/tables.rs b/src/compiler/tables.rs index ef1842e..c23b78b 100644 --- a/src/compiler/tables.rs +++ b/src/compiler/tables.rs @@ -488,13 +488,13 @@ impl Scope { Ok(()) } - pub fn resolve_symbol(&mut self, name: &str) -> Result { + pub fn resolve_symbol(&mut self, name: &str, used: bool) -> Result { let module = self.module(); let global = data!(self).global; if name.contains('.') { if global { - self.resolve_symbol_with_path(name) + self.resolve_symbol_with_path(name, used) } else { Err(symbols::Error::NotAGlobalScope( name.split('.').next().unwrap().to_owned(), @@ -513,6 +513,7 @@ impl Scope { &mut self.tree.borrow_mut(), name, perspective, + used, ) .map_err(|e| match e { symbols::Error::SymbolNotFound(s, _, _) => { @@ -531,14 +532,19 @@ impl Scope { &mut HashSet::new(), false, false, + used, ) .map_err(|_| symbols::Error::SymbolNotFound(name.to_owned(), module, None)) } } - pub fn resolve_symbol_with_path(&mut self, name: &str) -> Result { + pub fn resolve_symbol_with_path( + &mut self, + name: &str, + used: bool, + ) -> Result { let components = name.split('.').collect::>(); - self.root()._resolve_symbol_with_path(&components) + self.root()._resolve_symbol_with_path(&components, used) } fn _resolve_symbol( @@ -548,6 +554,7 @@ impl Scope { ax: &mut HashSet, absolute_path: bool, pure: bool, + used: bool, ) -> Result { if ax.contains(name) { Err(symbols::Error::CircularDefinition(name.to_string())) @@ -556,13 +563,15 @@ impl Scope { match tree[n].unwrap_data_mut().symbols.get_mut(name) { Some(Symbol::Alias(target)) => { let target = target.to_owned(); - Self::_resolve_symbol(n, tree, &target, ax, absolute_path, pure) + Self::_resolve_symbol(n, tree, &target, ax, absolute_path, pure, used) } Some(Symbol::Final(exp, ref mut visited)) => { if pure && !matches!(exp.e(), Expression::Const(..)) { Err(symbols::Error::UnavailableInPureContext(exp.to_string())) } else { - *visited = true; + if used { + *visited = true; + } Result::Ok(exp.clone()) } } @@ -580,6 +589,7 @@ impl Scope { &mut HashSet::new(), false, tree[n].unwrap_data().closed || pure, + used, ) }, ) @@ -594,6 +604,7 @@ impl Scope { tree: &mut SymbolTableTree, name: &str, perspective: &str, + used: bool, ) -> Result { match tree.find_child(n, |o| { o.perspective @@ -601,24 +612,30 @@ impl Scope { .map(|p| p == perspective) .unwrap_or(false) }) { - Some(o) => Self::_resolve_symbol(o, tree, name, &mut HashSet::new(), true, false), + Some(o) => Self::_resolve_symbol(o, tree, name, &mut HashSet::new(), true, false, used), None => tree.parent(n).map_or( Err(symbols::Error::PerspectiveNotFound( perspective.into(), tree[n].data().unwrap().module.clone(), )), - |parent| Self::_resolve_symbol_in_perspective(parent, tree, name, perspective), + |parent| { + Self::_resolve_symbol_in_perspective(parent, tree, name, perspective, used) + }, ), } } - fn _resolve_symbol_with_path(&mut self, path: &[&str]) -> Result { + fn _resolve_symbol_with_path( + &mut self, + path: &[&str], + used: bool, + ) -> Result { if path.len() == 1 { - self.resolve_symbol(path[0]) + self.resolve_symbol(path[0], used) } else { for c in self.children() { if data!(c).name == path[0] { - return self.at(c.id)._resolve_symbol_with_path(&path[1..]); + return self.at(c.id)._resolve_symbol_with_path(&path[1..], used); } } return Err(symbols::Error::ModuleNotFound( @@ -708,12 +725,6 @@ impl Scope { } } - // pub fn insert_used_symbol(&mut self, name: &str, e: Node) -> Result<()> { - // self.insert_symbol(name, e)?; - // let _ = self.resolve_symbol(name).unwrap(); - // Ok(()) - // } - pub fn insert_function(&mut self, name: &str, f: Function) -> Result<()> { let my_name = data!(self).name.to_owned(); // User-defined function can be polymorphic on their input arguments and