This commit is contained in:
Stephen Chung 2022-02-23 15:43:27 +08:00
parent dd566ed1e1
commit fa8e2e638b
2 changed files with 38 additions and 33 deletions

View File

@ -85,22 +85,32 @@ pub trait RegisterNativeFunction<Args, Result> {
fn return_type_name() -> &'static str; fn return_type_name() -> &'static str;
} }
#[inline]
#[must_use]
fn is_setter(_fn_name: &str) -> bool {
#[cfg(not(feature = "no_object"))]
if _fn_name.starts_with(crate::engine::FN_SET) {
return true;
}
#[cfg(not(feature = "no_index"))]
if _fn_name.starts_with(crate::engine::FN_IDX_SET) {
return true;
}
false
}
const EXPECT_ARGS: &str = "arguments"; const EXPECT_ARGS: &str = "arguments";
macro_rules! check_constant {
($ctx:ident, $args:ident) => {
#[cfg(any(not(feature = "no_object"), not(feature = "no_index")))]
{
let args_len = $args.len();
if args_len > 0 && $args[0].is_read_only() {
let deny = match $ctx.fn_name() {
#[cfg(not(feature = "no_object"))]
f if args_len == 2 && f.starts_with(crate::engine::FN_SET) => true,
#[cfg(not(feature = "no_index"))]
crate::engine::FN_IDX_SET if args_len == 3 => true,
_ => false,
};
if deny {
return Err(
ERR::ErrorAssignmentToConstant(String::new(), Position::NONE).into(),
);
}
}
}
};
}
macro_rules! def_register { macro_rules! def_register {
() => { () => {
def_register!(imp from_pure :); def_register!(imp from_pure :);
@ -124,11 +134,9 @@ macro_rules! def_register {
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
return Err(ERR::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
}
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
check_constant!(ctx, args);
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )* $($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )*
@ -152,11 +160,9 @@ macro_rules! def_register {
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
return Err(ERR::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
}
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
check_constant!(ctx, args);
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )* $($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )*
@ -180,11 +186,9 @@ macro_rules! def_register {
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
return Err(ERR::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
}
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
check_constant!(ctx, args);
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )* $($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )*
@ -205,11 +209,9 @@ macro_rules! def_register {
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| {
if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) {
return Err(ERR::ErrorAssignmentToConstant(String::new(), Position::NONE).into());
}
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
check_constant!(ctx, args);
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )* $($let $par = ($clone)(_drain.next().expect(EXPECT_ARGS)); )*

View File

@ -1670,9 +1670,12 @@ impl Module {
} }
/// Create a new [`Module`] by evaluating an [`AST`][crate::AST]. /// Create a new [`Module`] by evaluating an [`AST`][crate::AST].
/// ///
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions /// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions to
/// to cross-call each other. Functions in the global namespace, plus all functions /// cross-call each other.
/// defined in the [`Module`], are _merged_ into a _unified_ namespace before each call. ///
/// Functions in the global namespace, plus all functions defined in the [`Module`], are
/// _merged_ into a _unified_ namespace before each call.
///
/// Therefore, all functions will be found. /// Therefore, all functions will be found.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
pub(crate) fn eval_ast_as_new_raw( pub(crate) fn eval_ast_as_new_raw(