Minor code refactors.
This commit is contained in:
parent
42058836ba
commit
c5e2620d0f
@ -1305,7 +1305,7 @@ impl Expr {
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
/// Is the expression a simple variable access?
|
||||
/// Return the variable name if the expression a simple variable access.
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_variable_access(&self, non_qualified: bool) -> Option<&str> {
|
||||
match self {
|
||||
|
110
src/fn_call.rs
110
src/fn_call.rs
@ -914,59 +914,6 @@ impl Engine {
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
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
|
||||
let redirected;
|
||||
let mut args_expr = args_expr.as_ref();
|
||||
@ -1001,6 +948,58 @@ impl Engine {
|
||||
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()
|
||||
if name == KEYWORD_IS_DEF_VAR && args_expr.len() == 1 {
|
||||
let hash_fn = calc_native_fn_hash(empty(), name, once(TypeId::of::<ImmutableString>()));
|
||||
@ -1055,8 +1054,9 @@ impl Engine {
|
||||
// No arguments
|
||||
args = Default::default();
|
||||
} else {
|
||||
// If the first argument is a variable, and there is no curried arguments, convert to method-call style
|
||||
// in order to leverage potential &mut first argument and avoid cloning the value
|
||||
// If the first argument is a variable, and there is no curried arguments,
|
||||
// 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() {
|
||||
// func(x, ...) -> x.func(...)
|
||||
arg_values = args_expr
|
||||
|
@ -1036,9 +1036,9 @@ fn parse_primary(
|
||||
match input.peek().unwrap().0 {
|
||||
// Function call
|
||||
Token::LeftParen | Token::Bang => {
|
||||
// Once the identifier consumed we must enable next variables capturing
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
{
|
||||
// Once the identifier consumed we must enable next variables capturing
|
||||
state.allow_capture = true;
|
||||
}
|
||||
let var_name_def = Ident {
|
||||
@ -1050,9 +1050,9 @@ fn parse_primary(
|
||||
// Namespace qualification
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Token::DoubleColon => {
|
||||
// Once the identifier consumed we must enable next variables capturing
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
{
|
||||
// Once the identifier consumed we must enable next variables capturing
|
||||
state.allow_capture = true;
|
||||
}
|
||||
let var_name_def = Ident {
|
||||
@ -1082,36 +1082,30 @@ fn parse_primary(
|
||||
|
||||
match input.peek().unwrap().0 {
|
||||
// Function call is allowed to have reserved keyword
|
||||
Token::LeftParen | Token::Bang => {
|
||||
if is_keyword_function(&s) {
|
||||
Token::LeftParen | Token::Bang if is_keyword_function(&s) => {
|
||||
let var_name_def = Ident {
|
||||
name: state.get_interned_string(s),
|
||||
pos: settings.pos,
|
||||
};
|
||||
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 !settings.is_function_scope {
|
||||
let msg = format!("'{}' can only be used in functions", s);
|
||||
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()) => {
|
||||
return Err(PERR::Reserved(s).into_err(settings.pos));
|
||||
}
|
||||
_ => {
|
||||
return Err(LexError::UnexpectedInput(s).into_err(settings.pos));
|
||||
return Err(PERR::Reserved(s).into_err(settings.pos))
|
||||
}
|
||||
_ => return Err(LexError::UnexpectedInput(s).into_err(settings.pos)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1125,9 +1119,7 @@ fn parse_primary(
|
||||
}
|
||||
|
||||
_ => {
|
||||
return Err(
|
||||
LexError::UnexpectedInput(token.syntax().to_string()).into_err(settings.pos)
|
||||
);
|
||||
return Err(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)),
|
||||
};
|
||||
|
||||
let name = state.get_interned_string(name);
|
||||
let var_def = Ident {
|
||||
name: name.clone(),
|
||||
pos,
|
||||
};
|
||||
|
||||
// let name = ...
|
||||
let expr = if match_token(input, Token::Equals).0 {
|
||||
// let name = expr
|
||||
@ -2283,21 +2281,13 @@ fn parse_let(
|
||||
None
|
||||
};
|
||||
|
||||
state.stack.push((name, var_type));
|
||||
|
||||
match var_type {
|
||||
// let name = expr
|
||||
AccessMode::ReadWrite => {
|
||||
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))
|
||||
}
|
||||
AccessMode::ReadWrite => Ok(Stmt::Let(Box::new(var_def), expr, export, settings.pos)),
|
||||
// const name = { expr:constant }
|
||||
AccessMode::ReadOnly => {
|
||||
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))
|
||||
}
|
||||
AccessMode::ReadOnly => Ok(Stmt::Const(Box::new(var_def), expr, export, settings.pos)),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user