Remove EntryRef from Scope.
This commit is contained in:
parent
d043300ae2
commit
d3a97dc86b
@ -7,7 +7,7 @@ use crate::optimize::OptimizationLevel;
|
|||||||
use crate::packages::{CorePackage, Package, PackageLibrary, StandardPackage};
|
use crate::packages::{CorePackage, Package, PackageLibrary, StandardPackage};
|
||||||
use crate::parser::{Expr, FnDef, ReturnType, Stmt};
|
use crate::parser::{Expr, FnDef, ReturnType, Stmt};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::scope::{EntryRef as ScopeSource, EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
@ -439,11 +439,11 @@ fn search_scope<'a>(
|
|||||||
name: &str,
|
name: &str,
|
||||||
begin: Position,
|
begin: Position,
|
||||||
) -> Result<(&'a mut Dynamic, ScopeEntryType), Box<EvalAltResult>> {
|
) -> Result<(&'a mut Dynamic, ScopeEntryType), Box<EvalAltResult>> {
|
||||||
let ScopeSource { typ, index, .. } = scope
|
let (index, typ) = scope
|
||||||
.get(name)
|
.get(name)
|
||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(name.into(), begin)))?;
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(name.into(), begin)))?;
|
||||||
|
|
||||||
Ok((scope.get_mut(ScopeSource { name, typ, index }), typ))
|
Ok((scope.get_mut(index), typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
@ -517,9 +517,6 @@ impl Engine {
|
|||||||
return Err(Box::new(EvalAltResult::ErrorStackOverflow(pos)));
|
return Err(Box::new(EvalAltResult::ErrorStackOverflow(pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "no_function")]
|
|
||||||
const fn_lib: &FunctionsLib = None;
|
|
||||||
|
|
||||||
// First search in script-defined functions (can override built-in)
|
// First search in script-defined functions (can override built-in)
|
||||||
if let Some(fn_def) = fn_lib.get_function(fn_name, args.len()) {
|
if let Some(fn_def) = fn_lib.get_function(fn_name, args.len()) {
|
||||||
return self.call_fn_from_lib(scope, fn_lib, fn_def, args, pos, level);
|
return self.call_fn_from_lib(scope, fn_lib, fn_def, args, pos, level);
|
||||||
@ -1152,27 +1149,15 @@ impl Engine {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(
|
Some((index, ScopeEntryType::Normal)) => {
|
||||||
entry
|
|
||||||
@
|
|
||||||
ScopeSource {
|
|
||||||
typ: ScopeEntryType::Normal,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
// Avoid referencing scope which is used below as mut
|
// Avoid referencing scope which is used below as mut
|
||||||
let entry = ScopeSource { name, ..entry };
|
*scope.get_mut(index) = rhs_val.clone();
|
||||||
*scope.get_mut(entry) = rhs_val.clone();
|
|
||||||
Ok(rhs_val)
|
Ok(rhs_val)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(ScopeSource {
|
Some((_, ScopeEntryType::Constant)) => Err(Box::new(
|
||||||
typ: ScopeEntryType::Constant,
|
EvalAltResult::ErrorAssignmentToConstant(name.to_string(), *op_pos),
|
||||||
..
|
)),
|
||||||
}) => Err(Box::new(EvalAltResult::ErrorAssignmentToConstant(
|
|
||||||
name.to_string(),
|
|
||||||
*op_pos,
|
|
||||||
))),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// idx_lhs[idx_expr] = rhs
|
// idx_lhs[idx_expr] = rhs
|
||||||
@ -1402,15 +1387,10 @@ impl Engine {
|
|||||||
}) {
|
}) {
|
||||||
// Add the loop variable
|
// Add the loop variable
|
||||||
scope.push(name.clone(), ());
|
scope.push(name.clone(), ());
|
||||||
|
let index = scope.len() - 1;
|
||||||
let entry = ScopeSource {
|
|
||||||
name,
|
|
||||||
index: scope.len() - 1,
|
|
||||||
typ: ScopeEntryType::Normal,
|
|
||||||
};
|
|
||||||
|
|
||||||
for a in iter_fn(arr) {
|
for a in iter_fn(arr) {
|
||||||
*scope.get_mut(entry) = a;
|
*scope.get_mut(index) = a;
|
||||||
|
|
||||||
match self.eval_stmt(scope, fn_lib, body, level) {
|
match self.eval_stmt(scope, fn_lib, body, level) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
|
35
src/scope.rs
35
src/scope.rs
@ -28,14 +28,6 @@ pub struct Entry<'a> {
|
|||||||
pub expr: Option<Box<Expr>>,
|
pub expr: Option<Box<Expr>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about a particular entry in the Scope.
|
|
||||||
#[derive(Debug, Hash, Copy, Clone)]
|
|
||||||
pub(crate) struct EntryRef<'a> {
|
|
||||||
pub name: &'a str,
|
|
||||||
pub index: usize,
|
|
||||||
pub typ: EntryType,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type containing information about the current scope.
|
/// A type containing information about the current scope.
|
||||||
/// Useful for keeping state between `Engine` evaluation runs.
|
/// Useful for keeping state between `Engine` evaluation runs.
|
||||||
///
|
///
|
||||||
@ -291,18 +283,14 @@ impl<'a> Scope<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Find an entry in the Scope, starting from the last.
|
/// Find an entry in the Scope, starting from the last.
|
||||||
pub(crate) fn get(&self, name: &str) -> Option<EntryRef> {
|
pub(crate) fn get(&self, name: &str) -> Option<(usize, EntryType)> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev() // Always search a Scope in reverse order
|
.rev() // Always search a Scope in reverse order
|
||||||
.find_map(|(index, Entry { name: key, typ, .. })| {
|
.find_map(|(index, Entry { name: key, typ, .. })| {
|
||||||
if name == key {
|
if name == key {
|
||||||
Some(EntryRef {
|
Some((index, *typ))
|
||||||
name: key,
|
|
||||||
index,
|
|
||||||
typ: *typ,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -352,30 +340,23 @@ impl<'a> Scope<'a> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn set_value<T: Variant + Clone>(&mut self, name: &'a str, value: T) {
|
pub fn set_value<T: Variant + Clone>(&mut self, name: &'a str, value: T) {
|
||||||
match self.get(name) {
|
match self.get(name) {
|
||||||
Some(EntryRef {
|
Some((_, EntryType::Constant)) => panic!("variable {} is constant", name),
|
||||||
typ: EntryType::Constant,
|
Some((index, EntryType::Normal)) => {
|
||||||
..
|
self.0.get_mut(index).unwrap().value = Dynamic::from(value)
|
||||||
}) => panic!("variable {} is constant", name),
|
}
|
||||||
Some(EntryRef {
|
|
||||||
index,
|
|
||||||
typ: EntryType::Normal,
|
|
||||||
..
|
|
||||||
}) => 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_mut(&mut self, key: EntryRef) -> &mut Dynamic {
|
pub(crate) fn get_mut(&mut self, index: usize) -> &mut Dynamic {
|
||||||
let entry = self.0.get_mut(key.index).expect("invalid index in Scope");
|
let entry = self.0.get_mut(index).expect("invalid index in Scope");
|
||||||
assert_eq!(entry.typ, key.typ, "entry type not matched");
|
|
||||||
|
|
||||||
// assert_ne!(
|
// assert_ne!(
|
||||||
// entry.typ,
|
// entry.typ,
|
||||||
// EntryType::Constant,
|
// EntryType::Constant,
|
||||||
// "get mut of constant entry"
|
// "get mut of constant entry"
|
||||||
// );
|
// );
|
||||||
assert_eq!(entry.name, key.name, "incorrect key at Scope entry");
|
|
||||||
|
|
||||||
&mut entry.value
|
&mut entry.value
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user