From 89426f8b3a194d7cd3d3137688d8080b229d8364 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 9 Mar 2022 09:25:32 +0800 Subject: [PATCH] Add Scope::set_alias. --- CHANGELOG.md | 1 + src/eval/stmt.rs | 8 +++----- src/types/scope.rs | 26 +++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eeea89c0..0f9eac99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Enhancements * The `event_handler_map` example is enhanced to prevent shadowing of the state object map. * Separation of constants in function calls is removed as its performance benefit is dubious. * A function `sleep` is added to block the current thread by a specified number of seconds. +* `Scope::set_alias` is added to export a variable under a particular alias name. Version 1.5.0 diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 46a1b29c..1a1244fd 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -905,7 +905,7 @@ impl Engine { #[cfg(not(feature = "no_module"))] if let Some(alias) = _alias { - scope.add_entry_alias(scope.len() - 1, alias.name.clone()); + scope.add_alias_by_index(scope.len() - 1, alias.name.clone()); } Ok(Dynamic::UNIT) @@ -989,10 +989,8 @@ impl Engine { let (Ident { name, pos, .. }, alias) = x.as_ref(); // Mark scope variables as public if let Some((index, ..)) = scope.get_index(name) { - scope.add_entry_alias( - index, - if alias.is_empty() { name } else { alias }.clone(), - ); + let alias = if alias.is_empty() { name } else { alias }.clone(); + scope.add_alias_by_index(index, alias); Ok(Dynamic::UNIT) } else { Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into()) diff --git a/src/types/scope.rs b/src/types/scope.rs index 199940e9..bae3f2a8 100644 --- a/src/types/scope.rs +++ b/src/types/scope.rs @@ -514,13 +514,37 @@ impl Scope<'_> { /// Panics if the index is out of bounds. #[cfg(not(feature = "no_module"))] #[inline] - pub(crate) fn add_entry_alias(&mut self, index: usize, alias: Identifier) -> &mut Self { + pub(crate) fn add_alias_by_index(&mut self, index: usize, alias: Identifier) -> &mut Self { let aliases = self.aliases.get_mut(index).unwrap(); if aliases.is_empty() || !aliases.contains(&alias) { aliases.push(alias); } self } + /// Add an alias to a variable in the [`Scope`] so that it is exported under that name. + /// This is an advanced API. + /// + /// If the alias is empty, then the variable is exported under its original name. + /// + /// Multiple aliases can be added to any variable. + /// + /// Only the last variable matching the name (and not other shadowed versions) is aliased by + /// this call. + #[cfg(not(feature = "no_module"))] + #[inline] + pub fn set_alias( + &mut self, + name: impl AsRef + Into, + alias: impl Into, + ) { + if let Some((index, ..)) = self.get_index(name.as_ref()) { + let alias = match alias.into() { + x if x.is_empty() => name.into(), + x => x, + }; + self.add_alias_by_index(index, alias); + } + } /// Clone the [`Scope`], keeping only the last instances of each variable name. /// Shadowed variables are omitted in the copy. #[inline]