Refine data structures
This commit is contained in:
@@ -620,7 +620,7 @@ impl Engine {
|
||||
|
||||
match lhs {
|
||||
// id.??? or id[???]
|
||||
Expr::Variable(.., var_pos, x) => {
|
||||
Expr::Variable(x, .., var_pos) => {
|
||||
#[cfg(feature = "debugging")]
|
||||
self.run_debugger(scope, global, state, lib, this_ptr, lhs, level)?;
|
||||
|
||||
@@ -631,7 +631,7 @@ impl Engine {
|
||||
self.search_namespace(scope, global, state, lib, this_ptr, lhs, level)?;
|
||||
|
||||
let obj_ptr = &mut target;
|
||||
let root = (x.2.as_str(), *var_pos);
|
||||
let root = (x.3.as_str(), *var_pos);
|
||||
|
||||
self.eval_dot_index_chain_helper(
|
||||
global, state, lib, &mut None, obj_ptr, root, expr, rhs, options, idx_values,
|
||||
|
@@ -18,8 +18,10 @@ impl Engine {
|
||||
&self,
|
||||
global: &GlobalRuntimeState,
|
||||
state: &mut EvalState,
|
||||
namespace: &crate::module::Namespace,
|
||||
namespace: &crate::ast::Namespace,
|
||||
) -> Option<crate::Shared<Module>> {
|
||||
assert!(!namespace.is_empty());
|
||||
|
||||
let root = namespace.root();
|
||||
|
||||
// Qualified - check if the root module is directly indexed
|
||||
@@ -53,23 +55,23 @@ impl Engine {
|
||||
level: usize,
|
||||
) -> RhaiResultOf<(Target<'s>, Position)> {
|
||||
match expr {
|
||||
Expr::Variable(Some(_), ..) => {
|
||||
Expr::Variable(_, Some(_), _) => {
|
||||
self.search_scope_only(scope, global, state, lib, this_ptr, expr, level)
|
||||
}
|
||||
Expr::Variable(None, _var_pos, v) => match v.as_ref() {
|
||||
Expr::Variable(v, None, _var_pos) => match v.as_ref() {
|
||||
// Normal variable access
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
(_, None, _) => {
|
||||
(_, ns, ..) if ns.is_empty() => {
|
||||
self.search_scope_only(scope, global, state, lib, this_ptr, expr, level)
|
||||
}
|
||||
#[cfg(feature = "no_module")]
|
||||
(_, (), _) => {
|
||||
(_, (), ..) => {
|
||||
self.search_scope_only(scope, global, state, lib, this_ptr, expr, level)
|
||||
}
|
||||
|
||||
// Qualified variable access
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
(_, Some((namespace, hash_var)), var_name) => {
|
||||
(_, namespace, hash_var, var_name) => {
|
||||
// foo:bar::baz::VARIABLE
|
||||
if let Some(module) = self.search_imports(global, state, namespace) {
|
||||
return if let Some(mut target) = module.get_qualified_var(*hash_var) {
|
||||
@@ -139,7 +141,7 @@ impl Engine {
|
||||
|
||||
let (index, var_pos) = match expr {
|
||||
// Check if the variable is `this`
|
||||
Expr::Variable(None, pos, v) if v.0.is_none() && v.2 == KEYWORD_THIS => {
|
||||
Expr::Variable(v, None, pos) if v.0.is_none() && v.3 == KEYWORD_THIS => {
|
||||
return if let Some(val) = this_ptr {
|
||||
Ok(((*val).into(), *pos))
|
||||
} else {
|
||||
@@ -147,8 +149,8 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
_ if state.always_search_scope => (0, expr.start_position()),
|
||||
Expr::Variable(Some(i), pos, ..) => (i.get() as usize, *pos),
|
||||
Expr::Variable(None, pos, v) => (v.0.map(NonZeroUsize::get).unwrap_or(0), *pos),
|
||||
Expr::Variable(.., Some(i), pos) => (i.get() as usize, *pos),
|
||||
Expr::Variable(v, None, pos) => (v.0.map(NonZeroUsize::get).unwrap_or(0), *pos),
|
||||
_ => unreachable!("Expr::Variable expected but gets {:?}", expr),
|
||||
};
|
||||
|
||||
@@ -216,7 +218,7 @@ impl Engine {
|
||||
} = expr;
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
if let Some(namespace) = namespace.as_ref() {
|
||||
if !namespace.is_empty() {
|
||||
// Qualified function call
|
||||
let hash = hashes.native;
|
||||
|
||||
@@ -280,14 +282,14 @@ impl Engine {
|
||||
// Then variable access.
|
||||
// We shouldn't do this for too many variants because, soon or later, the added comparisons
|
||||
// will cost more than the mis-predicted `match` branch.
|
||||
if let Expr::Variable(index, var_pos, x) = expr {
|
||||
if let Expr::Variable(x, index, var_pos) = expr {
|
||||
#[cfg(feature = "debugging")]
|
||||
self.run_debugger(scope, global, state, lib, this_ptr, expr, level)?;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.inc_operations(&mut global.num_operations, expr.position())?;
|
||||
|
||||
return if index.is_none() && x.0.is_none() && x.2 == KEYWORD_THIS {
|
||||
return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
|
||||
this_ptr
|
||||
.as_deref()
|
||||
.cloned()
|
||||
@@ -396,8 +398,7 @@ impl Engine {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
let mut sizes = (0, 0, 0);
|
||||
|
||||
for (crate::ast::Ident { name, .. }, value_expr) in x.0.iter() {
|
||||
let key = name.as_str();
|
||||
for (key, value_expr) in x.0.iter() {
|
||||
let value = match self
|
||||
.eval_expr(scope, global, state, lib, this_ptr, value_expr, level)
|
||||
{
|
||||
@@ -411,7 +412,7 @@ impl Engine {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
let delta = Self::calc_data_sizes(&value, true);
|
||||
|
||||
*map.get_mut(key).unwrap() = value;
|
||||
*map.get_mut(key.as_str()).unwrap() = value;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if self.has_data_size_limit() {
|
||||
|
@@ -569,7 +569,7 @@ impl Engine {
|
||||
|
||||
// For loop
|
||||
Stmt::For(x, ..) => {
|
||||
let (Ident { name: var_name, .. }, counter, expr, statements) = x.as_ref();
|
||||
let (var_name, counter, expr, statements) = x.as_ref();
|
||||
|
||||
let iter_result = self
|
||||
.eval_expr(scope, global, state, lib, this_ptr, expr, level)
|
||||
@@ -600,14 +600,14 @@ impl Engine {
|
||||
if let Some(func) = func {
|
||||
// Add the loop variables
|
||||
let orig_scope_len = scope.len();
|
||||
let counter_index = if let Some(counter) = counter {
|
||||
let counter_index = if !counter.is_empty() {
|
||||
scope.push(counter.name.clone(), 0 as INT);
|
||||
scope.len() - 1
|
||||
} else {
|
||||
usize::MAX
|
||||
};
|
||||
|
||||
scope.push(var_name.clone(), ());
|
||||
scope.push(var_name.name.clone(), ());
|
||||
let index = scope.len() - 1;
|
||||
|
||||
let mut loop_result = Ok(Dynamic::UNIT);
|
||||
@@ -619,7 +619,7 @@ impl Engine {
|
||||
if x > INT::MAX as usize {
|
||||
loop_result = Err(ERR::ErrorArithmetic(
|
||||
format!("for-loop counter overflow: {}", x),
|
||||
counter.as_ref().expect("`Some`").pos,
|
||||
counter.pos,
|
||||
)
|
||||
.into());
|
||||
break;
|
||||
@@ -707,7 +707,10 @@ impl Engine {
|
||||
Stmt::TryCatch(x, ..) => {
|
||||
let TryCatchBlock {
|
||||
try_block,
|
||||
catch_var,
|
||||
catch_var:
|
||||
Ident {
|
||||
name: catch_var, ..
|
||||
},
|
||||
catch_block,
|
||||
} = x.as_ref();
|
||||
|
||||
@@ -757,9 +760,9 @@ impl Engine {
|
||||
|
||||
let orig_scope_len = scope.len();
|
||||
|
||||
catch_var
|
||||
.as_ref()
|
||||
.map(|Ident { name, .. }| scope.push(name.clone(), err_value));
|
||||
if !catch_var.is_empty() {
|
||||
scope.push(catch_var.clone(), err_value);
|
||||
}
|
||||
|
||||
let result = self.eval_stmt_block(
|
||||
scope,
|
||||
@@ -808,12 +811,12 @@ impl Engine {
|
||||
Stmt::Return(None, .., pos) => Err(ERR::Return(Dynamic::UNIT, *pos).into()),
|
||||
|
||||
// Let/const statement - shadowing disallowed
|
||||
Stmt::Var(x, .., pos) if !self.allow_shadowing() && scope.contains(&x.0.name) => {
|
||||
Err(ERR::ErrorVariableExists(x.0.name.to_string(), *pos).into())
|
||||
Stmt::Var(x, .., pos) if !self.allow_shadowing() && scope.contains(&x.0) => {
|
||||
Err(ERR::ErrorVariableExists(x.0.to_string(), *pos).into())
|
||||
}
|
||||
// Let/const statement
|
||||
Stmt::Var(x, options, pos) => {
|
||||
let (Ident { name: var_name, .. }, expr, index) = x.as_ref();
|
||||
let (var_name, expr, index) = x.as_ref();
|
||||
|
||||
let access = if options.contains(ASTFlags::CONSTANT) {
|
||||
AccessMode::ReadOnly
|
||||
@@ -879,7 +882,7 @@ impl Engine {
|
||||
));
|
||||
}
|
||||
crate::func::locked_write(global.constants.as_ref().unwrap())
|
||||
.insert(var_name.clone(), value.clone());
|
||||
.insert(var_name.name.clone(), value.clone());
|
||||
}
|
||||
|
||||
if export {
|
||||
@@ -897,12 +900,12 @@ impl Engine {
|
||||
value.set_access_mode(access);
|
||||
*scope.get_mut_by_index(scope.len() - index.get()) = value;
|
||||
} else {
|
||||
scope.push_entry(var_name.clone(), access, value);
|
||||
scope.push_entry(var_name.name.clone(), access, value);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
if let Some(alias) = _alias {
|
||||
scope.add_entry_alias(scope.len() - 1, alias.clone());
|
||||
scope.add_entry_alias(scope.len() - 1, alias.name.clone());
|
||||
}
|
||||
|
||||
Ok(Dynamic::UNIT)
|
||||
@@ -958,14 +961,14 @@ impl Engine {
|
||||
});
|
||||
|
||||
if let Ok(module) = module_result {
|
||||
if let Some(name) = export.as_ref().map(|x| x.name.clone()) {
|
||||
if !export.is_empty() {
|
||||
if !module.is_indexed() {
|
||||
// Index the module (making a clone copy if necessary) if it is not indexed
|
||||
let mut module = crate::func::native::shared_take_or_clone(module);
|
||||
module.build_index();
|
||||
global.push_import(name, module);
|
||||
let mut m = crate::func::native::shared_take_or_clone(module);
|
||||
m.build_index();
|
||||
global.push_import(export.name.clone(), m);
|
||||
} else {
|
||||
global.push_import(name, module);
|
||||
global.push_import(export.name.clone(), module);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -983,7 +986,7 @@ impl Engine {
|
||||
// Export statement
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Stmt::Export(x, ..) => {
|
||||
let (Ident { name, pos, .. }, Ident { name: alias, .. }) = x.as_ref();
|
||||
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(
|
||||
|
Reference in New Issue
Block a user