Add pure function attribute.
This commit is contained in:
parent
724ad05916
commit
ac1b7debe9
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rhai_codegen"
|
name = "rhai_codegen"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["jhwgh1968"]
|
authors = ["jhwgh1968"]
|
||||||
description = "Procedural macro support package for Rhai, a scripting language for Rust"
|
description = "Procedural macro support package for Rhai, a scripting language for Rust"
|
||||||
|
@ -106,6 +106,7 @@ pub(crate) fn print_type(ty: &syn::Type) -> String {
|
|||||||
pub(crate) struct ExportedFnParams {
|
pub(crate) struct ExportedFnParams {
|
||||||
pub name: Vec<String>,
|
pub name: Vec<String>,
|
||||||
pub return_raw: bool,
|
pub return_raw: bool,
|
||||||
|
pub pure: bool,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
pub special: FnSpecialAccess,
|
pub special: FnSpecialAccess,
|
||||||
pub namespace: FnNamespaceAccess,
|
pub namespace: FnNamespaceAccess,
|
||||||
@ -144,6 +145,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
} = info;
|
} = info;
|
||||||
let mut name = Vec::new();
|
let mut name = Vec::new();
|
||||||
let mut return_raw = false;
|
let mut return_raw = false;
|
||||||
|
let mut pure = false;
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
let mut namespace = FnNamespaceAccess::Unset;
|
let mut namespace = FnNamespaceAccess::Unset;
|
||||||
let mut special = FnSpecialAccess::None;
|
let mut special = FnSpecialAccess::None;
|
||||||
@ -224,6 +226,8 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
}
|
}
|
||||||
|
("pure", None) => pure = true,
|
||||||
|
("pure", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")),
|
||||||
("return_raw", None) => return_raw = true,
|
("return_raw", None) => return_raw = true,
|
||||||
("return_raw", Some(s)) => {
|
("return_raw", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
@ -255,6 +259,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
Ok(ExportedFnParams {
|
Ok(ExportedFnParams {
|
||||||
name,
|
name,
|
||||||
return_raw,
|
return_raw,
|
||||||
|
pure,
|
||||||
skip,
|
skip,
|
||||||
special,
|
special,
|
||||||
namespace,
|
namespace,
|
||||||
@ -746,18 +751,33 @@ impl ExportedFn {
|
|||||||
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(),
|
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(),
|
||||||
p => p,
|
p => p,
|
||||||
};
|
};
|
||||||
let downcast_span = quote_spanned!(
|
let downcast_span = quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> &mut args[0usize].write_lock::<#arg_type>().unwrap());
|
&mut args[0usize].write_lock::<#arg_type>().unwrap()
|
||||||
|
);
|
||||||
unpack_statements.push(
|
unpack_statements.push(
|
||||||
syn::parse2::<syn::Stmt>(quote! {
|
syn::parse2::<syn::Stmt>(quote! {
|
||||||
let #var = #downcast_span;
|
let #var = #downcast_span;
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
if !self.params().pure {
|
||||||
|
let arg_lit_str =
|
||||||
|
syn::LitStr::new(&pat.to_token_stream().to_string(), pat.span());
|
||||||
|
unpack_statements.push(
|
||||||
|
syn::parse2::<syn::Stmt>(quote! {
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant(#arg_lit_str.to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
input_type_names.push(arg_name);
|
input_type_names.push(arg_name);
|
||||||
input_type_exprs.push(
|
input_type_exprs.push(
|
||||||
syn::parse2::<syn::Expr>(quote_spanned!(
|
syn::parse2::<syn::Expr>(quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> TypeId::of::<#arg_type>()
|
TypeId::of::<#arg_type>()
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
@ -793,7 +813,8 @@ impl ExportedFn {
|
|||||||
is_string = true;
|
is_string = true;
|
||||||
is_ref = true;
|
is_ref = true;
|
||||||
quote_spanned!(arg_type.span() =>
|
quote_spanned!(arg_type.span() =>
|
||||||
mem::take(args[#i]).take_immutable_string().unwrap())
|
mem::take(args[#i]).take_immutable_string().unwrap()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => panic!("internal error: why wasn't this found earlier!?"),
|
_ => panic!("internal error: why wasn't this found earlier!?"),
|
||||||
},
|
},
|
||||||
@ -801,13 +822,15 @@ impl ExportedFn {
|
|||||||
is_string = true;
|
is_string = true;
|
||||||
is_ref = false;
|
is_ref = false;
|
||||||
quote_spanned!(arg_type.span() =>
|
quote_spanned!(arg_type.span() =>
|
||||||
mem::take(args[#i]).take_string().unwrap())
|
mem::take(args[#i]).take_string().unwrap()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
is_string = false;
|
is_string = false;
|
||||||
is_ref = false;
|
is_ref = false;
|
||||||
quote_spanned!(arg_type.span() =>
|
quote_spanned!(arg_type.span() =>
|
||||||
mem::take(args[#i]).cast::<#arg_type>())
|
mem::take(args[#i]).cast::<#arg_type>()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -820,15 +843,15 @@ impl ExportedFn {
|
|||||||
input_type_names.push(arg_name);
|
input_type_names.push(arg_name);
|
||||||
if !is_string {
|
if !is_string {
|
||||||
input_type_exprs.push(
|
input_type_exprs.push(
|
||||||
syn::parse2::<syn::Expr>(quote_spanned!(
|
syn::parse2::<syn::Expr>(quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> TypeId::of::<#arg_type>()
|
TypeId::of::<#arg_type>()
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
input_type_exprs.push(
|
input_type_exprs.push(
|
||||||
syn::parse2::<syn::Expr>(quote_spanned!(
|
syn::parse2::<syn::Expr>(quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> TypeId::of::<ImmutableString>()
|
TypeId::of::<ImmutableString>()
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
@ -878,9 +901,7 @@ impl ExportedFn {
|
|||||||
quote! {
|
quote! {
|
||||||
impl PluginFunction for #type_name {
|
impl PluginFunction for #type_name {
|
||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), #arg_count,
|
debug_assert_eq!(args.len(), #arg_count, "wrong arg count: {} != {}", args.len(), #arg_count);
|
||||||
"wrong arg count: {} != {}",
|
|
||||||
args.len(), #arg_count);
|
|
||||||
#(#unpack_statements)*
|
#(#unpack_statements)*
|
||||||
#return_expr
|
#return_expr
|
||||||
}
|
}
|
||||||
|
@ -587,6 +587,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<usize>();
|
let arg1 = mem::take(args[1usize]).cast::<usize>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<usize>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<usize>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0, arg1)))
|
Ok(Dynamic::from(increment(arg0, arg1)))
|
||||||
|
@ -1218,6 +1218,83 @@ mod generate_tests {
|
|||||||
assert_streams_eq(item_mod.generate(), expected_tokens);
|
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mut_ref_pure_fn_module() {
|
||||||
|
let input_tokens: TokenStream = quote! {
|
||||||
|
pub mod ref_fn {
|
||||||
|
#[rhai_fn(pure)]
|
||||||
|
pub fn foo(x: &mut FLOAT, y: INT) -> FLOAT {
|
||||||
|
*x + y as FLOAT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected_tokens = quote! {
|
||||||
|
pub mod ref_fn {
|
||||||
|
pub fn foo(x: &mut FLOAT, y: INT) -> FLOAT {
|
||||||
|
*x + y as FLOAT
|
||||||
|
}
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn rhai_module_generate() -> Module {
|
||||||
|
let mut m = Module::new();
|
||||||
|
rhai_generate_into_module(&mut m, false);
|
||||||
|
m.build_index();
|
||||||
|
m
|
||||||
|
}
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
|
m.set_fn("foo", FnNamespace::Internal, FnAccess::Public,
|
||||||
|
Some(&["x: &mut FLOAT", "y: INT", "FLOAT"]), &[core::any::TypeId::of::<FLOAT>(), core::any::TypeId::of::<INT>()],
|
||||||
|
foo_token().into());
|
||||||
|
if flatten {} else {}
|
||||||
|
}
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
struct foo_token();
|
||||||
|
impl PluginFunction for foo_token {
|
||||||
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
let arg1 = mem::take(args[1usize]).cast::<INT>();
|
||||||
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
|
Ok(Dynamic::from(foo(arg0, arg1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_method_call(&self) -> bool { true }
|
||||||
|
fn is_variadic(&self) -> bool { false }
|
||||||
|
fn clone_boxed(&self) -> Box<dyn PluginFunction> {
|
||||||
|
Box::new(foo_token())
|
||||||
|
}
|
||||||
|
fn input_names(&self) -> Box<[&'static str]> {
|
||||||
|
new_vec!["x: &mut FLOAT", "y: INT"].into_boxed_slice()
|
||||||
|
}
|
||||||
|
fn input_types(&self) -> Box<[TypeId]> {
|
||||||
|
new_vec![TypeId::of::<FLOAT>(), TypeId::of::<INT>()].into_boxed_slice()
|
||||||
|
}
|
||||||
|
fn return_type(&self) -> &'static str {
|
||||||
|
"FLOAT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn foo_token_callable() -> CallableFunction {
|
||||||
|
foo_token().into()
|
||||||
|
}
|
||||||
|
pub fn foo_token_input_names() -> Box<[&'static str]> {
|
||||||
|
foo_token().input_names()
|
||||||
|
}
|
||||||
|
pub fn foo_token_input_types() -> Box<[TypeId]> {
|
||||||
|
foo_token().input_types()
|
||||||
|
}
|
||||||
|
pub fn foo_token_return_type() -> &'static str {
|
||||||
|
foo_token().return_type()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let item_mod = syn::parse2::<Module>(input_tokens).unwrap();
|
||||||
|
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn one_mut_ref_fn_module() {
|
fn one_mut_ref_fn_module() {
|
||||||
let input_tokens: TokenStream = quote! {
|
let input_tokens: TokenStream = quote! {
|
||||||
@ -1255,6 +1332,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0)))
|
Ok(Dynamic::from(increment(arg0)))
|
||||||
}
|
}
|
||||||
@ -1333,6 +1415,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0)))
|
Ok(Dynamic::from(increment(arg0)))
|
||||||
}
|
}
|
||||||
@ -1432,6 +1519,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0)))
|
Ok(Dynamic::from(increment(arg0)))
|
||||||
}
|
}
|
||||||
@ -1530,6 +1622,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0)))
|
Ok(Dynamic::from(int_foo(arg0)))
|
||||||
}
|
}
|
||||||
@ -1607,6 +1704,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0)))
|
Ok(Dynamic::from(int_foo(arg0)))
|
||||||
}
|
}
|
||||||
@ -1683,6 +1785,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
||||||
@ -1763,6 +1870,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
||||||
@ -1842,6 +1954,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
||||||
@ -1927,6 +2044,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
||||||
@ -2008,6 +2130,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 3usize,
|
debug_assert_eq!(args.len(), 3usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 3usize);
|
"wrong arg count: {} != {}", args.len(), 3usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
@ -2097,6 +2224,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 3usize,
|
debug_assert_eq!(args.len(), 3usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 3usize);
|
"wrong arg count: {} != {}", args.len(), 3usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user