Remove RefCell in Scope.

This commit is contained in:
Stephen Chung 2020-04-27 09:36:31 +08:00
parent ce121ed6af
commit 07c5abcc02
2 changed files with 15 additions and 31 deletions

View File

@ -13,7 +13,6 @@ use crate::token::Position;
use crate::stdlib::{ use crate::stdlib::{
any::TypeId, any::TypeId,
boxed::Box, boxed::Box,
cell::RefCell,
collections::HashMap, collections::HashMap,
format, format,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
@ -80,8 +79,6 @@ const FUNCTIONS_COUNT: usize = 256;
enum Target<'a> { enum Target<'a> {
/// The target is a mutable reference to a `Dynamic` value somewhere. /// The target is a mutable reference to a `Dynamic` value somewhere.
Ref(&'a mut Dynamic), Ref(&'a mut Dynamic),
/// The target is a variable stored in the current `Scope`.
Scope(&'a RefCell<Dynamic>),
/// The target is a temporary `Dynamic` value (i.e. the mutation can cause no side effects). /// The target is a temporary `Dynamic` value (i.e. the mutation can cause no side effects).
Value(Box<Dynamic>), Value(Box<Dynamic>),
/// The target is a character inside a String. /// The target is a character inside a String.
@ -93,7 +90,6 @@ impl Target<'_> {
pub fn into_dynamic(self) -> Dynamic { pub fn into_dynamic(self) -> Dynamic {
match self { match self {
Target::Ref(r) => r.clone(), Target::Ref(r) => r.clone(),
Target::Scope(r) => r.borrow().clone(),
Target::Value(v) => *v, Target::Value(v) => *v,
Target::StringChar(s) => s.2, Target::StringChar(s) => s.2,
} }
@ -102,7 +98,6 @@ impl Target<'_> {
/// Update the value of the `Target`. /// Update the value of the `Target`.
pub fn set_value(&mut self, new_val: Dynamic, pos: Position) -> Result<(), Box<EvalAltResult>> { pub fn set_value(&mut self, new_val: Dynamic, pos: Position) -> Result<(), Box<EvalAltResult>> {
match self { match self {
Target::Scope(r) => *r.borrow_mut() = new_val,
Target::Ref(r) => **r = new_val, Target::Ref(r) => **r = new_val,
Target::Value(_) => { Target::Value(_) => {
return Err(Box::new(EvalAltResult::ErrorAssignmentToUnknownLHS(pos))) return Err(Box::new(EvalAltResult::ErrorAssignmentToUnknownLHS(pos)))
@ -132,11 +127,6 @@ impl Target<'_> {
} }
} }
impl<'a> From<&'a RefCell<Dynamic>> for Target<'a> {
fn from(value: &'a RefCell<Dynamic>) -> Self {
Self::Scope(value)
}
}
impl<'a> From<&'a mut Dynamic> for Target<'a> { impl<'a> From<&'a mut Dynamic> for Target<'a> {
fn from(value: &'a mut Dynamic) -> Self { fn from(value: &'a mut Dynamic) -> Self {
Self::Ref(value) Self::Ref(value)
@ -395,15 +385,15 @@ fn default_print(s: &str) {
/// Search for a variable within the scope, returning its value and index inside the Scope /// Search for a variable within the scope, returning its value and index inside the Scope
fn search_scope<'a>( fn search_scope<'a>(
scope: &'a Scope, scope: &'a mut Scope,
id: &str, id: &str,
begin: Position, begin: Position,
) -> Result<(&'a RefCell<Dynamic>, ScopeEntryType), Box<EvalAltResult>> { ) -> Result<(&'a mut Dynamic, ScopeEntryType), Box<EvalAltResult>> {
let (entry, _) = scope let (ScopeSource { typ, index, .. }, _) = scope
.get(id) .get(id)
.ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(id.into(), begin)))?; .ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(id.into(), begin)))?;
Ok((&scope.get_ref(entry), entry.typ)) Ok((scope.get_mut(ScopeSource { name: id, typ, index }), typ))
} }
impl Engine { impl Engine {
@ -717,14 +707,8 @@ impl Engine {
level: usize, level: usize,
mut new_val: Option<Dynamic>, mut new_val: Option<Dynamic>,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> { ) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
// Store a copy of the RefMut<Dynamic> from `borrow_mut` since it is a temporary value
let mut scope_base = match target {
Target::Scope(r) => Some(r.borrow_mut()),
Target::Ref(_) | Target::Value(_) | Target::StringChar(_) => None,
};
// Get a reference to the mutation target Dynamic // Get a reference to the mutation target Dynamic
let obj = match target { let obj = match target {
Target::Scope(_) => scope_base.as_mut().unwrap().deref_mut(),
Target::Ref(r) => r, Target::Ref(r) => r,
Target::Value(ref mut r) => r.as_mut(), Target::Value(ref mut r) => r.as_mut(),
Target::StringChar(ref mut x) => &mut x.2, Target::StringChar(ref mut x) => &mut x.2,
@ -1157,7 +1141,7 @@ impl Engine {
Expr::StringConstant(s, _) => Ok(s.to_string().into()), Expr::StringConstant(s, _) => Ok(s.to_string().into()),
Expr::CharConstant(c, _) => Ok((*c).into()), Expr::CharConstant(c, _) => Ok((*c).into()),
Expr::Variable(id, pos) => { Expr::Variable(id, pos) => {
search_scope(scope, id, *pos).map(|(v, _)| v.borrow().clone()) search_scope(scope, id, *pos).map(|(v, _)| v.clone())
} }
Expr::Property(_, _) => panic!("unexpected property."), Expr::Property(_, _) => panic!("unexpected property."),
@ -1189,7 +1173,7 @@ impl Engine {
)) => { )) => {
// Avoid referencing scope which is used below as mut // Avoid referencing scope which is used below as mut
let entry = ScopeSource { name, ..entry }; let entry = ScopeSource { name, ..entry };
*scope.get_ref(entry).borrow_mut() = rhs_val.clone(); *scope.get_mut(entry) = rhs_val.clone();
Ok(rhs_val) Ok(rhs_val)
} }
@ -1440,7 +1424,7 @@ impl Engine {
}; };
for a in iter_fn(arr) { for a in iter_fn(arr) {
*scope.get_ref(entry).borrow_mut() = a; *scope.get_mut(entry) = a;
match self.eval_stmt(scope, fn_lib, body, level) { match self.eval_stmt(scope, fn_lib, body, level) {
Ok(_) => (), Ok(_) => (),

View File

@ -4,7 +4,7 @@ use crate::any::{Dynamic, Variant};
use crate::parser::{map_dynamic_to_expr, Expr}; use crate::parser::{map_dynamic_to_expr, Expr};
use crate::token::Position; use crate::token::Position;
use crate::stdlib::{borrow::Cow, cell::RefCell, iter, vec::Vec}; use crate::stdlib::{borrow::Cow, iter, vec::Vec};
/// Type of an entry in the Scope. /// Type of an entry in the Scope.
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)] #[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
@ -23,7 +23,7 @@ pub struct Entry<'a> {
/// Type of the entry. /// Type of the entry.
pub typ: EntryType, pub typ: EntryType,
/// Current value of the entry. /// Current value of the entry.
pub value: RefCell<Dynamic>, pub value: Dynamic,
/// A constant expression if the initial value matches one of the recognized types. /// A constant expression if the initial value matches one of the recognized types.
pub expr: Option<Expr>, pub expr: Option<Expr>,
} }
@ -313,7 +313,7 @@ impl<'a> Scope<'a> {
index, index,
typ: *typ, typ: *typ,
}, },
value.borrow().clone(), value.clone(),
)) ))
} else { } else {
None None
@ -339,7 +339,7 @@ impl<'a> Scope<'a> {
.iter() .iter()
.rev() .rev()
.find(|Entry { name: key, .. }| name == key) .find(|Entry { name: key, .. }| name == key)
.and_then(|Entry { value, .. }| value.borrow().downcast_ref::<T>().cloned()) .and_then(|Entry { value, .. }| value.downcast_ref::<T>().cloned())
} }
/// Update the value of the named entry. /// Update the value of the named entry.
@ -379,14 +379,14 @@ impl<'a> Scope<'a> {
.. ..
}, },
_, _,
)) => *self.0.get_mut(index).unwrap().value.borrow_mut() = Dynamic::from(value), )) => self.0.get_mut(index).unwrap().value = Dynamic::from(value),
None => self.push(name, value), None => self.push(name, value),
} }
} }
/// Get a mutable reference to an entry in the Scope. /// Get a mutable reference to an entry in the Scope.
pub(crate) fn get_ref(&self, key: EntryRef) -> &RefCell<Dynamic> { pub(crate) fn get_mut(&mut self, key: EntryRef) -> &mut Dynamic {
let entry = self.0.get(key.index).expect("invalid index in Scope"); let entry = self.0.get_mut(key.index).expect("invalid index in Scope");
assert_eq!(entry.typ, key.typ, "entry type not matched"); assert_eq!(entry.typ, key.typ, "entry type not matched");
// assert_ne!( // assert_ne!(
@ -396,7 +396,7 @@ impl<'a> Scope<'a> {
// ); // );
assert_eq!(entry.name, key.name, "incorrect key at Scope entry"); assert_eq!(entry.name, key.name, "incorrect key at Scope entry");
&entry.value &mut entry.value
} }
/// Get an iterator to entries in the Scope. /// Get an iterator to entries in the Scope.