Add is_def_var and is_def_fn.

This commit is contained in:
Stephen Chung
2020-10-03 16:25:58 +08:00
parent eec3f4e1bf
commit fbfb7677c1
10 changed files with 220 additions and 56 deletions

View File

@@ -99,7 +99,10 @@ pub const KEYWORD_EVAL: &str = "eval";
pub const KEYWORD_FN_PTR: &str = "Fn";
pub const KEYWORD_FN_PTR_CALL: &str = "call";
pub const KEYWORD_FN_PTR_CURRY: &str = "curry";
#[cfg(not(feature = "no_closure"))]
pub const KEYWORD_IS_SHARED: &str = "is_shared";
pub const KEYWORD_IS_DEF_VAR: &str = "is_def_var";
pub const KEYWORD_IS_DEF_FN: &str = "is_def_fn";
pub const KEYWORD_THIS: &str = "this";
pub const FN_TO_STRING: &str = "to_string";
#[cfg(not(feature = "no_object"))]

View File

@@ -4,8 +4,8 @@ use crate::any::Dynamic;
use crate::calc_fn_hash;
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_SHARED,
KEYWORD_PRINT, KEYWORD_TYPE_OF,
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};
@@ -33,6 +33,9 @@ use crate::engine::{FN_IDX_GET, FN_IDX_SET};
#[cfg(not(feature = "no_object"))]
use crate::engine::{Map, Target, FN_GET, FN_SET};
#[cfg(not(feature = "no_closure"))]
use crate::engine::KEYWORD_IS_SHARED;
#[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "no_function"))]
use crate::scope::Entry as ScopeEntry;
@@ -744,15 +747,18 @@ impl Engine {
.into(),
false,
))
} else if cfg!(not(feature = "no_closure"))
&& _fn_name == KEYWORD_IS_SHARED
&& idx.is_empty()
{
} else if {
#[cfg(not(feature = "no_closure"))]
{
_fn_name == KEYWORD_IS_SHARED && idx.is_empty()
}
#[cfg(feature = "no_closure")]
false
} {
// is_shared call
Ok((target.is_shared().into(), false))
} else {
#[cfg(not(feature = "no_object"))]
let redirected;
let _redirected;
let mut hash = hash_script;
// Check if it is a map method call in OOP style
@@ -761,8 +767,8 @@ impl Engine {
if let Some(val) = map.get(_fn_name) {
if let Some(fn_ptr) = val.read_lock::<FnPtr>() {
// Remap the function name
redirected = fn_ptr.get_fn_name().clone();
_fn_name = &redirected;
_redirected = fn_ptr.get_fn_name().clone();
_fn_name = &_redirected;
// Add curried arguments
if !fn_ptr.curry().is_empty() {
fn_ptr
@@ -877,7 +883,8 @@ impl Engine {
}
// Handle is_shared()
if cfg!(not(feature = "no_closure")) && name == KEYWORD_IS_SHARED && args_expr.len() == 1 {
#[cfg(not(feature = "no_closure"))]
if name == KEYWORD_IS_SHARED && args_expr.len() == 1 {
let expr = args_expr.get(0).unwrap();
let value = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
@@ -917,6 +924,48 @@ impl Engine {
}
}
// Handle is_def_var()
if name == KEYWORD_IS_DEF_VAR && args_expr.len() == 1 {
let hash_fn = calc_fn_hash(empty(), name, 1, once(TypeId::of::<ImmutableString>()));
if !self.has_override(lib, hash_fn, hash_script, pub_only) {
let expr = args_expr.get(0).unwrap();
if let Ok(var_name) = self
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.as_str()
{
return Ok(scope.contains(var_name).into());
}
}
}
// Handle is_def_fn()
if name == KEYWORD_IS_DEF_FN && args_expr.len() == 2 {
let hash_fn = calc_fn_hash(
empty(),
name,
2,
[TypeId::of::<ImmutableString>(), TypeId::of::<INT>()]
.iter()
.cloned(),
);
if !self.has_override(lib, hash_fn, hash_script, pub_only) {
let fn_name_expr = args_expr.get(0).unwrap();
let num_params_expr = args_expr.get(1).unwrap();
if let (Ok(fn_name), Ok(num_params)) = (
self.eval_expr(scope, mods, state, lib, this_ptr, fn_name_expr, level)?
.as_str(),
self.eval_expr(scope, mods, state, lib, this_ptr, num_params_expr, level)?
.as_int(),
) {
let hash = calc_fn_hash(empty(), fn_name, num_params as usize, empty());
return Ok(lib.contains_fn(hash, false).into());
}
}
}
// Handle eval()
if name == KEYWORD_EVAL && args_expr.len() == 1 {
let hash_fn = calc_fn_hash(empty(), name, 1, once(TypeId::of::<ImmutableString>()));

View File

@@ -454,6 +454,9 @@ impl Module {
/// Arguments are simply passed in as a mutable array of `&mut Dynamic`,
/// which is guaranteed to contain enough arguments of the correct types.
///
/// The function is assumed to be a _method_, meaning that the first argument should not be consumed.
/// All other arguments can be consumed.
///
/// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::<T>()`
///
/// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::<T>()`.
@@ -1299,8 +1302,8 @@ impl Module {
.into_iter()
.for_each(|ScopeEntry { value, alias, .. }| {
// Variables with an alias left in the scope become module variables
if alias.is_some() {
module.variables.insert(*alias.unwrap(), value);
if let Some(alias) = alias {
module.variables.insert(*alias, value);
}
});

View File

@@ -2,9 +2,12 @@
use crate::engine::{
Engine, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY,
KEYWORD_IS_SHARED, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF,
KEYWORD_IS_DEF_FN, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_THIS, KEYWORD_TYPE_OF,
};
#[cfg(not(feature = "no_closure"))]
use crate::engine::KEYWORD_IS_SHARED;
use crate::error::LexError;
use crate::parser::INT;
use crate::utils::StaticVec;
@@ -507,9 +510,11 @@ impl Token {
| "await" | "yield" => Reserved(syntax.into()),
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_SHARED | KEYWORD_THIS => {
Reserved(syntax.into())
}
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_DEF_VAR
| KEYWORD_IS_DEF_FN | KEYWORD_THIS => Reserved(syntax.into()),
#[cfg(not(feature = "no_closure"))]
KEYWORD_IS_SHARED => Reserved(syntax.into()),
_ => return None,
})
@@ -1455,7 +1460,9 @@ pub fn is_keyword_function(name: &str) -> bool {
#[cfg(not(feature = "no_closure"))]
KEYWORD_IS_SHARED => true,
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY => true,
| KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY | KEYWORD_IS_DEF_VAR | KEYWORD_IS_DEF_FN => {
true
}
_ => false,
}
}
@@ -1465,7 +1472,8 @@ pub fn is_keyword_function(name: &str) -> bool {
#[inline(always)]
pub fn can_override_keyword(name: &str) -> bool {
match name {
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR => true,
KEYWORD_PRINT | KEYWORD_DEBUG | KEYWORD_TYPE_OF | KEYWORD_EVAL | KEYWORD_FN_PTR
| KEYWORD_IS_DEF_VAR | KEYWORD_IS_DEF_FN => true,
_ => false,
}
}