Minor code refactors.
This commit is contained in:
parent
42058836ba
commit
c5e2620d0f
@ -1305,7 +1305,7 @@ impl Expr {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/// Is the expression a simple variable access?
|
/// Return the variable name if the expression a simple variable access.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_variable_access(&self, non_qualified: bool) -> Option<&str> {
|
pub(crate) fn get_variable_access(&self, non_qualified: bool) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
|
110
src/fn_call.rs
110
src/fn_call.rs
@ -914,59 +914,6 @@ impl Engine {
|
|||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let args_expr = args_expr.as_ref();
|
let args_expr = args_expr.as_ref();
|
||||||
|
|
||||||
// Handle Fn()
|
|
||||||
if fn_name == KEYWORD_FN_PTR && args_expr.len() == 1 {
|
|
||||||
let hash_fn =
|
|
||||||
calc_native_fn_hash(empty(), fn_name, once(TypeId::of::<ImmutableString>()));
|
|
||||||
|
|
||||||
if !self.has_override(Some(mods), lib, hash_fn, hash_script, pub_only) {
|
|
||||||
// Fn - only in function call style
|
|
||||||
return self
|
|
||||||
.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?
|
|
||||||
.take_immutable_string()
|
|
||||||
.map_err(|typ| {
|
|
||||||
self.make_type_mismatch_err::<ImmutableString>(typ, args_expr[0].position())
|
|
||||||
})
|
|
||||||
.and_then(|s| FnPtr::try_from(s))
|
|
||||||
.map(Into::<Dynamic>::into)
|
|
||||||
.map_err(|err| err.fill_position(args_expr[0].position()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle curry()
|
|
||||||
if fn_name == KEYWORD_FN_PTR_CURRY && args_expr.len() > 1 {
|
|
||||||
let fn_ptr = self.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?;
|
|
||||||
|
|
||||||
if !fn_ptr.is::<FnPtr>() {
|
|
||||||
return Err(self.make_type_mismatch_err::<FnPtr>(
|
|
||||||
self.map_type_name(fn_ptr.type_name()),
|
|
||||||
args_expr[0].position(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let (fn_name, mut fn_curry) = fn_ptr.cast::<FnPtr>().take_data();
|
|
||||||
|
|
||||||
// Append the new curried arguments to the existing list.
|
|
||||||
|
|
||||||
args_expr
|
|
||||||
.iter()
|
|
||||||
.skip(1)
|
|
||||||
.try_for_each(|expr| -> Result<(), Box<EvalAltResult>> {
|
|
||||||
fn_curry.push(self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?);
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
return Ok(FnPtr::new_unchecked(fn_name, fn_curry).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle is_shared()
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
|
||||||
if fn_name == crate::engine::KEYWORD_IS_SHARED && args_expr.len() == 1 {
|
|
||||||
let value = self.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?;
|
|
||||||
|
|
||||||
return Ok(value.is_shared().into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle call() - Redirect function call
|
// Handle call() - Redirect function call
|
||||||
let redirected;
|
let redirected;
|
||||||
let mut args_expr = args_expr.as_ref();
|
let mut args_expr = args_expr.as_ref();
|
||||||
@ -1001,6 +948,58 @@ impl Engine {
|
|||||||
hash_script = calc_script_fn_hash(empty(), name, args_len);
|
hash_script = calc_script_fn_hash(empty(), name, args_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle Fn()
|
||||||
|
if name == KEYWORD_FN_PTR && args_expr.len() == 1 {
|
||||||
|
let hash_fn = calc_native_fn_hash(empty(), name, once(TypeId::of::<ImmutableString>()));
|
||||||
|
|
||||||
|
if !self.has_override(Some(mods), lib, hash_fn, hash_script, pub_only) {
|
||||||
|
// Fn - only in function call style
|
||||||
|
return self
|
||||||
|
.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?
|
||||||
|
.take_immutable_string()
|
||||||
|
.map_err(|typ| {
|
||||||
|
self.make_type_mismatch_err::<ImmutableString>(typ, args_expr[0].position())
|
||||||
|
})
|
||||||
|
.and_then(|s| FnPtr::try_from(s))
|
||||||
|
.map(Into::<Dynamic>::into)
|
||||||
|
.map_err(|err| err.fill_position(args_expr[0].position()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle curry()
|
||||||
|
if name == KEYWORD_FN_PTR_CURRY && args_expr.len() > 1 {
|
||||||
|
let fn_ptr = self.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?;
|
||||||
|
|
||||||
|
if !fn_ptr.is::<FnPtr>() {
|
||||||
|
return Err(self.make_type_mismatch_err::<FnPtr>(
|
||||||
|
self.map_type_name(fn_ptr.type_name()),
|
||||||
|
args_expr[0].position(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (name, mut fn_curry) = fn_ptr.cast::<FnPtr>().take_data();
|
||||||
|
|
||||||
|
// Append the new curried arguments to the existing list.
|
||||||
|
|
||||||
|
args_expr
|
||||||
|
.iter()
|
||||||
|
.skip(1)
|
||||||
|
.try_for_each(|expr| -> Result<(), Box<EvalAltResult>> {
|
||||||
|
fn_curry.push(self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?);
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
return Ok(FnPtr::new_unchecked(name, fn_curry).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is_shared()
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
if name == crate::engine::KEYWORD_IS_SHARED && args_expr.len() == 1 {
|
||||||
|
let value = self.eval_expr(scope, mods, state, lib, this_ptr, &args_expr[0], level)?;
|
||||||
|
|
||||||
|
return Ok(value.is_shared().into());
|
||||||
|
}
|
||||||
|
|
||||||
// Handle is_def_var()
|
// Handle is_def_var()
|
||||||
if name == KEYWORD_IS_DEF_VAR && args_expr.len() == 1 {
|
if name == KEYWORD_IS_DEF_VAR && args_expr.len() == 1 {
|
||||||
let hash_fn = calc_native_fn_hash(empty(), name, once(TypeId::of::<ImmutableString>()));
|
let hash_fn = calc_native_fn_hash(empty(), name, once(TypeId::of::<ImmutableString>()));
|
||||||
@ -1055,8 +1054,9 @@ impl Engine {
|
|||||||
// No arguments
|
// No arguments
|
||||||
args = Default::default();
|
args = Default::default();
|
||||||
} else {
|
} else {
|
||||||
// If the first argument is a variable, and there is no curried arguments, convert to method-call style
|
// If the first argument is a variable, and there is no curried arguments,
|
||||||
// in order to leverage potential &mut first argument and avoid cloning the value
|
// convert to method-call style in order to leverage potential &mut first argument and
|
||||||
|
// avoid cloning the value
|
||||||
if curry.is_empty() && args_expr[0].get_variable_access(false).is_some() {
|
if curry.is_empty() && args_expr[0].get_variable_access(false).is_some() {
|
||||||
// func(x, ...) -> x.func(...)
|
// func(x, ...) -> x.func(...)
|
||||||
arg_values = args_expr
|
arg_values = args_expr
|
||||||
|
@ -1036,9 +1036,9 @@ fn parse_primary(
|
|||||||
match input.peek().unwrap().0 {
|
match input.peek().unwrap().0 {
|
||||||
// Function call
|
// Function call
|
||||||
Token::LeftParen | Token::Bang => {
|
Token::LeftParen | Token::Bang => {
|
||||||
// Once the identifier consumed we must enable next variables capturing
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
{
|
{
|
||||||
|
// Once the identifier consumed we must enable next variables capturing
|
||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
@ -1050,9 +1050,9 @@ fn parse_primary(
|
|||||||
// Namespace qualification
|
// Namespace qualification
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
Token::DoubleColon => {
|
Token::DoubleColon => {
|
||||||
// Once the identifier consumed we must enable next variables capturing
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
{
|
{
|
||||||
|
// Once the identifier consumed we must enable next variables capturing
|
||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
@ -1082,36 +1082,30 @@ fn parse_primary(
|
|||||||
|
|
||||||
match input.peek().unwrap().0 {
|
match input.peek().unwrap().0 {
|
||||||
// Function call is allowed to have reserved keyword
|
// Function call is allowed to have reserved keyword
|
||||||
Token::LeftParen | Token::Bang => {
|
Token::LeftParen | Token::Bang if is_keyword_function(&s) => {
|
||||||
if is_keyword_function(&s) {
|
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_interned_string(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
} else {
|
|
||||||
return Err(PERR::Reserved(s).into_err(settings.pos));
|
|
||||||
}
|
}
|
||||||
|
// Access to `this` as a variable is OK within a function scope
|
||||||
|
_ if s == KEYWORD_THIS && settings.is_function_scope => {
|
||||||
|
let var_name_def = Ident {
|
||||||
|
name: state.get_interned_string(s),
|
||||||
|
pos: settings.pos,
|
||||||
|
};
|
||||||
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
}
|
}
|
||||||
// Access to `this` as a variable is OK
|
// Cannot access to `this` as a variable not in a function scope
|
||||||
_ if s == KEYWORD_THIS => {
|
_ if s == KEYWORD_THIS => {
|
||||||
if !settings.is_function_scope {
|
|
||||||
let msg = format!("'{}' can only be used in functions", s);
|
let msg = format!("'{}' can only be used in functions", s);
|
||||||
return Err(LexError::ImproperSymbol(s, msg).into_err(settings.pos));
|
return Err(LexError::ImproperSymbol(s, msg).into_err(settings.pos));
|
||||||
} else {
|
|
||||||
let var_name_def = Ident {
|
|
||||||
name: state.get_interned_string(s),
|
|
||||||
pos: settings.pos,
|
|
||||||
};
|
|
||||||
Expr::Variable(Box::new((None, None, var_name_def)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ if is_valid_identifier(s.chars()) => {
|
_ if is_valid_identifier(s.chars()) => {
|
||||||
return Err(PERR::Reserved(s).into_err(settings.pos));
|
return Err(PERR::Reserved(s).into_err(settings.pos))
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(LexError::UnexpectedInput(s).into_err(settings.pos));
|
|
||||||
}
|
}
|
||||||
|
_ => return Err(LexError::UnexpectedInput(s).into_err(settings.pos)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1125,9 +1119,7 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(
|
return Err(LexError::UnexpectedInput(token.syntax().to_string()).into_err(settings.pos))
|
||||||
LexError::UnexpectedInput(token.syntax().to_string()).into_err(settings.pos)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2275,6 +2267,12 @@ fn parse_let(
|
|||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let name = state.get_interned_string(name);
|
||||||
|
let var_def = Ident {
|
||||||
|
name: name.clone(),
|
||||||
|
pos,
|
||||||
|
};
|
||||||
|
|
||||||
// let name = ...
|
// let name = ...
|
||||||
let expr = if match_token(input, Token::Equals).0 {
|
let expr = if match_token(input, Token::Equals).0 {
|
||||||
// let name = expr
|
// let name = expr
|
||||||
@ -2283,21 +2281,13 @@ fn parse_let(
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state.stack.push((name, var_type));
|
||||||
|
|
||||||
match var_type {
|
match var_type {
|
||||||
// let name = expr
|
// let name = expr
|
||||||
AccessMode::ReadWrite => {
|
AccessMode::ReadWrite => Ok(Stmt::Let(Box::new(var_def), expr, export, settings.pos)),
|
||||||
let name = state.get_interned_string(name);
|
|
||||||
state.stack.push((name.clone(), AccessMode::ReadWrite));
|
|
||||||
let var_def = Ident { name, pos };
|
|
||||||
Ok(Stmt::Let(Box::new(var_def), expr, export, settings.pos))
|
|
||||||
}
|
|
||||||
// const name = { expr:constant }
|
// const name = { expr:constant }
|
||||||
AccessMode::ReadOnly => {
|
AccessMode::ReadOnly => Ok(Stmt::Const(Box::new(var_def), expr, export, settings.pos)),
|
||||||
let name = state.get_interned_string(name);
|
|
||||||
state.stack.push((name.clone(), AccessMode::ReadOnly));
|
|
||||||
let var_def = Ident { name, pos };
|
|
||||||
Ok(Stmt::Const(Box::new(var_def), expr, export, settings.pos))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user