Reformat.
This commit is contained in:
parent
414f3d3c23
commit
33c9be7efc
@ -858,7 +858,7 @@ impl Engine {
|
|||||||
|
|
||||||
return result.try_cast::<T>().ok_or_else(|| {
|
return result.try_cast::<T>().ok_or_else(|| {
|
||||||
Box::new(EvalAltResult::ErrorMismatchOutputType(
|
Box::new(EvalAltResult::ErrorMismatchOutputType(
|
||||||
return_type.to_string(),
|
return_type.into(),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
@ -1000,7 +1000,7 @@ impl Engine {
|
|||||||
|
|
||||||
let fn_def = fn_lib
|
let fn_def = fn_lib
|
||||||
.get_function_by_signature(name, args.len(), true)
|
.get_function_by_signature(name, args.len(), true)
|
||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorFunctionNotFound(name.to_string(), pos)))?;
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorFunctionNotFound(name.into(), pos)))?;
|
||||||
|
|
||||||
let state = State::new(fn_lib);
|
let state = State::new(fn_lib);
|
||||||
|
|
||||||
|
365
src/engine.rs
365
src/engine.rs
@ -3,7 +3,7 @@
|
|||||||
use crate::any::{Dynamic, Union};
|
use crate::any::{Dynamic, Union};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::error::ParseErrorType;
|
use crate::error::ParseErrorType;
|
||||||
use crate::fn_native::{FnCallArgs, NativeFunction, NativeFunctionABI, SharedNativeFunction};
|
use crate::fn_native::{FnCallArgs, NativeFunctionABI};
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{
|
use crate::packages::{
|
||||||
CorePackage, Package, PackageLibrary, PackageStore, PackagesCollection, StandardPackage,
|
CorePackage, Package, PackageLibrary, PackageStore, PackagesCollection, StandardPackage,
|
||||||
@ -194,14 +194,14 @@ impl FunctionsLib {
|
|||||||
/// Does a certain function exist in the `FunctionsLib`?
|
/// Does a certain function exist in the `FunctionsLib`?
|
||||||
///
|
///
|
||||||
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
||||||
pub fn has_function(&self, hash: u64) -> bool {
|
pub fn has_function(&self, hash_fn_def: u64) -> bool {
|
||||||
self.contains_key(&hash)
|
self.contains_key(&hash_fn_def)
|
||||||
}
|
}
|
||||||
/// Get a function definition from the `FunctionsLib`.
|
/// Get a function definition from the `FunctionsLib`.
|
||||||
///
|
///
|
||||||
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
||||||
pub fn get_function(&self, hash: u64) -> Option<&FnDef> {
|
pub fn get_function(&self, hash_fn_def: u64) -> Option<&FnDef> {
|
||||||
self.get(&hash).map(|fn_def| fn_def.as_ref())
|
self.get(&hash_fn_def).map(|fn_def| fn_def.as_ref())
|
||||||
}
|
}
|
||||||
/// Get a function definition from the `FunctionsLib`.
|
/// Get a function definition from the `FunctionsLib`.
|
||||||
pub fn get_function_by_signature(
|
pub fn get_function_by_signature(
|
||||||
@ -211,8 +211,8 @@ impl FunctionsLib {
|
|||||||
public_only: bool,
|
public_only: bool,
|
||||||
) -> Option<&FnDef> {
|
) -> Option<&FnDef> {
|
||||||
// Qualifiers (none) + function name + placeholders (one for each parameter).
|
// Qualifiers (none) + function name + placeholders (one for each parameter).
|
||||||
let hash = calc_fn_hash(empty(), name, repeat(EMPTY_TYPE_ID()).take(params));
|
let hash_fn_def = calc_fn_hash(empty(), name, repeat(EMPTY_TYPE_ID()).take(params));
|
||||||
let fn_def = self.get_function(hash);
|
let fn_def = self.get_function(hash_fn_def);
|
||||||
|
|
||||||
match fn_def.as_ref().map(|f| f.access) {
|
match fn_def.as_ref().map(|f| f.access) {
|
||||||
None => None,
|
None => None,
|
||||||
@ -419,9 +419,7 @@ fn search_scope<'a>(
|
|||||||
) -> Result<(&'a mut Dynamic, ScopeEntryType), Box<EvalAltResult>> {
|
) -> Result<(&'a mut Dynamic, ScopeEntryType), Box<EvalAltResult>> {
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
{
|
{
|
||||||
if let Some((modules, hash)) = modules {
|
if let Some((modules, hash_var)) = modules {
|
||||||
let (id, root_pos) = modules.get_ref(0);
|
|
||||||
|
|
||||||
let module = if let Some(index) = modules.index() {
|
let module = if let Some(index) = modules.index() {
|
||||||
scope
|
scope
|
||||||
.get_mut(scope.len() - index.get())
|
.get_mut(scope.len() - index.get())
|
||||||
@ -429,16 +427,15 @@ fn search_scope<'a>(
|
|||||||
.downcast_mut::<Module>()
|
.downcast_mut::<Module>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
} else {
|
} else {
|
||||||
|
let (id, root_pos) = modules.get_ref(0);
|
||||||
|
|
||||||
scope.find_module(id).ok_or_else(|| {
|
scope.find_module(id).ok_or_else(|| {
|
||||||
Box::new(EvalAltResult::ErrorModuleNotFound(
|
Box::new(EvalAltResult::ErrorModuleNotFound(id.into(), *root_pos))
|
||||||
id.to_string(),
|
|
||||||
*root_pos,
|
|
||||||
))
|
|
||||||
})?
|
})?
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok((
|
return Ok((
|
||||||
module.get_qualified_var_mut(name, hash, pos)?,
|
module.get_qualified_var_mut(name, hash_var, pos)?,
|
||||||
// Module variables are constant
|
// Module variables are constant
|
||||||
ScopeEntryType::Constant,
|
ScopeEntryType::Constant,
|
||||||
));
|
));
|
||||||
@ -544,10 +541,9 @@ impl Engine {
|
|||||||
scope: Option<&mut Scope>,
|
scope: Option<&mut Scope>,
|
||||||
state: &State,
|
state: &State,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
is_protected: bool,
|
hashes: (u64, u64),
|
||||||
hash_fn_spec: u64,
|
|
||||||
hash_fn_def: u64,
|
|
||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
|
is_ref: bool,
|
||||||
def_val: Option<&Dynamic>,
|
def_val: Option<&Dynamic>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
level: usize,
|
level: usize,
|
||||||
@ -558,8 +554,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// First search in script-defined functions (can override built-in)
|
// First search in script-defined functions (can override built-in)
|
||||||
if hash_fn_def > 0 {
|
if hashes.1 > 0 {
|
||||||
if let Some(fn_def) = state.get_function(hash_fn_def) {
|
if let Some(fn_def) = state.get_function(hashes.1) {
|
||||||
return self
|
return self
|
||||||
.call_script_fn(scope, state, fn_def, args, pos, level)
|
.call_script_fn(scope, state, fn_def, args, pos, level)
|
||||||
.map(|v| (v, false));
|
.map(|v| (v, false));
|
||||||
@ -569,21 +565,21 @@ impl Engine {
|
|||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
if let Some(func) = self
|
if let Some(func) = self
|
||||||
.base_package
|
.base_package
|
||||||
.get_function(hash_fn_spec)
|
.get_function(hashes.0)
|
||||||
.or_else(|| self.packages.get_function(hash_fn_spec))
|
.or_else(|| self.packages.get_function(hashes.0))
|
||||||
{
|
{
|
||||||
let mut backup: Dynamic = ().into();
|
let mut backup: Dynamic = Default::default();
|
||||||
let mut restore = false;
|
|
||||||
|
|
||||||
let updated = match func.abi() {
|
let (updated, restore) = match func.abi() {
|
||||||
// Calling pure function in method-call
|
// Calling pure function in method-call
|
||||||
NativeFunctionABI::Pure if is_protected && args.len() > 0 => {
|
NativeFunctionABI::Pure if is_ref && args.len() > 0 => {
|
||||||
|
// Backup the original value. It'll be consumed because the function
|
||||||
|
// is pure and doesn't know that the first value is a reference (i.e. `is_ref`)
|
||||||
backup = args[0].clone();
|
backup = args[0].clone();
|
||||||
restore = true;
|
(false, true)
|
||||||
false
|
|
||||||
}
|
}
|
||||||
NativeFunctionABI::Pure => false,
|
NativeFunctionABI::Pure => (false, false),
|
||||||
NativeFunctionABI::Method => true,
|
NativeFunctionABI::Method => (true, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run external function
|
// Run external function
|
||||||
@ -742,13 +738,13 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Has a system function an override?
|
// Has a system function an override?
|
||||||
fn has_override(&self, state: &State, hash_fn_spec: u64, hash_fn_def: u64) -> bool {
|
fn has_override(&self, state: &State, hashes: (u64, u64)) -> bool {
|
||||||
// First check registered functions
|
// First check registered functions
|
||||||
self.base_package.contains_function(hash_fn_spec)
|
self.base_package.contains_function(hashes.0)
|
||||||
// Then check packages
|
// Then check packages
|
||||||
|| self.packages.contains_function(hash_fn_spec)
|
|| self.packages.contains_function(hashes.0)
|
||||||
// Then check script-defined functions
|
// Then check script-defined functions
|
||||||
|| state.has_function(hash_fn_def)
|
|| state.has_function(hashes.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform an actual function call, taking care of special functions
|
// Perform an actual function call, taking care of special functions
|
||||||
@ -762,31 +758,26 @@ impl Engine {
|
|||||||
&self,
|
&self,
|
||||||
state: &State,
|
state: &State,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
is_protected: bool,
|
|
||||||
hash_fn_def: u64,
|
hash_fn_def: u64,
|
||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
|
is_ref: bool,
|
||||||
def_val: Option<&Dynamic>,
|
def_val: Option<&Dynamic>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
// Qualifiers (none) + function name + argument `TypeId`'s.
|
// Qualifiers (none) + function name + argument `TypeId`'s.
|
||||||
let hash_fn_spec = calc_fn_hash(empty(), fn_name, args.iter().map(|a| a.type_id()));
|
let hash_fn = calc_fn_hash(empty(), fn_name, args.iter().map(|a| a.type_id()));
|
||||||
|
let hashes = (hash_fn, hash_fn_def);
|
||||||
|
|
||||||
match fn_name {
|
match fn_name {
|
||||||
// type_of
|
// type_of
|
||||||
KEYWORD_TYPE_OF
|
KEYWORD_TYPE_OF if args.len() == 1 && !self.has_override(state, hashes) => Ok((
|
||||||
if args.len() == 1 && !self.has_override(state, hash_fn_spec, hash_fn_def) =>
|
self.map_type_name(args[0].type_name()).to_string().into(),
|
||||||
{
|
false,
|
||||||
Ok((
|
)),
|
||||||
self.map_type_name(args[0].type_name()).to_string().into(),
|
|
||||||
false,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
// eval - reaching this point it must be a method-style call
|
// eval - reaching this point it must be a method-style call
|
||||||
KEYWORD_EVAL
|
KEYWORD_EVAL if args.len() == 1 && !self.has_override(state, hashes) => {
|
||||||
if args.len() == 1 && !self.has_override(state, hash_fn_spec, hash_fn_def) =>
|
|
||||||
{
|
|
||||||
Err(Box::new(EvalAltResult::ErrorRuntime(
|
Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
"'eval' should not be called in method style. Try eval(...);".into(),
|
"'eval' should not be called in method style. Try eval(...);".into(),
|
||||||
pos,
|
pos,
|
||||||
@ -795,16 +786,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Normal function call
|
// Normal function call
|
||||||
_ => self.call_fn_raw(
|
_ => self.call_fn_raw(
|
||||||
None,
|
None, state, fn_name, hashes, args, is_ref, def_val, pos, level,
|
||||||
state,
|
|
||||||
fn_name,
|
|
||||||
is_protected,
|
|
||||||
hash_fn_spec,
|
|
||||||
hash_fn_def,
|
|
||||||
args,
|
|
||||||
def_val,
|
|
||||||
pos,
|
|
||||||
level,
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -857,7 +839,7 @@ impl Engine {
|
|||||||
mut new_val: Option<Dynamic>,
|
mut new_val: Option<Dynamic>,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
// Get a reference to the mutation target Dynamic
|
// Get a reference to the mutation target Dynamic
|
||||||
let (obj, is_protected) = match target {
|
let (obj, is_ref) = match target {
|
||||||
Target::Ref(r) => (r, true),
|
Target::Ref(r) => (r, true),
|
||||||
Target::Value(ref mut r) => (r.as_mut(), false),
|
Target::Value(ref mut r) => (r.as_mut(), false),
|
||||||
Target::StringChar(ref mut x) => (&mut x.2, false),
|
Target::StringChar(ref mut x) => (&mut x.2, false),
|
||||||
@ -870,60 +852,34 @@ impl Engine {
|
|||||||
match rhs {
|
match rhs {
|
||||||
// xxx[idx].dot_rhs... | xxx[idx][dot_rhs]...
|
// xxx[idx].dot_rhs... | xxx[idx][dot_rhs]...
|
||||||
Expr::Dot(x) | Expr::Index(x) => {
|
Expr::Dot(x) | Expr::Index(x) => {
|
||||||
let is_index = matches!(rhs, Expr::Index(_));
|
let is_idx = matches!(rhs, Expr::Index(_));
|
||||||
|
let pos = x.0.position();
|
||||||
|
let val =
|
||||||
|
self.get_indexed_mut(state, obj, is_ref, idx_val, pos, op_pos, false)?;
|
||||||
|
|
||||||
let indexed_val = self.get_indexed_mut(
|
|
||||||
state,
|
|
||||||
obj,
|
|
||||||
is_protected,
|
|
||||||
idx_val,
|
|
||||||
x.0.position(),
|
|
||||||
op_pos,
|
|
||||||
false,
|
|
||||||
)?;
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
state,
|
state, val, &x.1, idx_values, is_idx, x.2, level, new_val,
|
||||||
indexed_val,
|
|
||||||
&x.1,
|
|
||||||
idx_values,
|
|
||||||
is_index,
|
|
||||||
x.2,
|
|
||||||
level,
|
|
||||||
new_val,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// xxx[rhs] = new_val
|
// xxx[rhs] = new_val
|
||||||
_ if new_val.is_some() => {
|
_ if new_val.is_some() => {
|
||||||
let mut indexed_val = self.get_indexed_mut(
|
let pos = rhs.position();
|
||||||
state,
|
let mut val =
|
||||||
obj,
|
self.get_indexed_mut(state, obj, is_ref, idx_val, pos, op_pos, true)?;
|
||||||
is_protected,
|
|
||||||
idx_val,
|
val.set_value(new_val.unwrap(), rhs.position())?;
|
||||||
rhs.position(),
|
|
||||||
op_pos,
|
|
||||||
true,
|
|
||||||
)?;
|
|
||||||
indexed_val.set_value(new_val.unwrap(), rhs.position())?;
|
|
||||||
Ok((Default::default(), true))
|
Ok((Default::default(), true))
|
||||||
}
|
}
|
||||||
// xxx[rhs]
|
// xxx[rhs]
|
||||||
_ => self
|
_ => self
|
||||||
.get_indexed_mut(
|
.get_indexed_mut(state, obj, is_ref, idx_val, rhs.position(), op_pos, false)
|
||||||
state,
|
|
||||||
obj,
|
|
||||||
is_protected,
|
|
||||||
idx_val,
|
|
||||||
rhs.position(),
|
|
||||||
op_pos,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.map(|v| (v.clone_into_dynamic(), false)),
|
.map(|v| (v.clone_into_dynamic(), false)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match rhs {
|
match rhs {
|
||||||
// xxx.fn_name(arg_expr_list)
|
// xxx.fn_name(arg_expr_list)
|
||||||
Expr::FnCall(x) if x.1.is_none() => {
|
Expr::FnCall(x) if x.1.is_none() => {
|
||||||
let ((name, pos), _, hash, _, def_val) = x.as_ref();
|
let ((name, pos), _, hash_fn_def, _, def_val) = x.as_ref();
|
||||||
let def_val = def_val.as_ref();
|
let def_val = def_val.as_ref();
|
||||||
|
|
||||||
let mut arg_values: StaticVec<_> = once(obj)
|
let mut arg_values: StaticVec<_> = once(obj)
|
||||||
@ -936,7 +892,7 @@ impl Engine {
|
|||||||
.collect();
|
.collect();
|
||||||
let args = arg_values.as_mut();
|
let args = arg_values.as_mut();
|
||||||
|
|
||||||
self.exec_fn_call(state, name, is_protected, *hash, args, def_val, *pos, 0)
|
self.exec_fn_call(state, name, *hash_fn_def, args, is_ref, def_val, *pos, 0)
|
||||||
}
|
}
|
||||||
// xxx.module::fn_name(...) - syntax error
|
// xxx.module::fn_name(...) - syntax error
|
||||||
Expr::FnCall(_) => unreachable!(),
|
Expr::FnCall(_) => unreachable!(),
|
||||||
@ -944,83 +900,78 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Property(x) if obj.is::<Map>() && new_val.is_some() => {
|
Expr::Property(x) if obj.is::<Map>() && new_val.is_some() => {
|
||||||
let index = x.0.clone().into();
|
let index = x.0.clone().into();
|
||||||
let mut indexed_val =
|
let mut val =
|
||||||
self.get_indexed_mut(state, obj, is_protected, index, x.1, op_pos, true)?;
|
self.get_indexed_mut(state, obj, is_ref, index, x.1, op_pos, true)?;
|
||||||
indexed_val.set_value(new_val.unwrap(), rhs.position())?;
|
|
||||||
|
val.set_value(new_val.unwrap(), rhs.position())?;
|
||||||
Ok((Default::default(), true))
|
Ok((Default::default(), true))
|
||||||
}
|
}
|
||||||
// {xxx:map}.id
|
// {xxx:map}.id
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Property(x) if obj.is::<Map>() => {
|
Expr::Property(x) if obj.is::<Map>() => {
|
||||||
let index = x.0.clone().into();
|
let index = x.0.clone().into();
|
||||||
let indexed_val =
|
let val =
|
||||||
self.get_indexed_mut(state, obj, is_protected, index, x.1, op_pos, false)?;
|
self.get_indexed_mut(state, obj, is_ref, index, x.1, op_pos, false)?;
|
||||||
Ok((indexed_val.clone_into_dynamic(), false))
|
|
||||||
|
Ok((val.clone_into_dynamic(), false))
|
||||||
}
|
}
|
||||||
// xxx.id = ??? a
|
// xxx.id = ???
|
||||||
Expr::Property(x) if new_val.is_some() => {
|
Expr::Property(x) if new_val.is_some() => {
|
||||||
let fn_name = make_setter(&x.0);
|
let fn_name = make_setter(&x.0);
|
||||||
let mut args = [obj, new_val.as_mut().unwrap()];
|
let mut args = [obj, new_val.as_mut().unwrap()];
|
||||||
self.exec_fn_call(state, &fn_name, is_protected, 0, &mut args, None, x.1, 0)
|
self.exec_fn_call(state, &fn_name, 0, &mut args, is_ref, None, x.1, 0)
|
||||||
.map(|(v, _)| (v, true))
|
.map(|(v, _)| (v, true))
|
||||||
}
|
}
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(x) => {
|
Expr::Property(x) => {
|
||||||
let fn_name = make_getter(&x.0);
|
let fn_name = make_getter(&x.0);
|
||||||
let mut args = [obj];
|
let mut args = [obj];
|
||||||
self.exec_fn_call(state, &fn_name, is_protected, 0, &mut args, None, x.1, 0)
|
self.exec_fn_call(state, &fn_name, 0, &mut args, is_ref, None, x.1, 0)
|
||||||
.map(|(v, _)| (v, false))
|
.map(|(v, _)| (v, false))
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
// {xxx:map}.idx_lhs[idx_expr] | {xxx:map}.dot_lhs.rhs
|
// {xxx:map}.idx_lhs[idx_expr] | {xxx:map}.dot_lhs.rhs
|
||||||
Expr::Index(x) | Expr::Dot(x) if obj.is::<Map>() => {
|
Expr::Index(x) | Expr::Dot(x) if obj.is::<Map>() => {
|
||||||
let is_index = matches!(rhs, Expr::Index(_));
|
let is_idx = matches!(rhs, Expr::Index(_));
|
||||||
|
|
||||||
let indexed_val = if let Expr::Property(p) = &x.0 {
|
let val = if let Expr::Property(p) = &x.0 {
|
||||||
let index = p.0.clone().into();
|
let index = p.0.clone().into();
|
||||||
self.get_indexed_mut(state, obj, is_protected, index, x.2, op_pos, false)?
|
self.get_indexed_mut(state, obj, is_ref, index, x.2, op_pos, false)?
|
||||||
} else {
|
} else {
|
||||||
// Syntax error
|
// Syntax error
|
||||||
return Err(Box::new(EvalAltResult::ErrorDotExpr(
|
return Err(Box::new(EvalAltResult::ErrorDotExpr(
|
||||||
"".to_string(),
|
"".into(),
|
||||||
rhs.position(),
|
rhs.position(),
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
state,
|
state, val, &x.1, idx_values, is_idx, x.2, level, new_val,
|
||||||
indexed_val,
|
|
||||||
&x.1,
|
|
||||||
idx_values,
|
|
||||||
is_index,
|
|
||||||
x.2,
|
|
||||||
level,
|
|
||||||
new_val,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// xxx.idx_lhs[idx_expr] | xxx.dot_lhs.rhs
|
// xxx.idx_lhs[idx_expr] | xxx.dot_lhs.rhs
|
||||||
Expr::Index(x) | Expr::Dot(x) => {
|
Expr::Index(x) | Expr::Dot(x) => {
|
||||||
let is_index = matches!(rhs, Expr::Index(_));
|
let is_idx = matches!(rhs, Expr::Index(_));
|
||||||
let mut arg_values = [obj, &mut Default::default()];
|
let args = &mut [obj, &mut Default::default()];
|
||||||
|
|
||||||
let (mut indexed_val, updated) = if let Expr::Property(p) = &x.0 {
|
let (mut val, updated) = if let Expr::Property(p) = &x.0 {
|
||||||
let fn_name = make_getter(&p.0);
|
let fn_name = make_getter(&p.0);
|
||||||
let args = &mut arg_values[..1];
|
self.exec_fn_call(state, &fn_name, 0, &mut args[..1], is_ref, None, x.2, 0)?
|
||||||
self.exec_fn_call(state, &fn_name, is_protected, 0, args, None, x.2, 0)?
|
|
||||||
} else {
|
} else {
|
||||||
// Syntax error
|
// Syntax error
|
||||||
return Err(Box::new(EvalAltResult::ErrorDotExpr(
|
return Err(Box::new(EvalAltResult::ErrorDotExpr(
|
||||||
"".to_string(),
|
"".into(),
|
||||||
rhs.position(),
|
rhs.position(),
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
let indexed_val = &mut indexed_val;
|
let val = &mut val;
|
||||||
|
|
||||||
let (result, may_be_changed) = self.eval_dot_index_chain_helper(
|
let (result, may_be_changed) = self.eval_dot_index_chain_helper(
|
||||||
state,
|
state,
|
||||||
indexed_val.into(),
|
val.into(),
|
||||||
&x.1,
|
&x.1,
|
||||||
idx_values,
|
idx_values,
|
||||||
is_index,
|
is_idx,
|
||||||
x.2,
|
x.2,
|
||||||
level,
|
level,
|
||||||
new_val,
|
new_val,
|
||||||
@ -1031,9 +982,8 @@ impl Engine {
|
|||||||
if let Expr::Property(p) = &x.0 {
|
if let Expr::Property(p) = &x.0 {
|
||||||
let fn_name = make_setter(&p.0);
|
let fn_name = make_setter(&p.0);
|
||||||
// Re-use args because the first &mut parameter will not be consumed
|
// Re-use args because the first &mut parameter will not be consumed
|
||||||
arg_values[1] = indexed_val;
|
args[1] = val;
|
||||||
let args = &mut arg_values;
|
self.exec_fn_call(state, &fn_name, 0, args, is_ref, None, x.2, 0)
|
||||||
self.exec_fn_call(state, &fn_name, is_protected, 0, args, None, x.2, 0)
|
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
// If there is no setter, no need to feed it back because the property is read-only
|
// If there is no setter, no need to feed it back because the property is read-only
|
||||||
EvalAltResult::ErrorDotExpr(_, _) => Ok(Default::default()),
|
EvalAltResult::ErrorDotExpr(_, _) => Ok(Default::default()),
|
||||||
@ -1046,7 +996,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// Syntax error
|
// Syntax error
|
||||||
_ => Err(Box::new(EvalAltResult::ErrorDotExpr(
|
_ => Err(Box::new(EvalAltResult::ErrorDotExpr(
|
||||||
"".to_string(),
|
"".into(),
|
||||||
rhs.position(),
|
rhs.position(),
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
@ -1072,9 +1022,9 @@ impl Engine {
|
|||||||
match dot_lhs {
|
match dot_lhs {
|
||||||
// id.??? or id[???]
|
// id.??? or id[???]
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let ((name, pos), modules, hash, index) = x.as_ref();
|
let ((name, pos), modules, hash_var, index) = x.as_ref();
|
||||||
let index = if state.always_search { None } else { *index };
|
let index = if state.always_search { None } else { *index };
|
||||||
let mod_and_hash = modules.as_ref().map(|m| (m, *hash));
|
let mod_and_hash = modules.as_ref().map(|m| (m, *hash_var));
|
||||||
let (target, typ) = search_scope(scope, &name, mod_and_hash, index, *pos)?;
|
let (target, typ) = search_scope(scope, &name, mod_and_hash, index, *pos)?;
|
||||||
|
|
||||||
// Constants cannot be modified
|
// Constants cannot be modified
|
||||||
@ -1162,14 +1112,12 @@ impl Engine {
|
|||||||
&self,
|
&self,
|
||||||
state: &State,
|
state: &State,
|
||||||
val: &'a mut Dynamic,
|
val: &'a mut Dynamic,
|
||||||
is_protected: bool,
|
is_ref: bool,
|
||||||
mut idx: Dynamic,
|
mut idx: Dynamic,
|
||||||
idx_pos: Position,
|
idx_pos: Position,
|
||||||
op_pos: Position,
|
op_pos: Position,
|
||||||
create: bool,
|
create: bool,
|
||||||
) -> Result<Target<'a>, Box<EvalAltResult>> {
|
) -> Result<Target<'a>, Box<EvalAltResult>> {
|
||||||
let type_name = self.map_type_name(val.type_name());
|
|
||||||
|
|
||||||
match val {
|
match val {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Dynamic(Union::Array(arr)) => {
|
Dynamic(Union::Array(arr)) => {
|
||||||
@ -1212,43 +1160,31 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Dynamic(Union::Str(s)) => {
|
Dynamic(Union::Str(s)) => {
|
||||||
// val_string[idx]
|
// val_string[idx]
|
||||||
|
let chars_len = s.chars().count();
|
||||||
let index = idx
|
let index = idx
|
||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_pos))?;
|
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_pos))?;
|
||||||
|
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
let ch = s.chars().nth(index as usize).ok_or_else(|| {
|
let offset = index as usize;
|
||||||
Box::new(EvalAltResult::ErrorStringBounds(
|
let ch = s.chars().nth(offset).ok_or_else(|| {
|
||||||
s.chars().count(),
|
Box::new(EvalAltResult::ErrorStringBounds(chars_len, index, idx_pos))
|
||||||
index,
|
|
||||||
idx_pos,
|
|
||||||
))
|
|
||||||
})?;
|
})?;
|
||||||
|
Ok(Target::StringChar(Box::new((val, offset, ch.into()))))
|
||||||
Ok(Target::StringChar(Box::new((
|
|
||||||
val,
|
|
||||||
index as usize,
|
|
||||||
ch.into(),
|
|
||||||
))))
|
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(EvalAltResult::ErrorStringBounds(
|
Err(Box::new(EvalAltResult::ErrorStringBounds(
|
||||||
s.chars().count(),
|
chars_len, index, idx_pos,
|
||||||
index,
|
|
||||||
idx_pos,
|
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
let type_name = self.map_type_name(val.type_name());
|
||||||
let args = &mut [val, &mut idx];
|
let args = &mut [val, &mut idx];
|
||||||
self.exec_fn_call(state, FUNC_INDEXER, is_protected, 0, args, None, op_pos, 0)
|
self.exec_fn_call(state, FUNC_INDEXER, 0, args, is_ref, None, op_pos, 0)
|
||||||
.map(|(v, _)| v.into())
|
.map(|(v, _)| v.into())
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Box::new(EvalAltResult::ErrorIndexingType(
|
Box::new(EvalAltResult::ErrorIndexingType(type_name.into(), op_pos))
|
||||||
// Error - cannot be indexed
|
|
||||||
type_name.to_string(),
|
|
||||||
op_pos,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1263,36 +1199,29 @@ impl Engine {
|
|||||||
rhs: &Expr,
|
rhs: &Expr,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let lhs_value = self.eval_expr(scope, state, lhs, level)?;
|
let mut lhs_value = self.eval_expr(scope, state, lhs, level)?;
|
||||||
let rhs_value = self.eval_expr(scope, state, rhs, level)?;
|
let rhs_value = self.eval_expr(scope, state, rhs, level)?;
|
||||||
|
|
||||||
match rhs_value {
|
match rhs_value {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Dynamic(Union::Array(rhs_value)) => {
|
Dynamic(Union::Array(mut rhs_value)) => {
|
||||||
let op = "==";
|
let op = "==";
|
||||||
let def_value = false.into();
|
let def_value = false.into();
|
||||||
let fn_def = calc_fn_hash(empty(), op, repeat(EMPTY_TYPE_ID()).take(2));
|
let hash_fn_def = calc_fn_hash(empty(), op, repeat(EMPTY_TYPE_ID()).take(2));
|
||||||
|
|
||||||
// Call the `==` operator to compare each value
|
// Call the `==` operator to compare each value
|
||||||
for value in rhs_value.iter() {
|
for value in rhs_value.iter_mut() {
|
||||||
// WARNING - Always clone the values here because they'll be consumed by the function call.
|
let args = &mut [&mut lhs_value, value];
|
||||||
// Do not pass the `&mut` straight through because the `==` implementation
|
|
||||||
// very likely takes parameters passed by value!
|
|
||||||
let args = &mut [&mut lhs_value.clone(), &mut value.clone()];
|
|
||||||
let def_value = Some(&def_value);
|
let def_value = Some(&def_value);
|
||||||
let pos = rhs.position();
|
let pos = rhs.position();
|
||||||
|
|
||||||
// Qualifiers (none) + function name + argument `TypeId`'s.
|
// Qualifiers (none) + function name + argument `TypeId`'s.
|
||||||
let fn_spec = calc_fn_hash(empty(), op, args.iter().map(|a| a.type_id()));
|
let hash_fn = calc_fn_hash(empty(), op, args.iter().map(|a| a.type_id()));
|
||||||
|
let hashes = (hash_fn, hash_fn_def);
|
||||||
|
|
||||||
if self
|
let (r, _) = self
|
||||||
.call_fn_raw(
|
.call_fn_raw(None, state, op, hashes, args, true, def_value, pos, level)?;
|
||||||
None, state, op, false, fn_spec, fn_def, args, def_value, pos, level,
|
if r.as_bool().unwrap_or(false) {
|
||||||
)?
|
|
||||||
.0
|
|
||||||
.as_bool()
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
return Ok(true.into());
|
return Ok(true.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1331,9 +1260,9 @@ impl Engine {
|
|||||||
Expr::StringConstant(x) => Ok(x.0.to_string().into()),
|
Expr::StringConstant(x) => Ok(x.0.to_string().into()),
|
||||||
Expr::CharConstant(x) => Ok(x.0.into()),
|
Expr::CharConstant(x) => Ok(x.0.into()),
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let ((name, pos), modules, hash, index) = x.as_ref();
|
let ((name, pos), modules, hash_var, index) = x.as_ref();
|
||||||
let index = if state.always_search { None } else { *index };
|
let index = if state.always_search { None } else { *index };
|
||||||
let mod_and_hash = modules.as_ref().map(|m| (m, *hash));
|
let mod_and_hash = modules.as_ref().map(|m| (m, *hash_var));
|
||||||
let (val, _) = search_scope(scope, name, mod_and_hash, index, *pos)?;
|
let (val, _) = search_scope(scope, name, mod_and_hash, index, *pos)?;
|
||||||
Ok(val.clone())
|
Ok(val.clone())
|
||||||
}
|
}
|
||||||
@ -1350,17 +1279,16 @@ impl Engine {
|
|||||||
match &x.0 {
|
match &x.0 {
|
||||||
// name = rhs
|
// name = rhs
|
||||||
Expr::Variable(x) => {
|
Expr::Variable(x) => {
|
||||||
let ((name, pos), modules, hash, index) = x.as_ref();
|
let ((name, pos), modules, hash_var, index) = x.as_ref();
|
||||||
let index = if state.always_search { None } else { *index };
|
let index = if state.always_search { None } else { *index };
|
||||||
let mod_and_hash = modules.as_ref().map(|m| (m, *hash));
|
let mod_and_hash = modules.as_ref().map(|m| (m, *hash_var));
|
||||||
let (value_ptr, typ) =
|
let (lhs_ptr, typ) = search_scope(scope, name, mod_and_hash, index, *pos)?;
|
||||||
search_scope(scope, name, mod_and_hash, index, *pos)?;
|
|
||||||
match typ {
|
match typ {
|
||||||
ScopeEntryType::Constant => Err(Box::new(
|
ScopeEntryType::Constant => Err(Box::new(
|
||||||
EvalAltResult::ErrorAssignmentToConstant(name.clone(), *pos),
|
EvalAltResult::ErrorAssignmentToConstant(name.clone(), *pos),
|
||||||
)),
|
)),
|
||||||
ScopeEntryType::Normal => {
|
ScopeEntryType::Normal => {
|
||||||
*value_ptr = rhs_val;
|
*lhs_ptr = rhs_val;
|
||||||
Ok(Default::default())
|
Ok(Default::default())
|
||||||
}
|
}
|
||||||
// End variable cannot be a module
|
// End variable cannot be a module
|
||||||
@ -1429,6 +1357,7 @@ impl Engine {
|
|||||||
// Normal function call
|
// Normal function call
|
||||||
Expr::FnCall(x) if x.1.is_none() => {
|
Expr::FnCall(x) if x.1.is_none() => {
|
||||||
let ((name, pos), _, hash_fn_def, args_expr, def_val) = x.as_ref();
|
let ((name, pos), _, hash_fn_def, args_expr, def_val) = x.as_ref();
|
||||||
|
let def_val = def_val.as_ref();
|
||||||
|
|
||||||
let mut arg_values = args_expr
|
let mut arg_values = args_expr
|
||||||
.iter()
|
.iter()
|
||||||
@ -1437,41 +1366,35 @@ impl Engine {
|
|||||||
|
|
||||||
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
||||||
|
|
||||||
let hash_fn_spec =
|
if name == KEYWORD_EVAL && args.len() == 1 && args.get_ref(0).is::<String>() {
|
||||||
calc_fn_hash(empty(), KEYWORD_EVAL, once(TypeId::of::<String>()));
|
let hash_fn = calc_fn_hash(empty(), name, once(TypeId::of::<String>()));
|
||||||
|
|
||||||
if name == KEYWORD_EVAL
|
if !self.has_override(state, (hash_fn, *hash_fn_def)) {
|
||||||
&& args.len() == 1
|
// eval - only in function call style
|
||||||
&& !self.has_override(state, hash_fn_spec, *hash_fn_def)
|
let prev_len = scope.len();
|
||||||
{
|
|
||||||
// eval - only in function call style
|
|
||||||
let prev_len = scope.len();
|
|
||||||
|
|
||||||
// Evaluate the text string as a script
|
// Evaluate the text string as a script
|
||||||
let result =
|
let result = self.eval_script_expr(
|
||||||
self.eval_script_expr(scope, state, args.pop(), args_expr[0].position());
|
scope,
|
||||||
|
state,
|
||||||
|
args.pop(),
|
||||||
|
args_expr[0].position(),
|
||||||
|
);
|
||||||
|
|
||||||
if scope.len() != prev_len {
|
if scope.len() != prev_len {
|
||||||
// IMPORTANT! If the eval defines new variables in the current scope,
|
// IMPORTANT! If the eval defines new variables in the current scope,
|
||||||
// all variable offsets from this point on will be mis-aligned.
|
// all variable offsets from this point on will be mis-aligned.
|
||||||
state.always_search = true;
|
state.always_search = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
|
||||||
} else {
|
|
||||||
// Normal function call - except for eval (handled above)
|
|
||||||
self.exec_fn_call(
|
|
||||||
state,
|
|
||||||
name,
|
|
||||||
false,
|
|
||||||
*hash_fn_def,
|
|
||||||
args.as_mut(),
|
|
||||||
def_val.as_ref(),
|
|
||||||
*pos,
|
|
||||||
level,
|
|
||||||
)
|
|
||||||
.map(|(v, _)| v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normal function call - except for eval (handled above)
|
||||||
|
let args = args.as_mut();
|
||||||
|
self.exec_fn_call(state, name, *hash_fn_def, args, false, def_val, *pos, level)
|
||||||
|
.map(|(v, _)| v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module-qualified function call
|
// Module-qualified function call
|
||||||
@ -1514,9 +1437,9 @@ impl Engine {
|
|||||||
// the actual list of parameter `TypeId`'.s
|
// the actual list of parameter `TypeId`'.s
|
||||||
let hash_fn_args = calc_fn_hash(empty(), "", args.iter().map(|a| a.type_id()));
|
let hash_fn_args = calc_fn_hash(empty(), "", args.iter().map(|a| a.type_id()));
|
||||||
// 3) The final hash is the XOR of the two hashes.
|
// 3) The final hash is the XOR of the two hashes.
|
||||||
let hash = *hash_fn_def ^ hash_fn_args;
|
let hash_fn_native = *hash_fn_def ^ hash_fn_args;
|
||||||
|
|
||||||
match module.get_qualified_fn(name, hash, *pos) {
|
match module.get_qualified_fn(name, hash_fn_native, *pos) {
|
||||||
Ok(func) => func.call(args.as_mut(), *pos),
|
Ok(func) => func.call(args.as_mut(), *pos),
|
||||||
Err(_) if def_val.is_some() => Ok(def_val.clone().unwrap()),
|
Err(_) if def_val.is_some() => Ok(def_val.clone().unwrap()),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
@ -1669,8 +1592,8 @@ impl Engine {
|
|||||||
scope.push(name, ());
|
scope.push(name, ());
|
||||||
let index = scope.len() - 1;
|
let index = scope.len() - 1;
|
||||||
|
|
||||||
for a in iter_fn(iter_type) {
|
for loop_var in iter_fn(iter_type) {
|
||||||
*scope.get_mut(index).0 = a;
|
*scope.get_mut(index).0 = loop_var;
|
||||||
|
|
||||||
match self.eval_stmt(scope, state, &x.2, level) {
|
match self.eval_stmt(scope, state, &x.2, level) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
@ -1712,7 +1635,7 @@ impl Engine {
|
|||||||
Stmt::ReturnWithVal(x) if x.1.is_some() && (x.0).0 == ReturnType::Exception => {
|
Stmt::ReturnWithVal(x) if x.1.is_some() && (x.0).0 == ReturnType::Exception => {
|
||||||
let val = self.eval_expr(scope, state, x.1.as_ref().unwrap(), level)?;
|
let val = self.eval_expr(scope, state, x.1.as_ref().unwrap(), level)?;
|
||||||
Err(Box::new(EvalAltResult::ErrorRuntime(
|
Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
val.take_string().unwrap_or_else(|_| "".to_string()),
|
val.take_string().unwrap_or_else(|_| "".into()),
|
||||||
(x.0).1,
|
(x.0).1,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
@ -1771,8 +1694,7 @@ impl Engine {
|
|||||||
resolver.resolve(self, Scope::new(), &path, expr.position())?;
|
resolver.resolve(self, Scope::new(), &path, expr.position())?;
|
||||||
|
|
||||||
// TODO - avoid copying module name in inner block?
|
// TODO - avoid copying module name in inner block?
|
||||||
let mod_name = name.clone();
|
scope.push_module(name.clone(), module);
|
||||||
scope.push_module(mod_name, module);
|
|
||||||
Ok(Default::default())
|
Ok(Default::default())
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(EvalAltResult::ErrorModuleNotFound(
|
Err(Box::new(EvalAltResult::ErrorModuleNotFound(
|
||||||
@ -1789,8 +1711,6 @@ impl Engine {
|
|||||||
// Export statement
|
// Export statement
|
||||||
Stmt::Export(list) => {
|
Stmt::Export(list) => {
|
||||||
for ((id, id_pos), rename) in list.as_ref() {
|
for ((id, id_pos), rename) in list.as_ref() {
|
||||||
let mut found = false;
|
|
||||||
|
|
||||||
// Mark scope variables as public
|
// Mark scope variables as public
|
||||||
if let Some(index) = scope
|
if let Some(index) = scope
|
||||||
.get_index(id)
|
.get_index(id)
|
||||||
@ -1803,10 +1723,7 @@ impl Engine {
|
|||||||
.unwrap_or_else(|| id.clone());
|
.unwrap_or_else(|| id.clone());
|
||||||
|
|
||||||
scope.set_entry_alias(index, alias);
|
scope.set_entry_alias(index, alias);
|
||||||
found = true;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return Err(Box::new(EvalAltResult::ErrorVariableNotFound(
|
return Err(Box::new(EvalAltResult::ErrorVariableNotFound(
|
||||||
id.into(),
|
id.into(),
|
||||||
*id_pos,
|
*id_pos,
|
||||||
|
@ -97,10 +97,10 @@ macro_rules! def_anonymous_fn {
|
|||||||
type Output = Box<dyn Fn($($par),*) -> Result<RET, Box<EvalAltResult>>>;
|
type Output = Box<dyn Fn($($par),*) -> Result<RET, Box<EvalAltResult>>>;
|
||||||
|
|
||||||
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
||||||
let name = entry_point.to_string();
|
let fn_name = entry_point.to_string();
|
||||||
|
|
||||||
Box::new(move |$($par: $par),*| {
|
Box::new(move |$($par: $par),*| {
|
||||||
self.call_fn(&mut Scope::new(), &ast, &name, ($($par,)*))
|
self.call_fn(&mut Scope::new(), &ast, &fn_name, ($($par,)*))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,11 +172,11 @@ impl Module {
|
|||||||
pub(crate) fn get_qualified_var_mut(
|
pub(crate) fn get_qualified_var_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
hash: u64,
|
hash_var: u64,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<&mut Dynamic, Box<EvalAltResult>> {
|
) -> Result<&mut Dynamic, Box<EvalAltResult>> {
|
||||||
self.all_variables
|
self.all_variables
|
||||||
.get_mut(&hash)
|
.get_mut(&hash_var)
|
||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(name.to_string(), pos)))
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(name.to_string(), pos)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,8 +260,8 @@ impl Module {
|
|||||||
/// let hash = module.set_fn_0("calc", || Ok(42_i64));
|
/// let hash = module.set_fn_0("calc", || Ok(42_i64));
|
||||||
/// assert!(module.contains_fn(hash));
|
/// assert!(module.contains_fn(hash));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn contains_fn(&self, hash: u64) -> bool {
|
pub fn contains_fn(&self, hash_fn: u64) -> bool {
|
||||||
self.functions.contains_key(&hash)
|
self.functions.contains_key(&hash_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function into the module, returning a hash key.
|
/// Set a Rust function into the module, returning a hash key.
|
||||||
@ -275,7 +275,7 @@ impl Module {
|
|||||||
params: Vec<TypeId>,
|
params: Vec<TypeId>,
|
||||||
func: Box<FnAny>,
|
func: Box<FnAny>,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let hash = calc_fn_hash(empty(), &name, params.iter().cloned());
|
let hash_fn = calc_fn_hash(empty(), &name, params.iter().cloned());
|
||||||
|
|
||||||
let f = Box::new(NativeFunction::from((func, abi))) as Box<dyn NativeCallable>;
|
let f = Box::new(NativeFunction::from((func, abi))) as Box<dyn NativeCallable>;
|
||||||
|
|
||||||
@ -284,9 +284,9 @@ impl Module {
|
|||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
let func = Arc::new(f);
|
let func = Arc::new(f);
|
||||||
|
|
||||||
self.functions.insert(hash, (name, access, params, func));
|
self.functions.insert(hash_fn, (name, access, params, func));
|
||||||
|
|
||||||
hash
|
hash_fn
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking no parameters into the module, returning a hash key.
|
/// Set a Rust function taking no parameters into the module, returning a hash key.
|
||||||
@ -538,8 +538,8 @@ impl Module {
|
|||||||
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
||||||
/// assert!(module.get_fn(hash).is_some());
|
/// assert!(module.get_fn(hash).is_some());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_fn(&self, hash: u64) -> Option<&Box<dyn NativeCallable>> {
|
pub fn get_fn(&self, hash_fn: u64) -> Option<&Box<dyn NativeCallable>> {
|
||||||
self.functions.get(&hash).map(|(_, _, _, v)| v.as_ref())
|
self.functions.get(&hash_fn).map(|(_, _, _, v)| v.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a modules-qualified function.
|
/// Get a modules-qualified function.
|
||||||
@ -549,11 +549,11 @@ impl Module {
|
|||||||
pub(crate) fn get_qualified_fn(
|
pub(crate) fn get_qualified_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
hash: u64,
|
hash_fn_native: u64,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<&Box<dyn NativeCallable>, Box<EvalAltResult>> {
|
) -> Result<&Box<dyn NativeCallable>, Box<EvalAltResult>> {
|
||||||
self.all_functions
|
self.all_functions
|
||||||
.get(&hash)
|
.get(&hash_fn_native)
|
||||||
.map(|f| f.as_ref())
|
.map(|f| f.as_ref())
|
||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorFunctionNotFound(name.to_string(), pos)))
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorFunctionNotFound(name.to_string(), pos)))
|
||||||
}
|
}
|
||||||
@ -575,8 +575,8 @@ impl Module {
|
|||||||
/// Get a modules-qualified script-defined functions.
|
/// Get a modules-qualified script-defined functions.
|
||||||
///
|
///
|
||||||
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
||||||
pub(crate) fn get_qualified_scripted_fn(&mut self, hash: u64) -> Option<&FnDef> {
|
pub(crate) fn get_qualified_scripted_fn(&mut self, hash_fn_def: u64) -> Option<&FnDef> {
|
||||||
self.all_fn_lib.get_function(hash)
|
self.all_fn_lib.get_function(hash_fn_def)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `Module` by evaluating an `AST`.
|
/// Create a new `Module` by evaluating an `AST`.
|
||||||
@ -649,8 +649,8 @@ impl Module {
|
|||||||
// Index all variables
|
// Index all variables
|
||||||
for (var_name, value) in module.variables.iter() {
|
for (var_name, value) in module.variables.iter() {
|
||||||
// Qualifiers + variable name
|
// Qualifiers + variable name
|
||||||
let hash = calc_fn_hash(qualifiers.iter().map(|&v| v), var_name, empty());
|
let hash_var = calc_fn_hash(qualifiers.iter().map(|&v| v), var_name, empty());
|
||||||
variables.push((hash, value.clone()));
|
variables.push((hash_var, value.clone()));
|
||||||
}
|
}
|
||||||
// Index all Rust functions
|
// Index all Rust functions
|
||||||
for (name, access, params, func) in module.functions.values() {
|
for (name, access, params, func) in module.functions.values() {
|
||||||
@ -671,9 +671,9 @@ impl Module {
|
|||||||
// the actual list of parameter `TypeId`'.s
|
// the actual list of parameter `TypeId`'.s
|
||||||
let hash_fn_args = calc_fn_hash(empty(), "", params.iter().cloned());
|
let hash_fn_args = calc_fn_hash(empty(), "", params.iter().cloned());
|
||||||
// 3) The final hash is the XOR of the two hashes.
|
// 3) The final hash is the XOR of the two hashes.
|
||||||
let hash = hash_fn_def ^ hash_fn_args;
|
let hash_fn_native = hash_fn_def ^ hash_fn_args;
|
||||||
|
|
||||||
functions.push((hash, func.clone()));
|
functions.push((hash_fn_native, func.clone()));
|
||||||
}
|
}
|
||||||
// Index all script-defined functions
|
// Index all script-defined functions
|
||||||
for fn_def in module.fn_lib.values() {
|
for fn_def in module.fn_lib.values() {
|
||||||
@ -683,12 +683,12 @@ impl Module {
|
|||||||
DEF_ACCESS => (),
|
DEF_ACCESS => (),
|
||||||
}
|
}
|
||||||
// Qualifiers + function name + placeholders (one for each parameter)
|
// Qualifiers + function name + placeholders (one for each parameter)
|
||||||
let hash = calc_fn_hash(
|
let hash_fn_def = calc_fn_hash(
|
||||||
qualifiers.iter().map(|&v| v),
|
qualifiers.iter().map(|&v| v),
|
||||||
&fn_def.name,
|
&fn_def.name,
|
||||||
repeat(EMPTY_TYPE_ID()).take(fn_def.params.len()),
|
repeat(EMPTY_TYPE_ID()).take(fn_def.params.len()),
|
||||||
);
|
);
|
||||||
fn_lib.push((hash, fn_def.clone()));
|
fn_lib.push((hash_fn_def, fn_def.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,7 +984,7 @@ mod stat {
|
|||||||
self.0
|
self.0
|
||||||
.get(path)
|
.get(path)
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorModuleNotFound(path.to_string(), pos)))
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorModuleNotFound(path.into(), pos)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
/// Add a new constant to the list.
|
/// Add a new constant to the list.
|
||||||
pub fn push_constant(&mut self, name: &str, value: Expr) {
|
pub fn push_constant(&mut self, name: &str, value: Expr) {
|
||||||
self.constants.push((name.to_string(), value))
|
self.constants.push((name.into(), value))
|
||||||
}
|
}
|
||||||
/// Look up a constant from the list.
|
/// Look up a constant from the list.
|
||||||
pub fn find_constant(&self, name: &str) -> Option<&Expr> {
|
pub fn find_constant(&self, name: &str) -> Option<&Expr> {
|
||||||
|
@ -99,15 +99,15 @@ pub fn reg_none<R>(
|
|||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
) {
|
) {
|
||||||
let hash = calc_fn_hash(empty(), fn_name, ([] as [TypeId; 0]).iter().cloned());
|
let hash_fn_native = calc_fn_hash(empty(), fn_name, ([] as [TypeId; 0]).iter().cloned());
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
let f = Box::new(move |_: &mut FnCallArgs, pos| {
|
||||||
let r = func();
|
let r = func();
|
||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions
|
lib.functions
|
||||||
.insert(hash, Box::new(NativeFunction::new(f, Pure)));
|
.insert(hash_fn_native, Box::new(NativeFunction::new(f, Pure)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with one parameter to the package.
|
/// Add a function with one parameter to the package.
|
||||||
@ -148,9 +148,9 @@ pub fn reg_unary<T: Variant + Clone, R>(
|
|||||||
) {
|
) {
|
||||||
//println!("register {}({})", fn_name, crate::std::any::type_name::<T>());
|
//println!("register {}({})", fn_name, crate::std::any::type_name::<T>());
|
||||||
|
|
||||||
let hash = calc_fn_hash(empty(), fn_name, [TypeId::of::<T>()].iter().cloned());
|
let hash_fn_native = calc_fn_hash(empty(), fn_name, [TypeId::of::<T>()].iter().cloned());
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
let f = Box::new(move |args: &mut FnCallArgs, pos| {
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x = mem::take(*drain.next().unwrap()).cast::<T>();
|
let x = mem::take(*drain.next().unwrap()).cast::<T>();
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ pub fn reg_unary<T: Variant + Clone, R>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
lib.functions
|
lib.functions
|
||||||
.insert(hash, Box::new(NativeFunction::new(f, Pure)));
|
.insert(hash_fn_native, Box::new(NativeFunction::new(f, Pure)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with one mutable reference parameter to the package.
|
/// Add a function with one mutable reference parameter to the package.
|
||||||
@ -207,9 +207,9 @@ pub fn reg_unary_mut<T: Variant + Clone, R>(
|
|||||||
) {
|
) {
|
||||||
//println!("register {}(&mut {})", fn_name, crate::std::any::type_name::<T>());
|
//println!("register {}(&mut {})", fn_name, crate::std::any::type_name::<T>());
|
||||||
|
|
||||||
let hash = calc_fn_hash(empty(), fn_name, [TypeId::of::<T>()].iter().cloned());
|
let hash_fn_native = calc_fn_hash(empty(), fn_name, [TypeId::of::<T>()].iter().cloned());
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
let f = Box::new(move |args: &mut FnCallArgs, pos| {
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x: &mut T = drain.next().unwrap().downcast_mut().unwrap();
|
let x: &mut T = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
|
|
||||||
@ -218,7 +218,7 @@ pub fn reg_unary_mut<T: Variant + Clone, R>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
lib.functions
|
lib.functions
|
||||||
.insert(hash, Box::new(NativeFunction::new(f, Method)));
|
.insert(hash_fn_native, Box::new(NativeFunction::new(f, Method)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with two parameters to the package.
|
/// Add a function with two parameters to the package.
|
||||||
@ -259,13 +259,13 @@ pub fn reg_binary<A: Variant + Clone, B: Variant + Clone, R>(
|
|||||||
) {
|
) {
|
||||||
//println!("register {}({}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>());
|
//println!("register {}({}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>());
|
||||||
|
|
||||||
let hash = calc_fn_hash(
|
let hash_fn_native = calc_fn_hash(
|
||||||
empty(),
|
empty(),
|
||||||
fn_name,
|
fn_name,
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
let f = Box::new(move |args: &mut FnCallArgs, pos| {
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
||||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||||
@ -275,7 +275,7 @@ pub fn reg_binary<A: Variant + Clone, B: Variant + Clone, R>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
lib.functions
|
lib.functions
|
||||||
.insert(hash, Box::new(NativeFunction::new(f, Pure)));
|
.insert(hash_fn_native, Box::new(NativeFunction::new(f, Pure)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with two parameters (the first one being a mutable reference) to the package.
|
/// Add a function with two parameters (the first one being a mutable reference) to the package.
|
||||||
@ -323,13 +323,13 @@ pub fn reg_binary_mut<A: Variant + Clone, B: Variant + Clone, R>(
|
|||||||
) {
|
) {
|
||||||
//println!("register {}(&mut {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>());
|
//println!("register {}(&mut {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>());
|
||||||
|
|
||||||
let hash = calc_fn_hash(
|
let hash_fn_native = calc_fn_hash(
|
||||||
empty(),
|
empty(),
|
||||||
fn_name,
|
fn_name,
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
[TypeId::of::<A>(), TypeId::of::<B>()].iter().cloned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
let f = Box::new(move |args: &mut FnCallArgs, pos| {
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||||
@ -339,7 +339,7 @@ pub fn reg_binary_mut<A: Variant + Clone, B: Variant + Clone, R>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
lib.functions
|
lib.functions
|
||||||
.insert(hash, Box::new(NativeFunction::new(f, Method)));
|
.insert(hash_fn_native, Box::new(NativeFunction::new(f, Method)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with three parameters to the package.
|
/// Add a function with three parameters to the package.
|
||||||
@ -361,7 +361,7 @@ pub fn reg_trinary<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R
|
|||||||
) {
|
) {
|
||||||
//println!("register {}({}, {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>(), crate::std::any::type_name::<C>());
|
//println!("register {}({}, {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>(), crate::std::any::type_name::<C>());
|
||||||
|
|
||||||
let hash = calc_fn_hash(
|
let hash_fn_native = calc_fn_hash(
|
||||||
empty(),
|
empty(),
|
||||||
fn_name,
|
fn_name,
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
||||||
@ -369,7 +369,7 @@ pub fn reg_trinary<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R
|
|||||||
.cloned(),
|
.cloned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
let f = Box::new(move |args: &mut FnCallArgs, pos| {
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
||||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||||
@ -380,7 +380,7 @@ pub fn reg_trinary<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R
|
|||||||
});
|
});
|
||||||
|
|
||||||
lib.functions
|
lib.functions
|
||||||
.insert(hash, Box::new(NativeFunction::new(f, Pure)));
|
.insert(hash_fn_native, Box::new(NativeFunction::new(f, Pure)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with three parameters (the first one is a mutable reference) to the package.
|
/// Add a function with three parameters (the first one is a mutable reference) to the package.
|
||||||
@ -402,7 +402,7 @@ pub fn reg_trinary_mut<A: Variant + Clone, B: Variant + Clone, C: Variant + Clon
|
|||||||
) {
|
) {
|
||||||
//println!("register {}(&mut {}, {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>(), crate::std::any::type_name::<C>());
|
//println!("register {}(&mut {}, {}, {})", fn_name, crate::std::any::type_name::<A>(), crate::std::any::type_name::<B>(), crate::std::any::type_name::<C>());
|
||||||
|
|
||||||
let hash = calc_fn_hash(
|
let hash_fn_native = calc_fn_hash(
|
||||||
empty(),
|
empty(),
|
||||||
fn_name,
|
fn_name,
|
||||||
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
[TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]
|
||||||
@ -410,7 +410,7 @@ pub fn reg_trinary_mut<A: Variant + Clone, B: Variant + Clone, C: Variant + Clon
|
|||||||
.cloned(),
|
.cloned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let f = Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
let f = Box::new(move |args: &mut FnCallArgs, pos| {
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||||
@ -421,5 +421,5 @@ pub fn reg_trinary_mut<A: Variant + Clone, B: Variant + Clone, C: Variant + Clon
|
|||||||
});
|
});
|
||||||
|
|
||||||
lib.functions
|
lib.functions
|
||||||
.insert(hash, Box::new(NativeFunction::new(f, Method)));
|
.insert(hash_fn_native, Box::new(NativeFunction::new(f, Method)));
|
||||||
}
|
}
|
||||||
|
@ -989,12 +989,11 @@ fn parse_index_chain<'a>(
|
|||||||
match input.peek().unwrap() {
|
match input.peek().unwrap() {
|
||||||
// If another indexing level, right-bind it
|
// If another indexing level, right-bind it
|
||||||
(Token::LeftBracket, _) => {
|
(Token::LeftBracket, _) => {
|
||||||
let follow_pos = eat_token(input, Token::LeftBracket);
|
let idx_pos = eat_token(input, Token::LeftBracket);
|
||||||
// Recursively parse the indexing chain, right-binding each
|
// Recursively parse the indexing chain, right-binding each
|
||||||
let follow =
|
let idx = parse_index_chain(input, stack, idx_expr, idx_pos, allow_stmt_expr)?;
|
||||||
parse_index_chain(input, stack, idx_expr, follow_pos, allow_stmt_expr)?;
|
|
||||||
// Indexing binds to right
|
// Indexing binds to right
|
||||||
Ok(Expr::Index(Box::new((lhs, follow, pos))))
|
Ok(Expr::Index(Box::new((lhs, idx, pos))))
|
||||||
}
|
}
|
||||||
// Otherwise terminate the indexing chain
|
// Otherwise terminate the indexing chain
|
||||||
_ => Ok(Expr::Index(Box::new((lhs, idx_expr, pos)))),
|
_ => Ok(Expr::Index(Box::new((lhs, idx_expr, pos)))),
|
||||||
|
Loading…
Reference in New Issue
Block a user