From 6702fe349c117ffe2fa197f32265a1dbe9f3c0f8 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 25 Oct 2022 10:05:31 +0800 Subject: [PATCH] Add index to Share statement. --- src/ast/stmt.rs | 5 ++++- src/eval/expr.rs | 2 +- src/eval/stmt.rs | 11 ++++++++--- src/parser.rs | 5 ++++- src/types/scope.rs | 16 ++++++++-------- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 6b15061c..80ed1b36 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -614,7 +614,10 @@ pub enum Stmt { /// This variant does not map to any language structure. It is currently only used only to /// convert a normal variable into a shared variable when the variable is _captured_ by a closure. #[cfg(not(feature = "no_closure"))] - Share(crate::ImmutableString, Position), + Share( + Box<(crate::ImmutableString, Option)>, + Position, + ), } impl Default for Stmt { diff --git a/src/eval/expr.rs b/src/eval/expr.rs index 6480da35..5afd07d9 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -188,7 +188,7 @@ impl Engine { // Find the variable in the scope let var_name = expr.get_variable_name(true).expect("`Expr::Variable`"); - match scope.get_index(var_name) { + match scope.search(var_name) { Some(index) => index, None => { return match self.global_modules.iter().find_map(|m| m.get_var(var_name)) { diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 18f5465f..770d4174 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -959,7 +959,7 @@ impl Engine { Stmt::Export(x, ..) => { let (Ident { name, pos, .. }, Ident { name: alias, .. }) = &**x; // Mark scope variables as public - if let Some(index) = scope.get_index(name) { + if let Some(index) = scope.search(name) { let alias = if alias.is_empty() { name } else { alias }.clone(); scope.add_alias_by_index(index, alias.into()); Ok(Dynamic::UNIT) @@ -970,8 +970,13 @@ impl Engine { // Share statement #[cfg(not(feature = "no_closure"))] - Stmt::Share(name, pos) => { - if let Some(index) = scope.get_index(name) { + Stmt::Share(x, pos) => { + let (name, index) = &**x; + + if let Some(index) = index + .map(|n| scope.len() - n.get()) + .or_else(|| scope.search(name)) + { let val = scope.get_mut_by_index(index); if !val.is_shared() { diff --git a/src/parser.rs b/src/parser.rs index cb002908..e2bcb181 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3711,7 +3711,10 @@ impl Engine { statements.extend( externals .into_iter() - .map(|crate::ast::Ident { name, pos }| Stmt::Share(name, pos)), + .map(|crate::ast::Ident { name, pos }| { + let (index, _) = parent.access_var(&name, lib, pos); + Stmt::Share((name, index).into(), pos) + }), ); statements.push(Stmt::Expr(expr.into())); Expr::Stmt(crate::ast::StmtBlock::new(statements, pos, Position::NONE).into()) diff --git a/src/types/scope.rs b/src/types/scope.rs index 05d566a8..435042e8 100644 --- a/src/types/scope.rs +++ b/src/types/scope.rs @@ -407,7 +407,7 @@ impl Scope<'_> { /// Find an entry in the [`Scope`], starting from the last. #[inline] #[must_use] - pub(crate) fn get_index(&self, name: &str) -> Option { + pub(crate) fn search(&self, name: &str) -> Option { let len = self.len(); self.names @@ -467,7 +467,7 @@ impl Scope<'_> { #[inline] #[must_use] pub fn is_constant(&self, name: &str) -> Option { - self.get_index(name) + self.search(name) .map(|n| match self.values[n].access_mode() { AccessMode::ReadWrite => false, AccessMode::ReadOnly => true, @@ -505,7 +505,7 @@ impl Scope<'_> { value: impl Variant + Clone, ) -> &mut Self { match self - .get_index(name.as_ref()) + .search(name.as_ref()) .map(|n| (n, self.values[n].access_mode())) { None | Some((.., AccessMode::ReadOnly)) => { @@ -547,7 +547,7 @@ impl Scope<'_> { value: impl Variant + Clone, ) -> &mut Self { match self - .get_index(name.as_ref()) + .search(name.as_ref()) .map(|n| (n, self.values[n].access_mode())) { None => { @@ -583,7 +583,7 @@ impl Scope<'_> { #[inline(always)] #[must_use] pub fn get(&self, name: &str) -> Option<&Dynamic> { - self.get_index(name).map(|index| &self.values[index]) + self.search(name).map(|index| &self.values[index]) } /// Remove the last entry in the [`Scope`] by the specified name and return its value. /// @@ -614,7 +614,7 @@ impl Scope<'_> { #[inline(always)] #[must_use] pub fn remove(&mut self, name: &str) -> Option { - self.get_index(name).and_then(|index| { + self.search(name).and_then(|index| { self.names.remove(index); self.aliases.remove(index); self.values.remove(index).try_cast() @@ -646,7 +646,7 @@ impl Scope<'_> { #[inline] #[must_use] pub fn get_mut(&mut self, name: &str) -> Option<&mut Dynamic> { - self.get_index(name) + self.search(name) .and_then(move |n| match self.values[n].access_mode() { AccessMode::ReadWrite => Some(self.get_mut_by_index(n)), AccessMode::ReadOnly => None, @@ -692,7 +692,7 @@ impl Scope<'_> { name: impl AsRef + Into, alias: impl Into, ) { - if let Some(index) = self.get_index(name.as_ref()) { + if let Some(index) = self.search(name.as_ref()) { let alias = match alias.into() { x if x.is_empty() => name.into(), x => x,