Implement variable resolver.

This commit is contained in:
Stephen Chung
2020-10-11 21:58:11 +08:00
parent 9d93dac8e7
commit fd5a932611
18 changed files with 511 additions and 237 deletions

View File

@@ -2,9 +2,9 @@
use crate::any::Dynamic;
use crate::engine::{
search_imports, search_namespace, search_scope_only, Engine, Imports, State, KEYWORD_DEBUG,
KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_FN,
KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_TYPE_OF,
search_imports, Engine, Imports, State, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR,
KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR,
KEYWORD_PRINT, KEYWORD_TYPE_OF,
};
use crate::error::ParseErrorType;
use crate::fn_native::{FnCallArgs, FnPtr};
@@ -861,7 +861,7 @@ impl Engine {
})
.and_then(|s| FnPtr::try_from(s))
.map(Into::<Dynamic>::into)
.map_err(|err| err.new_position(expr.position()));
.map_err(|err| err.fill_position(expr.position()));
}
}
@@ -1000,7 +1000,7 @@ impl Engine {
})?;
let result = if !script.is_empty() {
self.eval_script_expr(scope, mods, state, lib, script, level + 1)
.map_err(|err| err.new_position(expr.position()))
.map_err(|err| err.fill_position(expr.position()))
} else {
Ok(().into())
};
@@ -1040,18 +1040,21 @@ impl Engine {
.map(|expr| self.eval_expr(scope, mods, state, lib, this_ptr, expr, level))
.collect::<Result<_, _>>()?;
let (target, _, _, pos) = search_namespace(scope, mods, state, this_ptr, lhs)?;
let (target, _, _, pos) =
self.search_namespace(scope, mods, state, lib, this_ptr, lhs)?;
self.inc_operations(state)
.map_err(|err| err.new_position(pos))?;
.map_err(|err| err.fill_position(pos))?;
args = if target.is_shared() {
arg_values.insert(0, target.flatten_clone());
args = if target.is_shared() || target.is_value() {
arg_values.insert(0, target.take_or_clone().flatten());
arg_values.iter_mut().collect()
} else {
// Turn it into a method call only if the object is not shared
// Turn it into a method call only if the object is not shared and not a simple value
is_ref = true;
once(target).chain(arg_values.iter_mut()).collect()
once(target.take_ref().unwrap())
.chain(arg_values.iter_mut())
.collect()
};
}
// func(..., ...)
@@ -1121,16 +1124,23 @@ impl Engine {
.collect::<Result<_, _>>()?;
// Get target reference to first argument
let var_expr = args_expr.get(0).unwrap();
let (target, _, _, pos) =
search_scope_only(scope, state, this_ptr, args_expr.get(0).unwrap())?;
self.search_scope_only(scope, mods, state, lib, this_ptr, var_expr)?;
self.inc_operations(state)
.map_err(|err| err.new_position(pos))?;
.map_err(|err| err.fill_position(pos))?;
let (first, rest) = arg_values.split_first_mut().unwrap();
first_arg_value = Some(first);
args = once(target).chain(rest.iter_mut()).collect();
if target.is_shared() || target.is_value() {
arg_values[0] = target.take_or_clone().flatten();
args = arg_values.iter_mut().collect();
} else {
let (first, rest) = arg_values.split_first_mut().unwrap();
first_arg_value = Some(first);
args = once(target.take_ref().unwrap())
.chain(rest.iter_mut())
.collect();
}
}
// func(..., ...) or func(mod::x, ...)
_ => {