- The binary bit-wise operators
&,|and^now work correctly withINToperands (#1037). - The methods
contains,get,filterandto_jsonfor object maps are now marked pure (#1037). - The methods
contains,get,parse_le_int,parse_be_int,parse_le_floatandparse_be_floatfor BLOB's are now marked pure (#1037). Ecan now be used in scientific notation for floating-point and decimal literals (thanks@BrynCooke#1039).- The
drainandretainmethods for object maps no longer empty the target map upon errors (#1043). - Using a reserved keyword as a function parameter now returns the
VariableExpectedparser error (thanks@TheAwiteb#1047).
- The method
mapis added to object maps. - The string methods
starts_withandends_withnow work with character argument (#1042).
This version is the same as version 1.23.6 but maintains compatibility by restricting the
ahash dependency to <=0.8.11 because higher versions break
no-std builds.
- (Fuzzing) Fixed crash when using
..=in arrays, BLOB's, bit-fields and iterators (#1004). - Modules loaded within a
ModuleResolversCollectionnow properly enable access to thescopeetc. - Registered functions for comparison operators with only one operand being a custom type now works properly (thanks
@mkeeter#1003). NativeCallContext::fn_sourcenow correctly returns the source of the function (usuallyNone). The missingNativeCallContext::call_sourceis added to return the source of caller (thanks@FlashSystems#1013).Engine::collect_fn_metadatanow properly includes functions registered into the global namespace (thanks@therealprofand@matthiasbeyer#1017).
build.rsno longer writes to the source tree butOUT_DIRinstead (thanks@matthiasbeyer#1018)CustomTypederive macro now supports generic types (thanks@ProphetOSpam#999). Therhai_codegencrate dependency is bumped to3.0.0or later.CustomTypederive macro now handlesOptionfields (thanks@agersant#1011).Engine::eval_fn_callis added to make a generic function call.Engine::eval_binary_opis added to quickly compare twoDynamicvalues.- Better handling for 32-bit architectures and enhanced safety by replacing casts with
try_from(thanks@therealprof#1009). - The new symbol types
$token$,$inner$, and$raw$can now be used in custom syntax definitions (#1023). Engine::register_custom_syntax_without_look_ahead_rawis added to allow the use of$raw$in custom syntax, which returns the script text character-by-character without processing, by-passing the tokenizer. This in turn allows for parsing arbitrary syntax. (#1022)CallFnOptions::in_all_namespacesis added to allow calling functions in all namespaces, instead of only scripted Rhai functions in theAST.
This version is the same as version 1.23.4 but maintains compatibility by restricting the
ahash dependency to <=0.8.11 because higher versions break
no-std builds.
This version removes the version restriction on ahash which may break code for no-std builds.
- Do not mask out version 0.8.11 for
ahash.
- (Fuzzing) An integer-overflow bug from an inclusive range in
get_bitsis fixed (#963). - (Fuzzing) Nested functions marked
privatenow properly cause compilation errors (#993). - Passing function as a function pointer into a function in an imported module now correctly encapsulates the current environment into the generated function pointer (thanks
@dcihlar#976). The same for passing a closure (thanks again,@dcihlar#979). - Revised epsilon-based floating-point comparisons (thanks
@HactarCE#981). - Unneeded optional dependencies are no longer pulled in with features (thanks
@HactarCE#987). Engine::collect_fn_metadatanow properly includes the namespaces of functions in static modules (thanks@therealprofand@elkowar#992).
- Improve display of function call errors by displaying the caller function's source together with line number info (thanks
@rhizoomeand@HactarCE#988). sourceandpositioninNativeCallContextare nowfn_sourceandcall_position. A new methodcall_sourceis added to return the source (if any) of the caller function (thanks@rhizoomeand@HactarCE#989).- The
&&,||and??operators are optimized to allow efficient chaining (#994).
- Fixed bug in raw strings (thanks
@benatkin#944). get_fn_metadata_listfunction is markedvolatile.no-stdplussyncshould now build correctly (thanksstargazing-dino#947).
- It is possible to create a function pointer (
FnPtr) which binds to a native Rust function or closure viaFnPtr::from_dnandFnPtr::from_dyn_fn. When called in script, the embedded function will be called (thanks@makspll#952).
- The methods
call_fn,call_native_fn,call_fn_rawandcall_native_fn_raware added toEvalContext(thanks@rawhuul#954). - A new
internalsfunction,Engine::collect_fn_metadata, is added to collect all functions metadata. This is to facilitate better error reporting for missing functions (thankstherealprof#945).
- If a string slice refers to the entire string, the slice is not cloned but returned as-is.
- (Fuzzing) An integer-overflow bug from an inclusive range in the bits iterator is fixed.
- (Fuzzing) An integer-underflow bug from an inclusive range is fixed.
- Copy strings if the strings interner is busy instead of panicing (thanks
@irevoire#917). - Deserialization of
Scopenow works correctly (thanks@AngelicosPhosphoros#918). - Support for
thumbv6mtarget is fixed (thankschxry#919)
- Added support for raw strings with the syntax
##..#" ... "#..##(thanks@cellomath#908 #910).
- New
as_immutable_string_ref,as_array_ref,as_blob_ref,as_map_refplus their_mutvariants forDynamic(thanks@madonuko#904). - The
break,returnandthrowstatements can now be simply used asswitchcase statement expressions. Previously it is required that the statement be wrapped in a block.
- Variable resolver now correctly resolves variables that are captured in a closure.
NativeCallContext<'_>(with a lifetime parameter) now parses correctly in the#[export_module]macro. This is to allow forrust_2018_idiomslints (thanks@ltabis#864).- The
syncfeature now works properly inno-stdbuilds (thanks@misssonder#874). - More data-race conditions are caught and returned as errors instead of panicking.
- Missing
minandmaxfunctions where both operands are floats orDecimalare added. - Fixed stack overflow when calling closures recursively (thanks
@MageWeiG#880). Engine::call_fnandEngine::call_fn_with_optionsnow correctly use theAST'ssourcefield.- (Fuzzing) Fixed crash when using
..=in strings. - (Fuzzing) A recursive stack-overflow bug in
Dynamic::is_hashableis fixed.
- The
break,continue,returnandthrowstatements can now follow the??operator to short-circuit operations where the value is(). - A new symbol,
$func$, is added to custom syntax to allow parsing of anonymous functions. - The
filter,drainandretainmethods are added to object maps.
Starting from this version, we try to put contributors' names on features/enhancements/fixes that they contributed. We apologize for neglecting to adopt this practice earlier, but late is better than never!
- The position of an undefined operation call now points to the operator instead of the first operand.
- The
optimizecommand inrhai-replnow works properly and cycles throughNone->Simple->Full. Engine::call_fn_XXXno longer return errors unnecessarily wrapped inEvalAltResult::ErrorInFunctionCall.- Some tests that panic on 32-bit architecture are fixed (thanks
@alexanderkjall#851). - The optimizer no longer goes into an infinite loop when optimizing a
trystatement with an empty body.
- The plugin macros
export_fn,register_exported_fn!,set_exported_fn!andset_exported_global_fn!are deprecated because they do not add value over existing direct API's.
- Sub-strings can now be selected from full strings by indexing via ranges, e.g.
s[1..4](thanks@zitsen#845). - Doc-comments are now automatically added to function registrations and custom types via the
CustomTypederive macro (thanks@Itabis#847). - New options
Engine::set_max_strings_internedandEngine::max_strings_internedare added to limit the maximum number of strings interned in theEngine's string interner. - A new advanced callback,
Engine::on_invalid_array_index, is added (gated under theinternalsfeature) to handle access to missing properties in object maps. - A new advanced callback,
Engine::on_missing_map_property, is added (gated under theinternalsfeature) to handle out-of-bound index into arrays.
parse_jsonis also available without themetadataorserdefeature -- it usesEngine::parse_jsonto parse the JSON text (thanks@Mathieu-Lala#840).FuncRegistration::in_global_namespaceandFuncRegistration::in_internal_namespaceare added to avoid pulling inFnNamespace.- Array/BLOB/string iterators are defined also within the
BasicIteratorPackagein addition to the regular array/BLOB/string packages. LexError::Runtimeis added for use withEngine::on_parse_token.- Shared values under
syncare now handled more elegantly -- instead of deadlocking and hanging indefinitely, it spins for a number of tries (waiting one second between each), then errors out.
- The engine no longer crashes when accessing a property or indexed item from a shared value returned from a variables resolver.
This is a bug-fix release that bumps rhai_codegen version to 2.0.0 to satisfy semver rules.
Starting from this version, the official preferred method of registering an API for a custom type is via the #[derive(CustomType)] macro. The old API is still available for types that reside in external crates (and thus cannot implement CustomType).
Starting from this version, the new FuncRegistration API is preferred for registering native Rust functions into a Module. The old API is still available but deprecated.
Starting from this version, fuzzing via Google OSS-Fuzz is used to flush out hidden bugs and edge cases. This should result in higher code quality, better stability and improved security. And indeed, a large number of bugs have been discovered from this and fixed.
ImmutableStringnow derefs to&strinstead of&SmartString. Normally this should not be a breaking change.- Traits implemented by
ImmutableStringare cleaned up. Normally this should not be a breaking change. EvalContext::new,FloatWrapperandConditionalExprare now gated underinternals.- Previously, Rhai follows Unicode's definition for whitespace, which allows many exotic whitespace characters in scripts. Starting from this version, whitespace follows WhatWG's definition of five ASCII characters (TAB, SPACE, CR, LF and FF), which is the same as Rust. All other Unicode whitespace characters (not inside strings) are not considered whitespace by Rhai. If a script used to contain non-ASCII whitespace characters, it now fails to parse with a syntax error.
- Great thanks to
@silvergaspfor setting up fuzzing. #[derive(CustomType)]is now available, driven by procedural macros inrhai_codegen(thanks@MavethGH#817).- A new
FuncRegistrationAPI is added to assist in registering native Rust functions into modules with various settings. Some of the originalModule::set_fn...API is now deprecated. - Functions defined in plugin modules can now be marked as
volatilewhich prevents it from being optimized away even underOptimizationLevel::Full. - Added
Engine::max_functionsandEngine::set_max_functionsto limit the maximum number of functions allowed in a script. This is to guard against DOS attacks -- e.g. a simple closure||(two characters) is a function. Whenmax_functionis exceeded during script compilation, a new parse error,ParseErrorType::TooManyFunctions, is returned. Engine::get_interned_stringis made public instead of gated underinternals.
rhai::config::hashing::set_ahash_seed,rhai::config::hashing::get_ahash_seedand theRHAI_AHASH_SEEDenvironment variable are deprecated in favor ofrhai::config::hashing::set_hashing_seed,rhai::config::hashing::get_hashing_seedandRHAI_HASHING_SEED.AST::clear_docis deprecated.- Much of the
Module::update_XXXAPI is deprecated in favor of using theFuncRegistrationAPI. Module::gen_fn_signaturesis deprecated in favor ofModule::gen_fn_signatures_with_mapper.
- Fixed crash when parsing multi-segment interpolated string longer than maximum.
- Fixed crash when parsing unterminated comment.
- Fixed crash when parsing deeply-nested right-associated operators such as
**. - Fixed crash when parsing combo-chaining expressions such as
(a.b).c. - Fixed crash when calling functions that have
Dynamicparameters with more than 16 parameters. - Fixed crash when indexing into an empty array with negative index.
- Indexing into an array with a negative index that is larger than the length of the array now throws an out-of-bounds error (similar to positive indices) instead of defaulting to the first element.
- Fixed edge-case crash in timestamp functions.
- Fixed crash when indenting a block doc-comment with Unicode multi-byte space characters.
- Fixed improper parsing of numbers with too many decimal points.
- Fixed exponential running time when raising a decimal number to a very large power (> 1 million) -- it now returns an overflow error.
- Shared values that contain reference loops no longer cause a stack overflow when printing.
sleepno longer panics onNaN.switchon ranges now work properly.
- Arrays in object maps now serialize to JSON correctly via
to_json()when theserdefeature is not enabled. Engine::format_map_as_jsonnow serializes arrays correctly.Engine::gen_fn_signatures(false)now properly skips functions in the standard library.TypeBuilder::with_namenow properly sets the display-name of the type for use in generating metadata.
- Avoid cloning values unless needed when performing constants propagation in optimization.
- Added
to_intmethod for characters. Token::FloatConstantandToken::DecimalConstantnow carry the original text representation for use in, say, a token mapper.Dynamic::is_fnptris made a public API.Scope::get_value_refandScope::get_value_mutare added.TypeBuilder::with_namenow takes any&strinstead of just&'static str.Engine::gen_fn_signaturesnow formats the function signatures using pretty-print names of custom types.
Public fields of VarDefInfo are marked deprecated but still accessible.
Fixes compilation error when importing multiple modules.
Fixes compilation error when using the serde feature with metadata.
The minimum Rust compiler version is raised to 1.66.0.
- Limit functions (e.g.
max_operations,max_array_sizeetc.) as well asEngine::ensure_data_size_within_limitsare no longer exported underunchecked. This should be the correct behavior instead of returningNoneor zero. - The type
OptimizationLevelis no longer exported underno_optimize. Originally it was mapped to()underno_optimize. - O/S features such as file access and time are no longer disabled when using
wasm32-wasi(or any WASM target other thanwasm32-unknown).
- Fixes a panic when using
thisas the first parameter in a namespace-qualified function call. - Comparing two different data types (e.g. a custom type and a standard type) now correctly defaults to
false(except for!=which defaults totrue). maxandminfor integers, strings and characters were missing from the standard library. They are now added.
- Minimal version numbers for dependencies are now specified in
Cargo.tomlto avoid breaking changes in future versions. bitflagsis bumped to version 2.syninrhai_codegenis bumped to version 2.hashbrown(used inno-stdbuilds) is bumped to version 0.14.
ParseErrorType::MalformedCallExprandParseErrorType::MalformedInExprare deprecated and will be removed in the next major version.Module::get_custom_typeis deprecated in favor ofModule::get_custom_type_display_by_nameand other new methods.
- New
exitfunction that terminates script evaluation regardless of where it is called, even inside deeply-nested function calls. - Added
Engine::max_variablesandEngine::set_max_variablesto limit the maximum number of variables allowed within a scope at any time. This is to guard against defining a huge number of variables containing large data just beyond individual data size limits. Whenmax_variablesis exceeded a new error,ErrorTooManyVariables, is returned. - Added
zipfunction for arrays. - Added
on_printandon_debugdefinitions forTypeBuilder. - Doc-comments are now included in custom type definitions within plugin modules. They can be accessed via
Module::get_custom_type_raw. These doc-comments for custom types are also exported in JSON viaEngine::gen_fn_metadata_to_json.
once_cellis used instdenvironments instead of the home-brewSusLockwhich is removed.- Originally, unit tests use the
?operator liberally to simplify code. However, this causes the loss of proper line numbers when a test fails, making it difficult to identify the exact location of the failure. This is now fixed by changing tounwrap(). - Many inlined collections are turned back into
Vecbecause they are not transient and do not appear to improve performance. UsingVecseems to be yield better performance as it probably enables more compiler optimizations. - General code clean-up to remove optimizations tricks that are not obviously beneficial in favor of clearer code.
Dynamic::deep_scanis fixed so now it properly scans arrays, object maps and function pointers embedded inside data.
- Fixes a concurrency error in static hashing keys (thanks
garypen!).
- Expressions involving
thisshould now run slightly faster due to a dedicatedASTnodeThisPtr. - A
takefunction is added to the standard library to take ownership of any data (replacing with()) in order to avoid cloning. Dynamic::takeis added to take ownership of the data (replacing with()) in order to avoid cloning.EvalAltResult::ErrorMismatchOutputTypenow gives a better name for the requested generic type (e.g.&stris now&strand notstring).
This new version contains a substantial number of bug fixes for edge cases.
A new syntax is supported to facilitate writing object methods in script.
The code hacks that attempt to optimize branch prediction performance are removed because benchmarks do not show any material speed improvements.
is_sharedis a reserved keyword and is now handled properly (e.g. it cannot be the target of a function pointer).- Re-optimizing an AST via
optimize_astwith constants now works correctly for closures. Previously the hiddenSharenodes are not removed and causes variable-not-found errors during runtime if the constants are not available in the scope. - Expressions such as
(v[0].func()).propnow parse correctly. - Shadowed variable exports are now handled correctly.
- Shadowed constant definitions are now optimized correctly when propagated (e.g.
const X = 1; const X = 1 + 1 + 1; Xnow evaluates to 3 instead of 0). - Identifiers and comma's in the middle of custom syntax now register correctly.
- Exporting an object map from a module with closures defined on properties now works correctly when those properties are called to mimic method calls in OOP-style.
- Compiling for
thumbv6m-none-eabitarget (e.g. Raspberry Pi Pico) now completes successfully. Dependency tono-std-compatis now pointed to the latest repo instead ofcrates.io.
- It is now possible to require a specific type to the
thispointer for a particular script-defined function so that it is called only when thethispointer contains the specified type. is_def_fnis extended to support checking for typed methods, with syntaxis_def_fn(this_type, fn_name, arity)Dynamic::takeis added as a short-cut forstd::mem::take(&mut value).
Engine::is_symbol_disabledis added to test whether a particular keyword/symbol is disabled.- Support is added to deserialize a
Dynamicvalue containing custom types or shared values back into anotherDynamic(essentially a straight cloned copy).
This version attempts a number of optimizations that may yield small speed improvements:
- Simple operators (e.g. integer arithmetic) are inlined to avoid the overhead of a function call.
- The tokenizer uses pre-calculated tables (generated by GNU
gperf) for keyword recognition. - A black-arts trick (see
Engine::black_box) is used to prevent LLVM from optimizing hand-tuned AST node matches back into a lookup table, which messes up branch prediction on modern CPU's.
- Complex indexing/dotting chains now parse correctly, for example:
a[b][c[d]].e mapandfilterfor arrays are markedpure. Warnings are added to the documentation of pure array methods that takethisclosures.- Syntax such as
foo.bar::bazno longer panics, but returns a proper parse error. - Expressions such as
!insidenow parses correctly instead of as!infollowed byside. - Custom syntax starting with symbols now works correctly and no longer raises a parse error.
- Comparing different custom types now works correctly when the appropriate comparison operators are registered.
- Some op-assignments, such as
x += ywherexandyarechar, now work correctly instead of failing silently. - Op-assignments to bit flags or bit ranges now work correctly.
- The trait method
ModuleResolver::resolve_raw(which is a low-level API) now takes a&mut Scopeparameter. This is a breaking change because the signature is modified, but this trait method has a default and is rarely called/implemented in practice. Module::eval_ast_as_new_raw(a low-level API) now takes a&mut Scopeinstead of theScopeparameter. This is a breaking change because the&mutis now required.Engine::allow_loop_expressionsnow correctly defaults totrue(was erroneouslyfalseby default).
Engine::new_rawis nowconstand runs very fast, delaying all other initialization until first use.- The functions
minandmaxare added for numbers. - Range cases in
switchstatements now also match floating-point and decimal values. In order to support this, however, small numeric ranges cases are no longer unrolled. - Loading a module via
importnow gives the module access to the current scope, including variables and constants defined inside. - Some very simple operator calls (e.g. integer add) are inlined to avoid the overhead of a function call, resulting in a small speed improvement.
- The tokenizer now uses table-driven keyword recognizers generated by GNU
gperf. At least theoretically it should be faster... - The field
isAnonymousis added to JSON functions metadata.
- Integer numbers that are too large to deserialize into
INTnow fall back toDecimalorFLOATinstead of silently truncating. - Parsing deeply-nested closures (e.g.
||{||{||{||{||{||{||{...}}}}}}}) no longer panics but will be confined to the nesting limit. - Closures containing a single expression are now allowed in
Engine::eval_expressionetc. - Strings interpolation now works under
Engine::new_rawwithout any standard package. Fnnow throws an error if the name is a reserved keyword as it cannot possibly map to such a function. This also disallows creating function pointers to custom operators which are defined as disabled keywords (a mouthful), but such custom operators are designed primarily to be used as operators.
- The callback for initializing a debugger instance has changed to
Fn(&Engine, Debugger) -> Debugger. This allows more control over the initial setup of the debugger. - The internal macro
reify!is no longer available publicly.
Module::with_capacityis deprecated.- The internal method
Engine::eval_statements_rawis deprecated. - Array overloaded methods that take function names (as string) are deprecated in favor of using the
Fn("...")call.
- The function registration mechanism is revamped to take advantage of constant generics, among others, to omit checking code where possible. This yields a 10-20% speed improvements on certain real-life, function-call-heavy workloads.
- Functions taking function pointers as parameters, usually called with closures, now run faster because a link to the anonymous function (generated by the closure) is stored together with the function pointer itself. This allows short-circuiting the function lookup step.
- A function pointer created via a closure definition now links to the particular anonymous function itself.
- This avoids a potentially expensive function lookup when the function pointer is called, speeding up closures.
- Closures now also encapsulate their defining environment, so function pointers can now be freely
exported from modules!
- A new operator
!inis added which maps to!(... in ...).
Engine::call_fn_rawis deprecated in favor ofEngine::call_fn_with_optionswhich allows setting options for the function call.- The options are for future-proofing the API.
- In this version, it gains the ability to set the value of the custom state (accessible via
NativeCallContext::tag) for a function evaluation, overridingEngine::set_default_tag.
Engine::compact_scriptis added which takes a valid script (it still returns parsing errors) and returns a compacted version of the script with all insignificant whitespaces and all comments removed.- A compact script compresses better than one with liberal whitespaces and comments.
- Unlike some uglifiers or minifiers,
Engine::compact_scriptdoes not optimize the script in any way, nor does it rename variables.
- Array methods that take a function pointer, usually a closure (e.g.
map,filter,index_of,reduceetc.), can now bind the array element tothiswhen calling a closure. - This vastly improves performance when working with arrays of large types (e.g. object maps) by avoiding unnecessary cloning.
findandfind_mapare added for arrays.for_eachis also added for arrays, allowing a closure to mutate array elements (bound tothis) in turn.
- Optimizations have been done to key data structures to minimize size and creation time, which involves turning rarely-used fields into
Option<Box<T>>. This resulted in some speed improvements. CallableFunctionis exported underinternals.- The
TypeBuildertype andCustomTypetrait are no longer marked as volatile. FuncArgsis also implemented for arrays.Engine::set_XXXAPI can now be chained.EvalContext::scope_mutnow returns&mut Scopeinstead of&mut &mut Scope.- Line-style doc-comments are now merged into a single string to avoid creating many strings. Block-style doc-comments continue to be independent strings.
- Block-style doc-comments are now "un-indented" for better formatting.
- Doc-comments on plugin modules are now captured in the module's
docfield. - Expression nesting levels is refined such that it grows less excessively for common patterns.
- The traits
IndexandIndexMutare added toFnPtr. FnPtr::iter_curryandFnPtr::iter_curry_mutare added.Dynamic::deep_scanis added to recursively scan forDynamicvalues.>>and<<operators on integers no longer throw errors when the number of bits to shift is out of bounds. Shifting by a negative number of bits simply reverses the shift direction.
- Due to a code refactor, built-in operators for standard types now run even faster, in certain cases by 20-30%.
Engine::parse_jsonnow returns an error on unquoted keys to be consistent with JSON specifications.importstatements insideevalno longer cause errors in subsequent code.- Functions marked
globalinimported modules with no alias names now work properly. - Incorrect loop optimizations that are too aggressive (e.g. unrolling a
do { ... } until truewith abreakstatement inside) and cause crashes are removed. Dynamic::isnow works properly for shared values.
NativeCallContext::newis completely deprecated and unimplemented (always panics) in favor of new API's.
- New methods are added to
Dynamicin the form ofis_XXX()whereXXXis a type (e.g.is_int,is_unit,is_bool,is_array). - This new API is to make it easier to detect the data type, instead of having to call
is::<XXX>().
- Loops (such as
loop,do,whileandfor) can now act as expressions, with thebreakstatement returning an optional value. - Normal loops return
()as the value. - Loop expressions can be enabled/disabled via
Engine::set_allow_loop_expressions
- It is now possible to specify a fixed seed for use with the
ahashhasher, via a static functionrhai::config::hashing::set_ahash_seedor an environment variable (RHAI_AHASH_SEED), in order to force static (i.e. deterministic) hashes for function signatures. - This is necessary when using Rhai across shared-library boundaries.
- A build script is used to extract the environment variable (
RHAI_AHASH_SEED, if any) and splice it into the source code before compilation.
- A new feature,
no_time, is added to disable support for timestamps. - This may be necessary when building for architectures without time support, such as raw WASM.
Scopeis now serializable and deserializable viaserde.
- A convenient API is added to store a
NativeCallContextinto a newNativeCallContextStoretype. - This allows a
NativeCallContextto be stored and recreated later on.
NativeCallContext::call_native_fnis added to call registered native Rust functions only.NativeCallContext::call_native_fn_rawis added as the advanced version.- This is often desirable as Rust functions typically do not want a similar-named scripted function to hijack the process -- which will cause brittleness.
- The look-ahead symbol for custom syntax now renders a string literal in quotes (instead of the generic term
string). - This facilitates more accurate parsing by separating strings and identifiers.
- Methods returning maximum limits (e.g.
Engine::max_string_len) are now available even underunchecked. - This helps avoid the proliferation of unnecessary feature flags in third-party library code.
parse_jsonfunction is added to parse a JSON string into an object map.Error::ErrorNonPureMethodCallOnConstantis added which is raised when a non-pure method is called on a constant value.
- Compiling on 32-bit architectures no longer cause a compilation error.
- Fix type-size test for 32-bit architectures without the
decimalfeature.
- [
Engine::register_custom_syntax_with_state_raw] is added. The custom syntax parser and implementation functions take on an additional parameter that holds a user-defined custom state which should substantially simplify writing some custom parsers. - [
Engine::register_custom_syntax_raw] is deprecated.
This version introduces Fast Operators mode, which is turned on by default but can be disabled via
a new options API: Engine::set_fast_operators.
Fast Operators mode assumes that none of Rhai's built-in operators for standard data types are
overloaded by user-registered functions. In the vast majority of cases this should be so (really,
who overloads the + operator for integers anyway?).
This assumption allows the Engine to avoid checking for overloads for every single operator call.
This usually results in substantial speed improvements, especially for expressions.
The minimum Rust version is now 1.61.0 in order to use some const generics.
- API for registering property getters/setters and indexers to an
Enginenow works with functions that take a first parameter ofNativeCallContext. - Missing API function
Module::set_getter_setter_fnis added. - To avoid subtle errors, simple optimization is used for
rhai-run; previous it was full optimization.
- All versions of the
Engine::register_XXX_resultAPI that register a function returningResult<T, Box<EvalAltResult>>are now deprecated. The regular, non-resultversions handle all functions correctly.
- A new option
Engine::fast_operatorsis introduced (default totrue) to enable/disable Fast Operators mode.
- For very special needs, the ability to register fallible type iterators is added.
if-expressions are allowed inEngine::eval_expressionandEngine::compile_expressionprovided that both statement blocks each contain at most a single expression.switch-expressions are allowed inEngine::eval_expressionandEngine::compile_expressionprovided that match actions are expressions only.
is_emptymethod is added to arrays, BLOB's, object maps, strings and ranges.StaticModuleResolvernow stores the path in the module'sidfield.Engine::module_resolveris added to grant access to theEngine's module resolver.- Constants and variables now have types in generated definition files.
This is a bug-fix version that fixes a bug.
Accessing properties in Strict Variables Mode no longer generates a variable not found error.
The minimum Rust version is now 1.60.0 in order to use the dep: syntax for dependencies.
switchcases with conditions that evaluate to constant()no longer optimize tofalse(should raise a type error during runtime).- Fixes concatenation of BLOB's and strings, where the BLOB's should be interpreted as UTF-8 encoded strings.
- Capturing an unknown variable in a closure no longer panics.
- Fixes panic in interpolated strings with constant expressions.
- Using
call_fn_rawon a function without evaluating the AST no longer panics on namespace-qualified function calls due toimportstatements not run. - Some reserved tokens (such as "?", "++") cannot be used in custom syntax; this is now fixed.
- The first closure passed to
Engine::register_debuggernow takes a single parameter which is a reference to the currentEngine.
- A new feature flag,
std, which is enabled by default, is added due to requirements from dependency crates. - A new feature flag,
no_custom_syntax, is added to remove custom syntax support from Rhai for applications that do not require it (which should be most).
- Comment lines beginning with
//!(requires themetadatafeature) are now collected as the script file's module documentation. ASTandModulehave methods to access and manipulate documentation.
- An API is added to automatically generate definition files from a fully-configured
Engine, for use with the Rhai Language Server.
- Using a script-defined function's name (in place of a variable) implicitly creates a function pointer to the function.
- Crate-level functions
rhai::eval,rhai::run,rhai::eval_file,rhai::run_fileare added as convenient wrappers.
- A new volatile API,
Engine::build_type, enables registration of the entire API of a custom type in one go, provided that the custom type implements theCustomTypetrait (which usesTypeBuilderto register the API functions).
- It is now easier to register packages via the
Package::register_into_engineandPackage::register_into_engine_asAPI. - Defining a custom package with base packages is also much easier with a new syntax - put the new base packages after a colon.
switchcases can now include multiple values separated by|.- Duplicated
switchcases are now allowed. - The error
ParseErrorType::DuplicatedSwitchCaseis deprecated. - Ranges in
switchstatements that are small (currently no more than 16 items) are unrolled if possible.
EvalContext::eval_expression_tree_rawandExpression::eval_with_context_raware added to allow for not rewinding theScopeat the end of a statements block.- A new
rangefunction variant that takes an exclusive range with a step. as_stringis added to BLOB's to convert it into a string by interpreting it as a UTF-8 byte stream.FnAccess::is_private,FnAccess::is_public,FnNamespace::is_module_namespaceandFnNameSpace::is_global_namespaceare added for convenience.Iterator<Item=T>type for functions metadata is simplified toIterator<T>.Scope::removeis added to remove a variable from aScope, returning its value.- The code base is cleaner by running it through Clippy.
ParseError::err_typeandParseError::positionare added for convenience.- The source of an
ASTcompiled from a script file is set to the file's path. |>and<|are now reserved symbols.
- Self-contained
ASTnow works properly withEngine::call_fn. - Missing
to_intfromDecimalis added. - Parsing of index expressions is relaxed and many cases no longer result in an index-type error to allow for custom indexers.
- Merging or combining a self-contained
ASTinto anotherASTnow works properly. - Plugin modules/functions no longer generate errors under
#![deny(missing_docs)]. - Calling a property on a function call that returns a shared value no longer causes an error.
- Strict Variables Mode now checks for module namespaces within functions as well.
- Module defined via
Engine::register_static_moduleare now checked in Strict Variables Mode.
?,??,?.,?[and!.are now reserved symbols.
FnPtr::num_curriedis deprecated in favor ofFnPtr::curry().len().
- The Elvis operators (
?.and?[) are now supported for property access, method calls and indexing. - The null-coalescing operator (
??) is now supported to short-circuit()values.
- Indexing and property access are now faster.
EvalAltResult::IndexNotFoundis added to aid in raising errors for indexers.Engine::def_tag,Engine::def_tag_mutandEngine::set_tagare added to manage a default value for the custom evaluation state, accessible viaEvalState::tag()(which is the same asNativeCallContext::tag()).- Originally, the debugger's custom state uses the same state as
EvalState::tag()(which is the same asNativeCallContext::tag()). It is now split into its own variable accessible underDebugger::state(). - Non-borrowed string keys can now be deserialized for object maps via
serde. Scope::getis added to get a reference to a variable's value.- Variable resolvers can now return a shared value which can be mutated.
- Compound assignments now work properly with indexers.
- Cloning a
Scopeno longer turns all constants to mutable.
- Strict Variables Mode no longer returns an error when an undeclared variable matches a variable/constant in the provided external
Scope.
- The
Engine::on_varandEngine::on_parse_tokenAPI's are now marked unstable/volatile. - The closures passed to
Engine::on_var,Engine::on_def_varandEngine::register_debuggertakeEvalContextinstead of&EvalContextor&mut EvalContext. - The following enum's are marked
non_exhaustive:AccessMode,FnAccess,FnNamespace,FnMetadata,OptimizationLevel
Module::eval_ast_as_new_rawis made public as a low-level API.format_map_as_jsonis provided globally, which is the same asto_jsonfor object maps.Engine::call_fn_raw_rawis added to add speed to repeated function calls.Engine::eval_statements_rawis added to evaluate a sequence of statements.
- A custom state is provided that is persistent during the entire evaluation run. This custom state is a
Dynamic, which can hold any data, and can be accessed by the host viaEvalContext::tag,EvalContext::tag_mut,NativeCallContext::tagandGlobalRuntimeState.tag.
- Improper
switchcase condition syntax is now caught at parse time. Engine::parse_jsonnow natively handles nested JSON inputs (using a token remap filter) without needing to replace{with#{.to_jsonis added to object maps to cheaply convert it to JSON format (()is mapped tonull, all other data types must be supported by JSON)FileModuleResolvernow accepts a customScopeto provide constants for optimization.- New variants,
StartandEnd, are added toDebuggerEventtriggered at the start/end of script evaluation.
- Functions with
Dynamicparameters now work in qualified calls fromimported modules. rhai-replnow compiles with the new patch version ofrustyline.rhai_codegendependency is now explicitly1.4or higher.
splitnow splits a string by whitespaces instead of splitting it into individual characters. This is more in line with common practices.- A new function
to_charsfor strings is added to split the string into individual characters.
- Strings are now directly iterable (via
for .. in) yielding individual characters.
This version, in particular, fixes a plugin macro hygiene error for the nightly compiler:
error[E0425]: cannot find value `args` in this scope
- Minimum compiler version is now
1.57due tosmartstringdependency.
- Fixed macro hygiene error with nightly compiler.
- Invalid property or method access such as
a.b::c.dora.b::func()no longer panics but properly returns a syntax error. Scope::is_constantnow returns the correct value.- Exporting a variable that contains a local function pointer (including anonymous function or closure) now raises a runtime error.
- Full optimization is now skipped for method calls.
- Type aliases in plugin modules are now used as friendly names for custom types. This makes plugin modules more self-contained when they are used to define a custom type's API.
- Variable definitions are optimized so that shadowed variables are reused as much as possible to reduce memory consumption.
FnAccessandFnNamespacenow implementOrdandPartialOrd.- The
event_handler_mapexample is enhanced to prevent shadowing of the state object map. - Separation of constants in function calls is removed as its performance benefit is dubious.
- A function
sleepis added to block the current thread by a specified number of seconds. Scope::set_aliasis added to export a variable under a particular alias name.starts_withandends_withare added for strings.- Variables in modules registered via
register_global_modulecan now be accessed in the global namespace. Dynamic::into_read_onlyis added to convert aDynamicvalue into constant.Modulenow holds a collection of custom types with an API.
This version adds a debugging interface, which can be used to integrate a debugger.
Based on popular demand, an option is added to throw exceptions when invalid properties are accessed on object maps (default is to return ()).
Also based on popular demand, the REPL tool now uses a slightly-enhanced version of rustyline for line editing and history.
- In
Scope::clone_visible, constants are now properly cloned as constants. - Variables introduced inside
tryblocks are now properly cleaned up upon an exception. - Off-by-one error in character positions after a comment line is now fixed.
- Globally-defined constants are now encapsulated correctly inside a loaded module and no longer spill across call boundaries.
- Type names display is fixed.
- Exceptions thrown inside function calls now unwrap correctly when
catch-ed. - Error messages for certain invalid property accesses are fixed.
- For consistency with the
importstatement, theexportstatement no longer exports multiple variables. - Appending a BLOB to a string (via
+,+=,appendor string interpolation) now treats the BLOB as a UTF-8 encoded string. - Appending a string/character to a BLOB (via
+=orappend) now adds the string/character as a UTF-8 encoded byte stream.
- A debugging interface is added.
- A new bin tool,
rhai-dbg(aka The Rhai Debugger), is added to showcase the debugging interface. - A new package,
DebuggingPackage, is added which contains theback_tracefunction to get the current call stack anywhere in a script. Engine::set_fail_on_invalid_map_propertyis added to control whether to raise an error (newEvalAltResult::ErrorPropertyNotFound) when invalid properties are accessed on object maps.Engine::set_allow_shadowingis added to allow/disallow variables shadowing, with new errorsEvalAltResult::ErrorVariableExistsandParseErrorType::VariableExists.Engine::on_def_varallows registering a closure which can decide whether a variable definition is allow to continue, during compilation or runtime, or should fail with an error (ParseErrorType::ForbiddenVariableorEvalAltResult::ErrorForbiddenVariable).- A new syntax for defining custom packages is introduced that removes the need to specify the Rhai crate name (internally uses the
$cratemeta variable).
- Default features for dependencies (such as
ahash/stdandnum-traits/std) are no longer required. - The
no_modulefeature now eliminates large sections of code via feature gates. - Debug display of
ASTis improved. NativeCallContext::call_level()is added to give the current nesting level of function calls.- A new feature,
bin-features, pulls in all the required features forbintools. ASTposition display is improved:Expr::start_positionis added to give the beginning of the expression (not the operator's position).StmtBlockandStmt::Blocknow keep the position of the closing}as well.
EvalAltResult::unwrap_inneris added to access the base error inside multiple layers of wrappings (e.g.EvalAltResult::ErrorInFunction).- Yet another new syntax is introduced for
def_package!that further simplifies the old syntax. - A new method
to_blobis added to convert a string into a BLOB as UTF-8 encoded bytes. - A new method
to_arrayis added to convert a BLOB into array of integers.
The REPL bin tool, rhai-rpl, has been enhanced.
- The
rustylinefeature is now required in order to buildrhai-repl. - Therefore,
rhai-replis no longer automatically built when using a simplecargo buildwith default features.
rhai-replnow uses a modified version ofrustylineas a line editor with history.- Ctrl-Enter can now be used to enter multiple lines without having to attach the
\continuation character the end of each line. - Bracketed paste is supported, even on Windows (version 10 or above), so pasting code directly into
rhai-replis made much more convenient.
strictto turn on/off Strict Variables Mode.optimizeto turn on/off script optimization.historyto print lines history.!!,!num,!text and!?text to recall a history line.keysto print all key bindings.
This is primarily a bug-fix version which fixes a large number of bugs.
- Expressions such as
x = x + 1no longer panics. - Padding arrays with another array via
padno longer loops indefinitely. chopfor arrays and BLOB's now works properly.set_bitfor bit-flags with negative index now works correctly.- Misnamed
paramsfieldnamein the JSON output ofEngine::gen_fn_metadata_to_jsonis fixed (was incorrectly namedtype). - Fixes a potential
unsafeviolation inforloop. - Missing
to_hex,to_octalandto_binaryfori128andu128are added. removefor arrays and BLOB's now treat negative index correctly.parse_intnow works properly for negative numbers.Engine::gen_fn_signaturesnow generates signatures for external packages registered viaEngine::register_global_module.\r\npairs are now recognized correctly for doc-comments.
- Formatting of return types in functions metadata info is improved.
- Use
SmartStringforScopevariable names and removeunsafelifetime casting. - Functions in the standard library now have doc-comments (which can be obtained via
Engine::gen_fn_metadata_to_json). getandsetmethods are added to arrays, BLOB's, object maps and strings.
This version adds support for integer ranges via the .. and ..= operators.
Many standard API's are extended with range parameters where appropriate.
isis (pun intended) now a reserved keyword to prepare for possible future type checking expressions (e.g.x is "string").
LogicPackageis removed fromCorePackage.- Bit-field functions are moved into a new
BitFieldPackage(used to be inLogicPackage) which makes more sense.
- Custom syntax now works properly inside binary expressions and with method calls.
- Hex numbers with the high-bit set now parse correctly into negative integer numbers.
- Constructing a literal array or object map now checks for size limits for each item instead of at the very end when it is already too late.
- Non-
INTinteger types are now treated exactly as custom types underonly_i64andonly_i32. - Calling
padon an array now checks for total size over limit after each item added.
- Added support for integer ranges via the
..and..=operators. - Added
EvalAltResult::ErrorCustomSyntaxto catch errors in custom syntax, which should not happen unless anASTis compiled on oneEnginebut evaluated on another unrelatedEngine.
BLOB's are refined to display in a more compact hex format.- A new syntax is introduced for
def_package!that will replace the old syntax in future versions. - Added
NativeCallContext::call_fnto easily call a function. - Doc-comments on plugin module functions are extracted into the functions' metadata.
Expression::get_variable_nameis deprecated in favor of the newExpression::get_string_value.- The old syntax of
def_package!is deprecated in favor of the new syntax.
This version adds native support for BLOB's (byte arrays), as well as a number of configuration
settings to fine-tun language features.
- Minimum compiler version is now 1.51.
from_dynamicnow supports deserializingOption.
BLOB(essentially a byte array) is added as a supported primitive value type parallel to arrays.- New options for
Enginewhich allows disablingif-expressions,switch-expressions, statement expressions, anonymous functions and/or looping (i.e.while,loop,doandforstatements):Engine::set_allow_if_expressionEngine::set_allow_switch_expressionEngine::set_allow_statement_expressionEngine::set_allow_anonymous_fnEngine::set_allow_looping
- New strict variables mode for
Engine(enabled viaEngine::set_strict_variables) to throw parse errors on undefined variable usage. Two new parse error variants,ParseErrorType::VariableNotFoundandParseErrorType::ModuleNotFound, are added.
- Two double quotes (
"") in a string literal now maps to"; two back-ticks (``) in a literal string now maps to`. - Added
Engine::register_type_with_name_rawto register a custom type based on a fully-qualified type path. - Added
into_arrayandinto_typed_arrayforDynamic. - Added
FnPtr::callandFnPtr::call_within_contextto simplify calling a function pointer. - A function's hashes are included in its JSON metadata to assist in debugging. Each function's
baseHashfield in the JSON object should map directly to the pre-calculated hash in the function call. Expressionnow derefs toExpr.
NativeCallContext::newis deprecated because it is simpler to call a function pointer viaFnPtr::call.AST::merge_filteredandAST::combine_filteredare no longer exported underno_function.AST::newandAST::new_with_sourceare moved underinternals.FnPtr::call_dynamicis deprecated in favor ofFnPtr::call_raw.
- Array methods (such as
map) taking a closure with captures as argument now works properly.
- As originally intended, function calls with a bang (
!) now operates directly on the caller's scope, allowing variables inside the scope to be mutated. - As originally intended,
Engine::XXX_with_scopeAPI's now properly propagate constants within the provided scope also to functions in the script. - Printing of integral floating-point numbers is fixed (used to only prints
0.0). func!()calls now work properly underno_closure.- Fixed parsing of unary negation such that expressions like
if foo { ... } -xparses correctly.
#[cfg(...)]attributes can now be put directly on plugin functions or function defined in a plugin module.- A custom syntax parser can now return a symbol starting with
$$to inform the implementation function which syntax variant was actually parsed. AST::iter_literal_variablesis added to extract all top-level literal constant/variable definitions from a script without running it.Engine::call_fn_dynamicis deprecated andEngine::call_fn_rawis added which allows keeping new variables in the custom scope.
- Array methods now avoid cloning as much as possible (although most predicates will involve cloning anyway if passed a closure).
- Array methods that take function pointers (e.g. closures) now optionally take the function name as a string.
- Array adds the
dedupmethod. - Array adds a
sortmethod with no parameters which sorts homogeneous arrays of built-in comparable types (e.g.INT). - Inlining is disabled for error-path functions because errors are exceptional and scripts usually fail completely when an error is encountered.
- The
optimizemodule is completely eliminated underno_optimize, which should yield smaller code size. NativeCallContext::positionis added to return the position of the function call.Scope::clone_visibleis added that copies only the last instance of each variable, omitting all shadowed variables.
NativeCallContext::call_fn_dynamic_rawis deprecated andNativeCallContext::call_fn_rawis added.From<EvalAltResult>forResult<T, Box<EvalAltResult> >is deprecated so it will no longer be possible to doEvalAltResult::ErrorXXXXX.into()to convert to aResult; instead,Err(EvalAltResult:ErrorXXXXX.into())must be used. Code is clearer if errors are explicitly wrapped inErr.
0.0now prints correctly (used to print0e0).- Unary operators are now properly recognized as an expression statement.
- Reverses a regression on string
+operations. - The global namespace is now searched before packages, which is the correct behavior.
- Assignment to indexing expression with dot expressions inside no longer cause a compilation error.
- The
no_moduleandinternalsfeatures now work together without a compilation error. - String literal operations (such as
"hello" + ", world") now optimizes correctly.
- Custom syntax starting with a disabled standard keyword now works properly.
- When calling
Engine::call_fn, new variables defined during evaluation of the body script are removed and no longer spill into the function call. NamespaceRef::newis fixed.
Engine::consume_XXXmethods are renamed toEngine::run_XXXto make meanings clearer. Theconsume_XXXAPI is deprecated.Engine::register_type_XXXare now available even underno_object.- Added
Engine::on_parse_tokento allow remapping certain tokens during parsing. - Added
Engine::const_empty_stringto merge empty strings into a single instance.
$symbol$is supported in custom syntax to match any symbol.- Custom syntax with
$block$,}or;as the last symbol are now self-terminating (i.e. no need to attach a terminating;).
Dynamic::as_stringandDynamic::as_immutable_stringare deprecated and replaced byinto_stringandinto_immutable_stringrespectively.- Added a number of constants to
Dynamic. - Added a number of constants and
fromXXXconstant methods toDynamic. - Added
sin,cosandtanforDecimalvalues.
parse_float(),PI()andE()now defer toDecimalunderno_floatifdecimalis turned on.- Added
log10()forDecimal. lnforDecimalis now checked and won't panic.
SmartStringnow usesLazyCompactinstead ofCompactto minimize allocations.- Added
popfor strings. - Added
ImmutableString::ptr_eqto test if two strings point to the same allocation. - The
serdefeature ofSmartStringis turned on undermetadatato makeMapserializable.
Scope::set_valuenow takes anything that implementsInto<Cow<str> >.- Added
Scope::is_constantto check if a variable is constant. - Added
Scope::set_or_pushto add a new variable only if one doesn't already exist.
- Added
ASTNode::position. ReturnTypeis removed in favor of option flags forStmt::Return.Stmt::BreakandStmt::Continueare merged intoStmt::BreakLoopvia an option flag.StaticVecis changed to keep three items inline instead of four.
- Eliminate unnecessary property write-back when accessed via a getter since property getters are assumed to be pure.
- Writing to a property of an indexed valued obtained via an indexer now works properly by writing back the changed value via an index setter.
MultiInputsStream,ParseState,TokenIterator,IdentifierBuilderandAccessModeare exported under theinternalsfeature.
FloatWrapperis no longer erroneously exported underno_float+internals.- The
signfunction now works properly for float values that areNaN.
- Fixed bug with
catchvariable used incatchblock.
- Fixed bug in method call followed by an array indexing.
- Fixed bug in using indexing/dotting inside index bracket.
whileandloopstatements are no longer considered pure (since a loop can go on forever and this is a side effect).
The official version 1.0.
Almost the same version as 0.20.3 but with deprecated API's removed.
- Fixed infinite loop in certain script optimizations.
- Building for
no-stdno longer requires patchingsmartstring. - Parsing a lone
returnorthrowwithout a semicolon at the end of a block no longer raises an error.
- All deprecated API's (e.g. the
RegisterFnandRegisterResultFntraits) are removed. Module::set_idis split intoModule::set_idandModule::clear_idpair.begin,end,each,then,unlessare no longer reserved keywords.
- New methods
is_odd,is_evenfor integers, andis_zerofor all numbers. From<BTreeSet>andFrom<HashSet>are added forDynamic, which create object maps with()values.
This version adds support to index into an integer number, treating it as a bit-field.
- Fixed incorrect optimization regarding chain-indexing with non-numeric index.
- Variable values are checked for over-sized violations after assignments and setters.
- To keep the API consistent, strings are no longer iterable by default. Use the
charsmethod to iterate through the characters in a string. Dynamic::take_stringandDynamic::take_immutable_stringare renamed toDynamic::as_stringandDynamic::as_immutable_stringrespectively.
- New syntax for
forstatement to include counter variable. - An integer value can now be indexed to get/set a single bit.
- The
bitsmethod of an integer can be used to iterate through its bits. - New
$bool$,$int$,$float$and$string$expression types for custom syntax. - New methods
to_hex,to_octalandto_binaryfor integer numbers. - New methods
to_upper,to_lower,make_upper,make_lowerfor strings/characters.
This version adds a number of convenience features:
-
Ability for a
Dynamicto hold ani32tag of arbitrary data -
Simplifies dynamic properties access by falling back to an indexer (passing the name of the property as a string) when a property is not found.
- Propagation of constants held in a custom scope now works properly instead of always replacing by
().
Engine::disable_doc_commentsis removed because doc-comments are now placed under themetadatafeature flag.- Registering a custom syntax now only requires specifying whether the
Scopeis adjusted (i.e. whether variables are added or removed). There is no need to specify the number of variables added/removed. - Assigning to a property of a constant is now allowed and no longer raise an
EvalAltResult::ErrorAssignmentToConstanterror. This is to facilitate the Singleton pattern. Registered setter functions are automatically guarded against setters calling on constants and will continue to raise errors unless thepureattribute is present (for plugins). - If a property getter/setter is not found, an indexer with string index, if any, is tried.
- The indexers API (
Engine::register_indexer_XXXandModule::set_indexer_XXX) are now also exposed underno_index.
- Each
Dynamicvalue can now contain arbitrary data (typei32) in the form of a tag. This is to use up otherwise wasted space in theDynamictype. - A new internal feature
no_smartstringto turn offSmartStringfor those rare cases that it is needed. DynamicReadLockandDynamicWriteLocare exposed underinternals.From< Shared< Locked<Dynamic> > >is added forDynamicmapping directly to a shared value, together with support forDynamic::from.- An indexer with string index acts as a fallback to a property getter/setter.
- Registering a custom syntax now only requires specifying whether the
Scopeis adjusted (i.e. whether variables are added or removed). This allows more flexibility for cases where the number of new variables declared depends on internal logic. - Putting a
pureattribute on a plugin property/index setter now enables it to be used on constants.
This version enables functions to access constants declared at global level via the special global module.
- Fixed bug when position is zero in
insertandsplit_atmethods for arrays. - Indexing operations with pure index values are no longer considered pure due to the possibility of indexers.
Dynamic::is_sharedandDynamic::is_lockedare removed under theno_closurefeature. They used to always returnfalse.Engine::call_fnnow evaluates theASTbefore calling the function.Engine::on_progressis disabled withunchecked.
- The crate
no-std-compatis used to compile forno-std. This removes the need to use a specialcrate::stdlibnamespace forstdimports.
- A module called
globalis automatically created to hold global-level constants, which can then be accessed from functions. - A new feature
no_positionis added to turn off position tracking during parsing to squeeze out the last drop of performance.
This version adds string interpolation with `... ${ ... } ...` syntax.
switch statement cases can now have conditions.
Negative indices for arrays and strings are allowed and now count from the end (-1 = last item/character).
- Property setter op-assignments now work properly.
- Off-by-one bug in
Array::drainmethod with range is fixed.
- Negative index to an array or string yields the appropriate element/character counting from the end.
- The default
_case of aswitchstatement now must be the last case, together with two new error variants:EvalAltResult::WrongSwitchDefaultCaseandEvalAltResult::WrongSwitchCaseCondition. ModuleResolvertrait methods take an additional parametersource_paththat contains the path of the current environment. This is to facilitate loading other script files always from the current directory.FileModuleResolvernow resolves relative paths under the source path if there is no base path set.FileModuleResolver::base_pathnow returnsOption<&str>which isNoneif there is no base path set.- Doc-comments now require the
metadatafeature.
Array::drainandArray::retainmethods with predicate now scan the array in forward order instead of in reverse.
- String interpolation support is added via the
`... ${...} ...`syntax. FileModuleResolverresolves relative paths under the parent path (i.e. the path holding the script that does the loading). This allows seamless cross-loading of scripts from a directory hierarchy instead of having all relative paths load from the current working directory.- Negative index to an array or string yields the appropriate element/character counting from the end.
switchstatement cases can now have an optionalifclause.
This version replaces all internal usage of HashMap with BTreeMap, which should result
in some speed improvement because a BTreeMap is leaner when the number of items held is small.
Most, if not all, collections in Rhai hold very few data items, so this is a typical scenario of
many tiny-sized collections.
The Rhai object map type, Map, used to be an alias to HashMap and is now aliased to BTreeMap
instead. This is also because, in the vast majority of usage cases, the number of properties held by
an object map is small.
HashMap and BTreeMap have almost identical public API's so this change is unlikely to break
existing code.
SmartString is used to store identifiers (which tend to
be short, fewer than 23 characters, and ASCII-based) because they can usually be stored inline.
Map keys now also use SmartString.
In addition, there is now support for line continuation in strings (put \ at the end of line) as
well as multi-line literal strings (wrapped by back-ticks: `...`).
Finally, all function signature/metadata methods are now grouped under the umbrella metadata feature.
This avoids spending precious resources maintaining metadata for functions for the vast majority of
use cases where such information is not required.
- The feature flags
no_index + no_objectnow compile without errors.
- The traits
RegisterFnandRegisterResultFnare removed.Engine::register_fnandEngine::register_result_fnare now implemented directly onEngine. FnPtr::call_dynamicnow takes&NativeCallContextinstead of consuming it.- All
Module::set_fn_XXXmethods are removed, in favor ofModule::set_native_fn. Array::reduceandArray::reduce_revnow take aDynamicas initial value instead of a function pointer.protected,superare now reserved keywords.- The
Module::set_fn_XXXAPI now take&stras the function name instead ofInto<String>. - The reflections API such as
Engine::gen_fn_signatures,Module::update_fn_metadataetc. are put under themetadatafeature gate. - The shebang
#!is now a reserved symbol. - Shebangs at the very beginning of script files are skipped when loading them.
SmartStringis used for identifiers by default. Currently, a PR branch is pulled forno-stdbuilds. The official crate will be used onceSmartStringis fixed to supportno-std.Mapis now an alias toBTreeMap<SmartString, Dynamic>instead ofHashMapbecause most object maps hold few properties.EvalAltResult::FnWrongDefinitionis renamedWrongFnDefinitionfor consistency.
- Line continuation (via
\) and multi-line literal strings (wrapped with`) support are added. - Rhai scripts can now start with a shebang
#!which is ignored.
- Replaced all
HashMapusage withBTreeMapfor better performance because collections in Rhai are tiny. Engine::register_result_fnno longer requires the successful return type to beDynamic. It can now be any clonable type.#[rhai_fn(return_raw)]can now returnResult<T, Box<EvalAltResult> >whereTis any clonable type instead ofResult<Dynamic, Box<EvalAltResult> >.Dynamic::clone_castis added to simplify casting from a&Dynamic.
This version runs faster due to optimizations done on AST node structures. It also fixes a number of panic bugs related to passing shared values as function call arguments.
- Panic when passing a shared string into a registered function as
&strargument is fixed. - Panic when calling
switchstatements on custom types is fixed. - Potential overflow panics in
range(from, to, step)is fixed. &mut Stringparameters in registered functions no longer panic when passed a string.- Some expressions involving shared variables now work properly, for example
x in shared_value,return shared_value,obj.field = shared_valueetc. Previously, the resultant value is still shared which is counter-intuitive. - Errors in native Rust functions now contain the correct function call positions.
- Fixed error types in
EvalAltResult::ErrorMismatchDataTypewhich were swapped.
Dynamic::as_stris removed because it does not properly handle shared values.- Zero step in the
rangefunction now raises an error instead of creating an infinite stream. - Error variable captured by
catchis now an object map containing error fields. EvalAltResult::clear_positionis renamedEvalAltResult::take_positionand returns the position taken.privatefunctions in anASTcan now be called withcall_fnetc.NativeCallContext::call_fn_dynamic_rawno longer has thepub_onlyparameter.Module::update_fn_metadatainput parameter is changed.- Function keywords (e.g.
type_of,eval,Fn) can no longer be overloaded. It is more trouble than worth. To disable these keywords, useEngine::disable_symbol. is_def_varandis_def_fnare now reserved keywords.Engine::idfield is removed because it is never used.num-traitsis now a required dependency.- The
inoperator is now implemented on top of thecontainsfunction and is no longer restricted to a few specific types. EvalAltResult::ErrorInExpris removed because theinoperator now callscontains.- The methods
AST::walk,Expr::walk,Stmt::walkandASTNode::walkand the callbacks they take now returnboolto optionally terminate the recursive walk.
- Layout of AST nodes is optimized to reduce redirections, so speed is improved.
- Function calls are more optimized and should now run faster.
rangefunction now supports negative step and decreasing streams (i.e. to < from).- More information is provided to the error variable captured by the
catchstatement in an object map. - Previously,
privatefunctions in anASTcannot be called withcall_fnetc. This is inconvenient when trying to call a function inside a script which also serves as a loadable module exporting part (but not all) of the functions. Now, all functions (privateor not) can be called in anAST. Theprivatekeyword is relegated to preventing a function from being exported. Dynamic::as_unitjust for completeness sake.bytesmethod added for strings to get length quickly (if the string is ASCII-only).FileModuleResolvercan now enable/disable caching.- Recursively walking an
ASTcan now be terminated in the middle.
This version introduces functions with Dynamic parameters acting as wildcards.
- Bug in
Position::is_beginning_of_lineis fixed.
- For plugin functions, constants passed to methods (i.e.
&mutparameter) now raise an error unless the functions are marked with#[rhai_fn(pure)]. - Visibility (i.e.
pubor not) for generated plugin modules now follow the visibility of the underlying module. - Comparison operators between the sames types or different numeric types now throw errors when they're not defined instead of returning the default. Only comparing between different types will return the default.
- Default stack-overflow and top-level expression nesting limits for release builds are lowered to 64 from 128.
Engine::call_fn_dynamictakes an additional parameter to optionally evaluate the givenASTbefore calling the function.
- Functions are now allowed to have
Dynamicarguments. #[rhai_fn(pure)]attribute to mark a plugin function with&mutparameter as pure so constants can be passed to it. Without it, passing a constant value into the&mutparameter will now raise an error.
- Built-in operators between
FLOAT/DecimalandINTare now implemented for more speed under those cases. - Error position in
evalstatements is now wrapped in anEvalAltResult::ErrorInFunctionCall. Positionnow implementsAddandAddAssign.Scopenow implementsIntoIterator.- Strings now have the
-/-=operators and theremovemethod to delete a sub-string/character. - Strings now have the
split_revmethod and variations ofsplitwith maximum number of segments. - Arrays now have the
splitmethod. - Comparisons between
FLOAT/DecimalandINTare now built in. - Comparisons between string and
charare now built in. Engine::call_fn_dynamiccan now optionally evaluate the givenASTbefore calling the function.
This version is an incremental release with a number of enhancements and bug fixes.
Notice that there are a number of breaking changes, especially with regards to replacing the ~
exponential operator with **, and the addition of the decimal feature that turns on
Decimal support.
- Empty statements (i.e. statements with only one
;) now parse correctly and no longer hang. continue,breakandreturnstatements no longer panic inside atry .. catchblock.roundfunction forf64is now implemented correctly.
- In order to be consistent with other scripting languages:
- the power/exponentiation operator is changed from
~to**;~is now a reserved symbol - the power/exponentiation operator now binds to the right
- trigonometry functions now take radians and return radians instead of degrees
- the power/exponentiation operator is changed from
Dynamic::into_sharedis no longer available underno_closure. It used to panic.Token::is_operatoris renamed toToken::is_symbol.AST::clone_functions_only_filtered,AST::merge_filtered,AST::combine_filteredandAST::retain_functionsnow takeFninstead ofFnMutas the filter predicate.
- Scientific notation is supported for floating-point number literals.
- A new feature,
decimal, enables theDecimaldata type. When bothno_floatanddecimalfeatures are enabled, floating-point literals parse toDecimal.
- Functions resolution cache is used in more cases, making repeated function calls faster.
- Added
atan(x, y)andhypot(x, y)toBasicMathPackage. - Added standard arithmetic operators between
FLOAT/DecimalandINT.
This version streamlines compiling for WASM.
Rust compiler minimum version is raised to 1.49.
- Parameters passed to plugin module functions were sometimes erroneously consumed. This is now fixed.
- Fixes compilation errors in
metadatafeature build. - Stacking
!operators now work properly. - Off-by-one error in
insertmethod for arrays is fixed. - Invalid property access now throws the appropriate error instead of panics.
- Rust compiler requirement raised to 1.49.
NativeCallContext::newtaker an additional parameter containing the name of the function called.Engine::set_doc_commentsis renamedEngine::enable_doc_comments.
- Two new features,
wasm-bindgenandstdweb, to specify the JS interop layer for WASM builds.wasm-bindgenused to be required.
ahashis used to hash function call parameters. This should yield speed improvements.DynamicandImmutableStringnow implementserde::Serializeandserde::Deserialize.NativeCallContexthas a new field containing the name of the function called, useful when the same Rust function is registered under multiple names in Rhai.- New functions
PI()andE()to return mathematical constants, andto_radiansandto_degreesto convert between radians and degrees.
no_stdfeature now compiles correctly (bug introduced in0.19.9).- Bug in
FileModuleResolver::clear_cache_for_pathpath mapping fixed. - Some optimizer fringe cases are fixed - related to constants propagation when the evil
evalis present.
- The error variant
EvalAltResult::ErrorInFunctionCallhas a new parameter holding the source of the function. ParseErrorType::WrongFnDefinitionis renamedFnWrongDefinition.- Redefining an existing function within the same script now throws a new
ParseErrorType::FnDuplicatedDefinition. This is to prevent accidental overwriting an earlier function definition. AST::set_sourceis now split intoAST::set_sourceandAST::clear_source.
Engine::compile_into_self_containedcompiles a script into anASTand eagerly resolves allimportstatements with string literal paths. The resolved modules are directly embedded into theAST. When theASTis later evaluated,importstatements directly yield the pre-resolved modules without going through the resolution process once again.AST::walk,Stmt::walkandExpr::walkinternal API's to recursively walk anAST.
- Source information is provided when there is an error within a call to a function defined in another module.
- Source information is provided to the
NativeCallContextfor native Rust functions. EvalAltResult::clear_positionto clear the position information of an error - useful when only the message is needed and the position doesn't need to be printed out.- A new optional function
resolve_astis added to theModuleResolvertrait for advanced usage.
This version fixes a bug introduced in 0.19.8 which breaks property access
within closures.
It also removes the confusing differences between packages and modules by unifying the terminology and API under the global umbrella of modules.
- Fix bug when accessing properties in closures.
- Fix bug when accessing a deep index with a function call.
- Fix bug that sometimes allow assigning to an invalid l-value.
- Fix off-by-one error with
Engine::set_max_call_levels.
Engine::load_packageis renamedEngine::register_global_moduleand now must explicitly pass a shared [Module].Engine::register_moduleis renamedEngine::register_static_moduleand now must explicitly pass a shared [Module].Package::getis renamedPackage::as_shared_module.Engine::set_module_resolvernow takes a straight module resolver instead of anOption. To disable module resolving, use the newDummyModuleResolver.
Scopeis nowClone + Hash.Engine::register_static_modulenow supports sub-module paths (e.g.foo::bar::baz).Engine::register_custom_operatornow accepts reserved symbols.Engine::register_custom_operatornow returns an error if given a precedence of zero.- The examples
replandrhai_runnerare moved intobinand renamedrhai-replandrhai-runrespectively.
This version makes it easier to generate documentation for a Rhai code base.
Each function defined in an AST can optionally attach doc-comments (which, as in Rust,
are comments prefixed by either /// or /**). Doc-comments allow third-party tools to
automatically generate documentation for functions defined in a Rhai script.
A new API, Engine::gen_fn_metadata_to_json and Engine::gen_fn_metadata_with_ast_to_json,
paired with the new metadata feature, exports the full list of functions metadata
(including those in an AST) as a JSON document.
There are also a sizable number of bug fixes.
- Unary prefix operators
-,+and!now bind correctly when applied to an expression. Previously,-x.lenis parsed as(-x).lenwhich is obviously counter-intuitive. - Indexing of namespace-qualified variables now work properly, such as
path::to::var[x]. - Constants are no longer propagated by the optimizer if shadowed by a non-constant variable.
- A constant passed as the
thisparameter to Rhai functions now throws an error if assigned to. - Generic type parameter of
Engine::register_iteratorisIntoIteratorinstead ofIterator. - Fixes parsing of block comments ending with
**/or inner blocks starting with//*.
Engine::on_progressnow takesu64instead of&u64.- The closure for
Engine::on_debugnow takes two additional parameters:source: Option<&str>andpos: Position. AST::iter_functionsnow returnsScriptFnMetadata.- The parser function passed to
Engine::register_custom_syntax_rawnow takes an additional parameter containing the look-ahead symbol.
AST::iter_functionsnow returnsScriptFnMetadatawhich includes, among others, doc-comments for functions prefixed by///or/**.- Doc-comments can be enabled/disabled with the new
Engine::set_doc_commentsmethod. - A new feature
metadatais added that pulls inserde_jsonand enablesEngine::gen_fn_metadata_to_jsonandEngine::gen_fn_metadata_with_ast_to_jsonwhich exports the full list of functions metadata (including those inside anAST) in JSON format. Engine::on_debugprovides two additional parameters:source: Option<&str>andpos: Position, containing the current source (if any) and position of thedebugstatement.NativeCallContextandEvalContextboth exposesource()which returns the current source, if any.
- A functions lookup cache is added to make function call resolution faster.
- Capturing a constant variable in a closure is now supported, with no cloning.
- A look-ahead symbol is provided to custom syntax parsers, which can be used to parse variable-length symbol streams.
- Fixes compilation errors with certain feature flag combinations.
- Property getters/setters and indexers defined in a plugin module are by default
#[rhai_fn(global)]. to_debugis a new standard function for converting a value into debug format.- Arrays and object maps now print values using
to_debug(if available).
This version adds the switch statement.
It also allows exposing selected module functions (usually methods) to the global namespace. This is very convenient when encapsulating the API of a custom Rust type into a module while having methods and iterators registered on the custom type work normally.
A new gen_fn_signatures API enables enumerating the registered functions of an Engine for documentation purposes.
It also prepares the way for a future reflection API.
- Custom syntax that introduces a shadowing variable now works properly.
Module::set_fn,Module::set_raw_fnandModule::set_fn_XXX_mutall take an additional parameter ofFnNamespace.Module::set_fntakes a further parameter with a list of parameter names/types plus the function return type, if any.Module::get_sub_module_mutis removed.begin,end,unlessare now reserved keywords.EvalPackageis removed in favor ofEngine::disable_symbol.
- New
switchstatement. - New
do ... whileanddo ... untilstatements. - New
Engine::gen_fn_signatures,Module::gen_fn_signaturesandPackagesCollection::gen_fn_signaturesto generate a list of signatures for functions registered. - New
Engine::register_static_moduleto register a module as a sub-module in the global namespace. - New
set_exported_global_fn!macro to register a plugin function and expose it to the global namespace. Module::set_fn_XXX_mutcan expose a module function to the global namespace. This is convenient when registering an API for a custom type.Module::set_getter_fn,Module::set_setter_fn,Module::set_indexer_get_fn,Module::set_indexer_set_fnall expose the function to the global namespace by default. This is convenient when registering an API for a custom type.- New
Module::update_fn_metadatato update a module function's parameter names and types. - New
#[rhai_fn(global)]and#[rhai_fn(internal)]attributes to determine whether a function defined in a plugin module should be exposed to the global namespace. This is convenient when defining an API for a custom type. - New
get_fn_metadata_listto get the metadata of all script-defined functions in scope.
- New constants under
DynamicincludingUNIT,TRUE,FALSE,ZERO,ONEetc. - Floating-point numbers ending with a decimal point without a trailing
0are supported.
This version fixes a bug that prevents compilation with the internals feature.
It also speeds up importing modules.
- Fixes compilation error when using the
internalsfeature. Bug introduced in0.19.4. - Importing script files recursively no longer panics.
- Modules imported at global level can now be accessed in functions.
ModuleResolver::resolvenow returnsShared<Module>for better resources sharing when loading modules.ParseErrorType::DuplicatedExportis removed as multipleexport's are now allowed.
- Modules imported via
importstatements at global level can now be used in functions. There is no longer any need to re-importthe modules at the beginning of each function block. - Modules imported via
importstatements are encapsulated into theASTwhen loading a module from a script file. exportkeyword can now be tagged ontoletandconststatements as a short-hand, e.g.:export let x = 42;- Variables can now be
export-ed multiple times under different names. index_of,==and!=are defined for arrays.==and!=are defined for object maps.
This version basically cleans up the code structure in preparation for a potential 1.0 release in the future.
Most scripts should see a material speed increase.
This version also adds a low-level API for more flexibility when defining custom syntax.
- Fixes
Send + SyncforEvalAltResultunder thesyncfeature. Bug introduced with0.19.3.
- Custom syntax can no longer start with a keyword (even a reserved one), even if it has been disabled. That is to avoid breaking scripts later when the keyword is no longer disabled.
EvalAltResult::ErrorAssignmentToUnknownLHSis moved toParseError::AssignmentToInvalidLHS.ParseError::AssignmentToCopyis removed.EvalAltResult::ErrorDataTooLargeis simplified.Engine::on_progressclosure signature now returnsOption<Dynamic>with the termination value passed on toEvalAltResult::ErrorTerminated.ParseErrorType::BadInputnow wraps aLexErrorinstead of a text string.
f32_floatfeature to setFLOATtof32.- Low-level API for custom syntax allowing more flexibility in designing the syntax.
Module::fill_withto poly-fill a module with another.- Scripts terminated via
Engine::on_progresscan now pass on a value as a termination token.
- Essential AST structures like
ExprandStmtare packed into smaller sizes (16 bytes and 32 bytes on 64-bit), stored inline for more cache friendliness, and de-Boxed as much as possible. Scopeis optimized for cache friendliness.
This version streamlines some of the advanced API's, and adds the try ... catch statement
to catch exceptions.
EvalAltResult::ErrorReadingScriptFileis removed in favor of the newEvalAltResult::ErrorSystem.EvalAltResult::ErrorLoopBreakis renamed toEvalAltResult::LoopBreak.Engine::register_raw_fnandFnPtr::call_dynamicfunction signatures have changed.- Callback signatures to
Engine::on_varandEngine::register_custom_syntaxhave changed. EvalAltResult::ErrorRuntimenow wraps aDynamicinstead of a string.- Default call stack depth for
debugbuilds is reduced to 8 (from 12) because it keeps overflowing the stack in GitHub CI! - Keyword
threadis reserved.
- The plugins system is enhanced to support functions taking a
NativeCallContextas the first parameter. throwstatement can now throw any value instead of just text strings.- New
try...catchstatement to catch exceptions.
- Calling
evalorFnin method-call style, which is an error, is now caught during parsing. func!()call style is valid even underno_closurefeature.
Bug fix on call module functions.
This version adds a variable resolver with the ability to short-circuit variable access, plus a whole bunch of array methods.
AST::iter_functionsnow returns an iterator instead of taking a closure.Module::get_script_function_by_signaturerenamed toModule::get_script_fnand returns&<Shared<ScriptFnDef> >.Module::num_fn,Module::num_varandModule::num_iterare removed and merged intoModule::count.- The
merge_namespacesparameter toModule::eval_ast_as_newis removed and now defaults totrue. GlobalFileModuleResolveris removed because its performance gain over theFileModuleResolveris no longer very significant.- The following
EvalAltResultvariants are removed and merged intoEvalAltResult::ErrorMismatchDataType:ErrorCharMismatch,ErrorNumericIndexExpr,ErrorStringIndexExpr,ErrorImportExpr,ErrorLogicGuard,ErrorBooleanArgMismatch Scope::iter_rawreturns an iterator with an additional field indicating whether the variable is constant or not.rhai::serandrhai::denamespaces are merged intorhai::serde.- New reserved symbols:
++,--,..,.... - Callback signature for custom syntax implementation function is changed to allow for more flexibility.
- Default call stack depth for
debugbuilds is reduced to 12 (from 16). - Precedence for
~is raised, whileinis moved below logic comparison operators.
- New
Engine::on_varto register a variable resolver. conststatements can now take any expression (or none at all) instead of only constant values.OptimizationLevel::Simplenow eagerly evaluates built-in binary operators of primary types (if not overloaded).is_def_var()to detect if variable is defined, andis_def_fn()to detect if script function is defined.Dynamic::from(&str)now constructs aDynamicwith a copy of the string as value.AST::combineandAST::combine_filteredallows combining twoAST's without creating a new one.map,filter,reduce,reduce_rev,some,all,extract,splice,chopandsortfunctions for arrays.- New
Module::set_iterableandModule::set_iteratorto define type iterators more easily.Engine::register_iteratoris changed to use the simpler version.
- Many one-liners and few-liners are now marked
#[inline]or[inline(always)], just in case it helps when LTO is not turned on.
The major new feature for this version is Plugins support, powered by procedural macros.
Plugins make it extremely easy to develop and register Rust functions with an Engine.
ifstatement with an emptytrueblock would not evaluate thefalseblock. This is now fixed.- Fixes a bug in
Module::set_fn_4_mut. - Module API's now properly handle
&strandStringparameters. - Indexers are available under
no_object. - Registered operator-assignment functions (e.g.
+=) now work correctly.
Engine::register_set_resultandEngine::register_indexer_set_resultnow take a function that returnsResult<(), Box<EvalAltResult> >.Engine::register_indexer_XXXandModule::set_indexer_XXXpanic when the type isArray,MaporString.EvalAltResulthas a new variantErrorInModulewhich holds errors when loading an external module.Module::eval_ast_as_newnow takes an extra boolean parameter, indicating whether to encapsulate the entire module into a separate namespace.- Functions in
FileModuleResolverloaded modules now can cross-call each other in addition to functions in the global namespace. For the old behavior, useMergingFileModuleResolverinstead. - New
EvalAltResult::ErrorInModulevariant capturing errors when loading a module from a script file.
- Plugins support via procedural macros.
- Scripted functions are allowed in packages.
parse_intandparse_floatfunctions for parsing numbers;splitfunction for splitting strings.AST::iter_functionsandModule::iter_script_fn_infoto iterate functions.- Functions iteration functions for
ASTandModulenow takeFnMutinstead ofFn. - New
FileModuleResolverthat encapsulates the entireASTof the module script, allowing function cross-calling. The old version is renamedMergingFileModuleResolver. +and-operators for timestamps to increment/decrement by seconds.
Engine::compile_expression,Engine::eval_expressionetc. no longer parse anonymous functions and closures.- Imported modules now work inside closures.
- Closures that capture now work under
no_object.
- Adds
Module::combine_flattento combine two modules while flattening to the root level.
- Fixes bug that prevents calling functions in closures.
- Fixes bug that erroneously consumes the first argument to a namespace-qualified function call.
Module::contains_fnandModule::get_script_fnno longer take thepublic_onlyparameter.
- Adds
Engine::register_get_result,Engine::register_set_result,Engine::register_indexer_get_result,Engine::register_indexer_set_resultAPI. - Adds
Module::combineto combine two modules. Engine::parse_jsonnow also accepts a JSON object starting with#{.
This version adds:
- Anonymous functions (in Rust closure syntax). Simplifies creation of single-use ad-hoc functions.
- Currying of function pointers.
- Closures - auto-currying of anonymous functions to capture shared variables from the external scope. Use the
no_closurefeature to disable sharing values and capturing. - Binding the
thispointer in a function pointercall. - Capturing call scope via
func!(...)syntax.
callcan now be called function-call style for function pointers - this is to handle builds withno_object.- Reserve language keywords, such as
print,eval,call,thisetc. x.call(f, ...)allows bindingxtothisfor the function referenced by the function pointerf.- Anonymous functions are supported in the syntax of a Rust closure, e.g.
|x, y, z| x + y - z. - Custom syntax now works even without the
internalsfeature. - Currying of function pointers is supported via the new
currykeyword. - Automatic currying of anonymous functions to capture shared variables from the external scope.
- Capturing of the calling scope for function call via the
func!(...)syntax. Module::set_indexer_get_set_fnis added as a short-hand of bothModule::set_indexer_get_fnandModule::set_indexer_set_fn.- New
unicode-xid-identfeature to allow Unicode Standard Annex #31 for identifiers. Scope::iter_rawreturns an iterator with a reference to the underlyingDynamicvalue (which may be shared).
- Language keywords are now reserved (even when disabled) and they can no longer be used as variable names.
- Function signature for defining custom syntax is simplified.
Engine::register_raw_fn_XXXAPI shortcuts are removed.PackagesCollection::get_fn,PackagesCollection::contains_fn,Module::get_fnandModule::contains_fnnow take an additionalpublic_onlyparameter indicating whether only public functions are accepted.- The iterator returned by
Scope::iternow contains a clone of theDynamicvalue (unshared). Engine::register_global_moduletakes any type that isInto<PackageLibrary>.- Error in
Engine::register_custom_syntaxis no longerBox-ed.
- Most compilation warnings are eliminated via feature gates.
This version adds:
serdesupport for working withDynamicvalues (particularly object maps).- Low-level API to register functions.
- Surgically disable keywords and/or operators in the language.
- Define custom operators.
- Extend the language via custom syntax.
- Fixed method calls in the middle of a dot chain.
EvalAltResult::ErrorMismatchOutputTypehas an extra argument containing the name of the requested type.Engine::call_fn_dynamictake an extra argument, allowing aDynamicvalue to be bound to thethispointer.- Precedence of the
%(modulo) operator is lowered to below bit shifts. This is to handle the case ofx < < 3 % 10.
- New
serdefeature to allow serializing/deserializing to/fromDynamicvalues usingserde. This is particularly useful when converting a Ruststructto aDynamicobject map and back. Engine::disable_symbolto surgically disable keywords and/or operators.Engine::register_custom_operatorto define a custom operator.Engine::register_custom_syntaxto define a custom syntax.- New low-level API
Engine::register_raw_fn. - New low-level API
Module::set_raw_fnmirroringEngine::register_raw_fn. AST::clone_functions_only,AST::clone_functions_only_filteredandAST::clone_statements_onlyto clone only part of anAST.- The boolean
^(XOR) operator is added. FnPtris exposed as the function pointer type.rhai::module_resolvers::ModuleResolversCollectionadded to try a list of module resolvers.- It is now possible to mutate the first argument of a namespace-qualified function call when the argument is a simple variable (but not a module constant).
- Many configuration/setting API's now returns
&mut Selfso that the calls can be chained. Stringparameters in functions are supported (but inefficiently).
Bug fix release to fix errors when compiling with features.
The major new feature in this version is OOP - well, poor man's OOP, that is.
The README is officially transferred to The Rhai Book.
An online Playground is available.
- The trait function
ModuleResolver::resolveno longer takes aScopeas argument. - Functions defined in script now differentiates between using method-call style and normal function-call style.
The method-call style will bind the object to the
thisparameter instead of consuming the first parameter. - Imported modules are no longer stored in the
Scope.Scope::push_moduleis removed. Therefore, cannot rely on module imports to persist across invocations using aScope. AST::retain_functionsis used for another purpose. The oldAST::retain_functionsis renamed toAST::clear_statements.
- Support for function pointers via
Fn(name)andFn.call(...)syntax - a poor man's first-class function. - Support for calling script-defined functions in method-call style with
thisbinding to the object. - Special support in object maps for OOP.
- Expanded the
ASTAPI for fine-tuned manipulation of functions.
- The Rhai Book is online. Most content in the original
READMEwas transferred to the Book. - New feature
internalsto expose internal data structures (e.g. the AST nodes).
This is a minor release which enables updating indexers (via registered indexer setters) and supports functions
with &str parameters (maps transparently to ImmutableString). WASM is also a tested target.
let s="abc"; s[1].change_to('X');now correctly sets the character 'X' into 's' yielding"aXc".
- Callback closure passed to
Engine::on_progressnow takes&u64instead ofu64to be consistent with other callback signatures. Engine::register_indexeris renamed toEngine::register_indexer_get.Module::set_indexer_fnis renamed toModule::set_indexer_get_fn.- The tuple
ParseErrornow exposes the internal fields and theParseError::error_typeandParseError::positionmethods are removed. The first tuple field is theParseErrorTypeand the second tuple field is thePosition. Engine::call_fn_dynamicnow takes any type that implementsIntoIterator<Item = Dynamic>.
- Indexers are now split into getters and setters (which now support updates). The API is split into
Engine::register_indexer_getandEngine::register_indexer_setwithEngine::register_indexer_get_setbeing a short-hand. Similarly,Module::set_indexer_get_fnandModule::set_indexer_set_fnare added. Engine:register_fnandEngine:register_result_fnaccepts functions that take parameters of type&str(immutable string slice), which maps directly toImmutableString. This is to avoid needing wrappers for functions taking string parameters.- Set maximum limit on data sizes:
Engine::set_max_string_size,Engine::set_max_array_sizeandEngine::set_max_map_size. - Supports trailing commas on array literals, object map literals, function definitions and function calls.
- Enhances support for compiling to WASM.
This version uses immutable strings (ImmutableString type) and built-in operator functions (e.g. +, >, +=) to improve speed, plus some bug fixes.
- Do not optimize script with
eval_expression- it is assumed to be one-off and short.
- Indexing with an index or dot expression now works property (it compiled wrongly before).
For example,
let s = "hello"; s[s.len-1] = 'x';now works property instead of causing a runtime error. ifexpressions are not supposed to be allowed when compiling for expressions only. This is fixed.
Engine::compile_XXXfunctions now returnParseErrorinstead ofBox<ParseError>.- The
RegisterDynamicFntrait is merged into theRegisterResultFntrait which now always returnsRhaiResult. - 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::ImmutableStringis used instead ofstd::string::String. This is to avoid excessive cloning of strings. All native-Rust functions taking string parameters should switch torhai::ImmutableString(which is eitherRc<String>orArc<String>depending on whether thesyncfeature is used). - Native Rust functions registered with the
Enginealso mutates the first argument when called in normal function-call style (previously the first argument will be passed by value if not called in method-call style). Of course, if the first argument is a calculated value (e.g. result of an expression), then mutating it has no effect, but at least it is not cloned. - Some built-in methods (e.g.
lenfor string,floorforFLOAT) now have property versions in addition to methods to simplify coding.
- Set limit on maximum level of nesting expressions and statements to avoid panics during parsing.
- New
EvalPackageto disableeval. Module::set_getter_fn,Module::set_setter_fnandModule:set_indexer_fnto register getter/setter/indexer functions.Engine::call_fn_dynamicfor more control in calling script functions.
- Common operators (e.g.
+,>,==) now call into highly efficient built-in implementations for standard types (i.e.INT,FLOAT,bool,char,()andImmutableString) if not overridden by a registered function. This yields a 5-10% speed benefit depending on script operator usage. Scripts running tight loops will see significant speed-up. - Common assignment operators (e.g.
+=,%=) now call into highly efficient built-in implementations for standard types (i.e.INT,FLOAT,bool,char,()andImmutableString) if not overridden by a registered function. - Implementations of common operators for standard types are removed from the
ArithmeticPackageandLogicPackage(and therefore theCorePackage) because they are now always available, even underEngine::new_raw. - Operator-assignment statements (e.g.
+=) are now handled directly and much faster. - Strings are now immutable and use the
rhai::ImmutableStringtype, eliminating large amounts of cloning. - For Native Rust functions taking a first
&mutparameter, the first argument is passed by reference instead of by value, even if not called in method-call style. This allows many functions declared with&mutparameter to avoid excessive cloning. For example, ifais a large array, getting its length in this manner:len(a)used to result in a full clone ofabefore taking the length and throwing the copy away. Now,ais simply passed by reference, avoiding the cloning altogether. - A custom hasher simply passes through
u64keys without hashing to avoid function call hash keys (which are by themselvesu64) being hashed twice.
The major features for this release is modules, script resource limits, and speed improvements (mainly due to avoiding allocations).
- Modules and module resolvers allow loading external scripts under a module namespace. A module can contain constant variables, Rust functions and Rhai functions.
exportvariables andprivatefunctions.- Indexers for Rust types.
- Track script evaluation progress and terminate script run.
- Set limit on maximum number of operations allowed per script run.
- Set limit on maximum number of modules loaded per script run.
- A new API,
Engine::compile_scripts_with_scope, can compile a list of script segments without needing to first concatenate them together into one large string. - Stepped
rangefunction with a custom step.
A script contains many lists - statements in a block, arguments to a function call etc.
In a typical script, most of these lists tend to be short - e.g. the vast majority of function calls contain
fewer than 4 arguments, while most statement blocks have fewer than 4-5 statements, with one or two being
the most common. Before, dynamic Vec's are used to hold these short lists for very brief periods of time,
causing allocations churn.
In this version, large amounts of allocations are avoided by converting to a StaticVec -
a list type based on a static array for a small number of items (currently four) -
wherever possible plus other tricks. Most real-life scripts should see material speed increases.
Almost all variable lookups, as well as lookups in loaded modules, are now pre-computed. A variable's name is almost never used to search for the variable in the current scope.
Getters and setter function names are also pre-computed and cached, so no string allocations are performed during a property get/set call.
Lookup of all function calls, including Rust and Rhai ones, are now through pre-computed hashes. The function name is no longer used to search for a function, making function call dispatches much faster.
The expression (Expr) and statement (Stmt) types are modified so that all of the variants contain only
one single Box to a large allocated structure containing all the fields. This makes the Expr and
Stmt types very small (only one single pointer) and improves evaluation speed due to cache efficiency.
Previously, when an error occurs inside a function call, the error position reported is the function call site. This makes it difficult to diagnose the actual location of the error within the function.
A new error variant EvalAltResult::ErrorInFunctionCall is added in this version.
It wraps the internal error returned by the called function, including the error position within the function.