Introduce RhaiResult.

This commit is contained in:
Stephen Chung 2021-03-02 15:02:28 +08:00
parent 521c8fad27
commit e3e53bd399
13 changed files with 54 additions and 79 deletions

View File

@ -724,7 +724,7 @@ Breaking changes
----------------
* `Engine::compile_XXX` functions now return `ParseError` instead of `Box<ParseError>`.
* The `RegisterDynamicFn` trait is merged into the `RegisterResultFn` trait which now always returns `Result<Dynamic, Box<EvalAltResult>>`.
* The `RegisterDynamicFn` trait is merged into the `RegisterResultFn` trait which now always returns `RhaiResult`.
* Default maximum limit on levels of nested function calls is fine-tuned and set to a different value.
* Some operator functions are now built in (see _Speed enhancements_ below), so they are available even under `Engine::new_raw`.
* Strings are now immutable. The type `rhai::ImmutableString` is used instead of `std::string::String`. This is to avoid excessive cloning of strings. All native-Rust functions taking string parameters should switch to `rhai::ImmutableString` (which is either `Rc<String>` or `Arc<String>` depending on whether the `sync` feature is used).

View File

@ -1,8 +1,8 @@
//! Built-in implementations for common operators.
use crate::fn_native::{FnCallArgs, NativeCallContext};
use crate::stdlib::{any::TypeId, boxed::Box, format, string::ToString};
use crate::{Dynamic, EvalAltResult, ImmutableString, INT};
use crate::stdlib::{any::TypeId, format, string::ToString};
use crate::{Dynamic, ImmutableString, RhaiResult, INT};
#[cfg(not(feature = "no_float"))]
use crate::FLOAT;
@ -19,7 +19,7 @@ pub fn get_builtin_binary_op_fn(
op: &str,
x: &Dynamic,
y: &Dynamic,
) -> Option<fn(NativeCallContext, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>> {
) -> Option<fn(NativeCallContext, &mut FnCallArgs) -> RhaiResult> {
let type1 = x.type_id();
let type2 = y.type_id();
@ -792,7 +792,7 @@ pub fn get_builtin_op_assignment_fn(
op: &str,
x: &Dynamic,
y: &Dynamic,
) -> Option<fn(NativeCallContext, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>> {
) -> Option<fn(NativeCallContext, &mut FnCallArgs) -> RhaiResult> {
let type1 = x.type_id();
let type2 = y.type_id();

View File

@ -25,8 +25,8 @@ use crate::stdlib::{
use crate::syntax::CustomSyntax;
use crate::utils::{get_hasher, StraightHasherBuilder};
use crate::{
calc_native_fn_hash, Dynamic, EvalAltResult, FnPtr, ImmutableString, Module, Position, Scope,
Shared, StaticVec,
calc_native_fn_hash, Dynamic, EvalAltResult, FnPtr, ImmutableString, Module, Position,
RhaiResult, Scope, Shared, StaticVec,
};
#[cfg(not(feature = "no_index"))]
@ -1385,7 +1385,7 @@ impl Engine {
expr: &Expr,
level: usize,
new_val: Option<((Dynamic, Position), (&str, Position))>,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let (crate::ast::BinaryExpr { lhs, rhs }, chain_type, op_pos) = match expr {
Expr::Index(x, pos) => (x.as_ref(), ChainType::Index, *pos),
Expr::Dot(x, pos) => (x.as_ref(), ChainType::Dot, *pos),
@ -1649,7 +1649,7 @@ impl Engine {
lhs: &Expr,
rhs: &Expr,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
self.inc_operations(state, rhs.position())?;
let lhs_value = self.eval_expr(scope, mods, state, lib, this_ptr, lhs, level)?;
@ -1707,7 +1707,7 @@ impl Engine {
this_ptr: &mut Option<&mut Dynamic>,
expr: &Expr,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
self.inc_operations(state, expr.position())?;
let result = match expr {
@ -1876,7 +1876,7 @@ impl Engine {
statements: &[Stmt],
restore: bool,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let mut _has_imports = false;
let prev_always_search = state.always_search;
let prev_scope_len = scope.len();
@ -1992,7 +1992,7 @@ impl Engine {
this_ptr: &mut Option<&mut Dynamic>,
stmt: &Stmt,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
self.inc_operations(state, stmt.position())?;
let result = match stmt {
@ -2467,21 +2467,13 @@ impl Engine {
/// [`Position`] in [`EvalAltResult`] may be None and should be set afterwards.
#[cfg(feature = "unchecked")]
#[inline(always)]
fn check_data_size(
&self,
result: Result<Dynamic, Box<EvalAltResult>>,
_pos: Position,
) -> Result<Dynamic, Box<EvalAltResult>> {
fn check_data_size(&self, result: RhaiResult, _pos: Position) -> RhaiResult {
result
}
/// Check a result to ensure that the data size is within allowable limit.
#[cfg(not(feature = "unchecked"))]
fn check_data_size(
&self,
result: Result<Dynamic, Box<EvalAltResult>>,
pos: Position,
) -> Result<Dynamic, Box<EvalAltResult>> {
fn check_data_size(&self, result: RhaiResult, pos: Position) -> RhaiResult {
// Simply return all errors
if result.is_err() {
return result;

View File

@ -13,7 +13,7 @@ use crate::stdlib::{
};
use crate::{
scope::Scope, Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, Module, NativeCallContext,
ParseError, Position, Shared, AST,
ParseError, Position, RhaiResult, Shared, AST,
};
#[cfg(not(feature = "no_index"))]
@ -217,7 +217,7 @@ impl Engine {
/// impl TestStruct {
/// fn new() -> Self { Self { field: 1 } }
/// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self) -> Result<Dynamic, Box<EvalAltResult>> {
/// fn get_field(&mut self) -> RhaiResult {
/// Ok(self.field.into())
/// }
/// }
@ -241,7 +241,7 @@ impl Engine {
pub fn register_get_result<T: Variant + Clone>(
&mut self,
name: &str,
get_fn: impl Fn(&mut T) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static,
get_fn: impl Fn(&mut T) -> RhaiResult + SendSync + 'static,
) -> &mut Self {
use crate::{engine::make_getter, RegisterResultFn};
self.register_result_fn(&make_getter(name), get_fn)
@ -474,7 +474,7 @@ impl Engine {
/// impl TestStruct {
/// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
/// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self, index: i64) -> Result<Dynamic, Box<EvalAltResult>> {
/// fn get_field(&mut self, index: i64) -> RhaiResult {
/// Ok(self.fields[index as usize].into())
/// }
/// }
@ -499,7 +499,7 @@ impl Engine {
#[inline(always)]
pub fn register_indexer_get_result<T: Variant + Clone, X: Variant + Clone>(
&mut self,
get_fn: impl Fn(&mut T, X) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static,
get_fn: impl Fn(&mut T, X) -> RhaiResult + SendSync + 'static,
) -> &mut Self {
if TypeId::of::<T>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
@ -1518,7 +1518,7 @@ impl Engine {
mods: &mut Imports,
ast: &'a AST,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let mut state: State = Default::default();
state.source = ast.clone_source();
#[cfg(not(feature = "no_module"))]
@ -1733,7 +1733,7 @@ impl Engine {
name: &str,
mut this_ptr: Option<&mut Dynamic>,
mut arg_values: impl AsMut<[Dynamic]>,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let mut args: crate::StaticVec<_> = arg_values.as_mut().iter_mut().collect();
self.call_fn_dynamic_raw(scope, ast, eval_ast, name, &mut this_ptr, args.as_mut())
@ -1756,7 +1756,7 @@ impl Engine {
name: &str,
this_ptr: &mut Option<&mut Dynamic>,
args: &mut FnCallArgs,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let state = &mut Default::default();
let mods = &mut Default::default();
let lib = &[ast.lib()];

View File

@ -24,6 +24,7 @@ use crate::utils::combine_hashes;
use crate::{
ast::{Expr, Stmt},
fn_native::CallableFunction,
RhaiResult,
};
use crate::{
calc_native_fn_hash, calc_script_fn_hash, Dynamic, Engine, EvalAltResult, FnPtr,
@ -468,7 +469,7 @@ impl Engine {
args: &mut FnCallArgs,
pos: Position,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
#[inline(always)]
fn make_error(
name: crate::stdlib::string::String,
@ -476,7 +477,7 @@ impl Engine {
state: &State,
err: Box<EvalAltResult>,
pos: Position,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
Err(Box::new(EvalAltResult::ErrorInFunctionCall(
name,
fn_def
@ -817,7 +818,7 @@ impl Engine {
statements: &[Stmt],
lib: &[&Module],
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
self.eval_stmt_block(scope, mods, state, lib, &mut None, statements, false, level)
.or_else(|err| match *err {
EvalAltResult::Return(out, _) => Ok(out),
@ -838,7 +839,7 @@ impl Engine {
script: &str,
pos: Position,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
self.inc_operations(state, pos)?;
let script = script.trim();
@ -1026,7 +1027,7 @@ impl Engine {
pos: Position,
capture_scope: bool,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let args_expr = args_expr.as_ref();
// Handle call() - Redirect function call
@ -1276,7 +1277,7 @@ impl Engine {
hash_script: NonZeroU64,
pos: Position,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let args_expr = args_expr.as_ref();
let namespace = namespace.unwrap();

View File

@ -15,7 +15,7 @@ use crate::stdlib::{
use crate::token::is_valid_identifier;
use crate::{
calc_script_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ImmutableString, Module,
Position,
Position, RhaiResult,
};
#[cfg(not(feature = "sync"))]
@ -185,7 +185,7 @@ impl<'e, 'n, 's, 'a, 'm> NativeCallContext<'e, 'n, 's, 'a, 'm> {
fn_name: &str,
is_method: bool,
args: &mut [&mut Dynamic],
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
self.engine()
.exec_fn_call(
&mut self.mods.cloned().unwrap_or_default(),
@ -317,7 +317,7 @@ impl FnPtr {
ctx: NativeCallContext,
this_ptr: Option<&mut Dynamic>,
mut arg_values: impl AsMut<[Dynamic]>,
) -> Result<Dynamic, Box<EvalAltResult>> {
) -> RhaiResult {
let arg_values = arg_values.as_mut();
let mut args_data = self
@ -381,11 +381,10 @@ impl TryFrom<&str> for FnPtr {
/// A general function trail object.
#[cfg(not(feature = "sync"))]
pub type FnAny = dyn Fn(NativeCallContext, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
pub type FnAny = dyn Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResult;
/// A general function trail object.
#[cfg(feature = "sync")]
pub type FnAny =
dyn Fn(NativeCallContext, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
pub type FnAny = dyn Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResult + Send + Sync;
/// A standard function that gets an iterator from a type.
pub type IteratorFn = fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;

View File

@ -7,7 +7,7 @@ use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
use crate::r#unsafe::unsafe_cast_box;
use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String};
use crate::{
Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, NativeCallContext,
Dynamic, Engine, FnAccess, FnNamespace, ImmutableString, NativeCallContext, RhaiResult,
};
/// Trait to register custom functions with the [`Engine`].
@ -52,7 +52,7 @@ pub trait RegisterResultFn<FN, ARGS> {
/// use rhai::{Engine, Dynamic, RegisterResultFn, EvalAltResult};
///
/// // Normal function
/// fn div(x: i64, y: i64) -> Result<Dynamic, Box<EvalAltResult>> {
/// fn div(x: i64, y: i64) -> RhaiResult {
/// if y == 0 {
/// // '.into()' automatically converts to 'Box<EvalAltResult::ErrorRuntime>'
/// Err("division by zero!".into())
@ -142,15 +142,13 @@ macro_rules! make_func {
/// To Dynamic mapping function.
#[inline(always)]
pub fn map_dynamic(data: impl Variant + Clone) -> Result<Dynamic, Box<EvalAltResult>> {
pub fn map_dynamic(data: impl Variant + Clone) -> RhaiResult {
Ok(data.into_dynamic())
}
/// To Dynamic mapping function.
#[inline(always)]
pub fn map_result(
data: Result<Dynamic, Box<EvalAltResult>>,
) -> Result<Dynamic, Box<EvalAltResult>> {
pub fn map_result(data: RhaiResult) -> RhaiResult {
data
}
@ -197,7 +195,7 @@ macro_rules! def_register {
impl<
$($par: Variant + Clone,)*
FN: Fn($($param),*) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static,
FN: Fn($($param),*) -> RhaiResult + SendSync + 'static,
> RegisterResultFn<FN, ($($mark,)*)> for Engine
{
#[inline]

View File

@ -88,6 +88,8 @@ mod token;
mod r#unsafe;
mod utils;
pub type RhaiResult = Result<Dynamic, Box<EvalAltResult>>;
/// The system integer type. It is defined as [`i64`].
///
/// If the `only_i32` feature is enabled, this will be [`i32`] instead.

View File

@ -4,7 +4,7 @@ pub use crate::fn_native::{CallableFunction, FnCallArgs};
pub use crate::stdlib::{any::TypeId, boxed::Box, format, mem, string::ToString, vec as new_vec};
pub use crate::{
Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, Module,
NativeCallContext, Position, RegisterFn, RegisterResultFn,
NativeCallContext, Position, RegisterFn, RegisterResultFn, RhaiResult,
};
#[cfg(not(features = "no_module"))]
@ -18,11 +18,7 @@ pub use rhai_codegen::{export_fn, register_exported_fn};
/// Use the `#[export_module]` and `#[export_fn]` procedural attributes instead.
pub trait PluginFunction {
/// Call the plugin function with the arguments provided.
fn call(
&self,
context: NativeCallContext,
args: &mut FnCallArgs,
) -> Result<Dynamic, Box<EvalAltResult>>;
fn call(&self, context: NativeCallContext, args: &mut FnCallArgs) -> RhaiResult;
/// Is this plugin function a method?
fn is_method_call(&self) -> bool;

View File

@ -79,7 +79,7 @@ impl DynamicSerializer {
/// # Ok(())
/// # }
/// ```
pub fn to_dynamic<T: Serialize>(value: T) -> Result<Dynamic, Box<EvalAltResult>> {
pub fn to_dynamic<T: Serialize>(value: T) -> RhaiResult {
let mut s = DynamicSerializer::new(Default::default());
value.serialize(&mut s)
}
@ -690,7 +690,7 @@ impl serde::ser::SerializeStructVariant for StructVariantSerializer {
}
#[cfg(not(feature = "no_object"))]
fn make_variant(variant: &'static str, value: Dynamic) -> Result<Dynamic, Box<EvalAltResult>> {
fn make_variant(variant: &'static str, value: Dynamic) -> RhaiResult {
let mut map = Map::with_capacity(1);
map.insert(variant.into(), value);
Ok(map.into())

View File

@ -6,8 +6,7 @@ use crate::fn_native::SendSync;
use crate::stdlib::{boxed::Box, format, string::ToString};
use crate::token::{is_valid_identifier, Token};
use crate::{
Dynamic, Engine, EvalAltResult, ImmutableString, LexError, ParseError, Position, Shared,
StaticVec,
Engine, ImmutableString, LexError, ParseError, Position, RhaiResult, Shared, StaticVec,
};
pub const MARKER_EXPR: &str = "$expr$";
@ -16,12 +15,10 @@ pub const MARKER_IDENT: &str = "$ident$";
/// A general expression evaluation trait object.
#[cfg(not(feature = "sync"))]
pub type FnCustomSyntaxEval =
dyn Fn(&mut EvalContext, &[Expression]) -> Result<Dynamic, Box<EvalAltResult>>;
pub type FnCustomSyntaxEval = dyn Fn(&mut EvalContext, &[Expression]) -> RhaiResult;
/// A general expression evaluation trait object.
#[cfg(feature = "sync")]
pub type FnCustomSyntaxEval =
dyn Fn(&mut EvalContext, &[Expression]) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
pub type FnCustomSyntaxEval = dyn Fn(&mut EvalContext, &[Expression]) -> RhaiResult + Send + Sync;
/// A general expression parsing trait object.
#[cfg(not(feature = "sync"))]
@ -68,10 +65,7 @@ impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> {
///
/// This function is very low level. It evaluates an expression from an [`AST`][crate::AST].
#[inline(always)]
pub fn eval_expression_tree(
&mut self,
expr: &Expression,
) -> Result<Dynamic, Box<EvalAltResult>> {
pub fn eval_expression_tree(&mut self, expr: &Expression) -> RhaiResult {
self.engine.eval_expr(
self.scope,
self.mods,
@ -113,9 +107,7 @@ impl Engine {
&mut self,
keywords: &[S],
new_vars: isize,
func: impl Fn(&mut EvalContext, &[Expression]) -> Result<Dynamic, Box<EvalAltResult>>
+ SendSync
+ 'static,
func: impl Fn(&mut EvalContext, &[Expression]) -> RhaiResult + SendSync + 'static,
) -> Result<&mut Self, ParseError> {
let keywords = keywords.as_ref();
@ -234,9 +226,7 @@ impl Engine {
+ SendSync
+ 'static,
new_vars: isize,
func: impl Fn(&mut EvalContext, &[Expression]) -> Result<Dynamic, Box<EvalAltResult>>
+ SendSync
+ 'static,
func: impl Fn(&mut EvalContext, &[Expression]) -> RhaiResult + SendSync + 'static,
) -> &mut Self {
let syntax = CustomSyntax {
parse: Box::new(parse),

View File

@ -1,12 +1,9 @@
use rhai::{Dynamic, Engine, EvalAltResult, NativeCallContext, INT};
use rhai::{Dynamic, Engine, EvalAltResult, NativeCallContext, RhaiResult, INT};
use std::any::TypeId;
#[test]
fn test_native_context() -> Result<(), Box<EvalAltResult>> {
fn add_double(
context: NativeCallContext,
args: &mut [&mut Dynamic],
) -> Result<Dynamic, Box<EvalAltResult>> {
fn add_double(context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult {
let x = args[0].as_int().unwrap();
let y = args[1].as_int().unwrap();
Ok(format!("{}_{}", context.fn_name(), x + 2 * y).into())

View File

@ -18,7 +18,7 @@ mod test {
#[rhai_fn(get = "foo", return_raw)]
#[inline(always)]
pub fn foo(array: &mut Array) -> Result<Dynamic, Box<EvalAltResult>> {
pub fn foo(array: &mut Array) -> RhaiResult {
Ok(array[0].clone())
}
}