Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small enhancements. #766

Merged
merged 21 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
Rhai Release Notes
==================

Version 1.17.0
==============

Potentially breaking changes
----------------------------

* `ImmutableString` now derefs to `&str` instead of `&SmartString`. Normally this should not be a breaking change.
* Traits implemented by `ImmutableString` are cleaned up. However, I cannot guarantee that there are absolutely no breaking changes, although I try to be careful.
* `EvalContext::new`, `FloatWrapper` and `ConditionalExpr` are now exported only under `internals`.

Deprecated API's
----------------

* `rhai::config::hashing::set_ahash_seed`, `rhai::config::hashing::get_ahash_seed` and the `RHAI_AHASH_SEED` environment variable are deprecated in favor of `rhai::config::hashing::set_hashing_seed`, `rhai::config::hashing::get_hashing_seed` and `RHAI_HASHING_SEED`.

Enhancements
------------

* Added `to_int` method for characters.
* `Token::FloatConstant` and `Token::DecimalConstant` now carry the original text representation for use in, say, a _token mapper_.


Version 1.16.2
==============

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = [".", "codegen"]

[package]
name = "rhai"
version = "1.16.2"
version = "1.17.0"
rust-version = "1.66.0"
edition = "2018"
resolver = "2"
Expand Down
7 changes: 5 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ fn main() {
// Tell Cargo that if the given environment variable changes, to rerun this build script.
println!("cargo:rerun-if-changed=build.template");
println!("cargo:rerun-if-env-changed=RHAI_AHASH_SEED");
println!("cargo:rerun-if-env-changed=RHAI_HASHING_SEED");
let mut contents = String::new();

File::open("build.template")
.expect("cannot open `build.template`")
.read_to_string(&mut contents)
.expect("cannot read from `build.template`");

let seed = env::var("RHAI_AHASH_SEED").map_or_else(|_| "None".into(), |s| format!("Some({s})"));
let seed = env::var("RHAI_HASHING_SEED")
.or_else(|_| env::var("RHAI_AHASH_SEED"))
.map_or_else(|_| "None".into(), |s| format!("Some({s})"));

contents = contents.replace("{{AHASH_SEED}}", &seed);
contents = contents.replace("{{HASHING_SEED}}", &seed);

File::create("src/config/hashing_env.rs")
.expect("cannot create `config.rs`")
Expand Down
2 changes: 1 addition & 1 deletion build.template
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
//! This file is automatically recreated during build time by `build.rs` from `build.template`.

pub const AHASH_SEED: Option<[u64; 4]> = {{AHASH_SEED}};
pub const HASHING_SEED: Option<[u64; 4]> = {{HASHING_SEED}};
2 changes: 1 addition & 1 deletion no_std/no_std_test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn foo(_: core::alloc::Layout) -> ! {

#[panic_handler]
#[lang = "panic_impl"]
extern "C" fn rust_begin_panic(_: &core::panic::PanicInfo) -> ! {
fn rust_begin_panic(_: &core::panic::PanicInfo) -> ! {
core::intrinsics::abort();
}

Expand Down
13 changes: 3 additions & 10 deletions src/api/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ impl Engine {
collect_imports(&ast, &resolver, &mut imports);

if !imports.is_empty() {
while let Some(path) = imports.iter().next() {
while let Some(path) = imports.pop_first() {
let path = path.clone();

match self
Expand All @@ -141,7 +141,6 @@ impl Engine {

let module = shared_take_or_clone(module);

imports.remove(&path);
resolver.insert(path, module);
}
ast.set_resolver(resolver);
Expand Down Expand Up @@ -203,11 +202,7 @@ impl Engine {
scope: &Scope,
scripts: impl AsRef<[S]>,
) -> ParseResult<AST> {
self.compile_with_scope_and_optimization_level(
Some(scope),
scripts,
self.optimization_level,
)
self.compile_scripts_with_scope_raw(Some(scope), scripts, self.optimization_level)
}
/// Join a list of strings and compile into an [`AST`] using own scope at a specific optimization level.
///
Expand All @@ -217,7 +212,7 @@ impl Engine {
/// throughout the script _including_ functions. This allows functions to be optimized based on
/// dynamic global constants.
#[inline]
pub(crate) fn compile_with_scope_and_optimization_level<S: AsRef<str>>(
pub(crate) fn compile_scripts_with_scope_raw<S: AsRef<str>>(
&self,
scope: Option<&Scope>,
scripts: impl AsRef<[S]>,
Expand Down Expand Up @@ -283,8 +278,6 @@ impl Engine {
/// scope.push_constant("x", 10_i64); // 'x' is a constant
///
/// // Compile a script to an AST and store it for later evaluation.
/// // Notice that `Full` optimization is on, so constants are folded
/// // into function calls and operators.
/// let ast = engine.compile_expression_with_scope(&mut scope,
/// "2 + (x + x) * 2" // all 'x' are replaced with 10
/// )?;
Expand Down
4 changes: 2 additions & 2 deletions src/api/custom_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ impl Expression<'_> {
match self.0 {
#[cfg(not(feature = "no_module"))]
Expr::Variable(x, ..) if !x.1.is_empty() => None,
Expr::Variable(x, ..) => Some(x.3.as_str()),
Expr::Variable(x, ..) => Some(&x.3),
#[cfg(not(feature = "no_function"))]
Expr::ThisPtr(..) => Some(crate::engine::KEYWORD_THIS),
Expr::StringConstant(x, ..) => Some(x.as_str()),
Expr::StringConstant(x, ..) => Some(&x),
_ => None,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/api/definitions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ impl Module {
!f.metadata.name.contains('$') && !is_valid_function_name(&f.metadata.name);

#[cfg(not(feature = "no_custom_syntax"))]
let operator = operator || def.engine.is_custom_keyword(f.metadata.name.as_str());
let operator = operator || def.engine.is_custom_keyword(&f.metadata.name);

f.write_definition(writer, def, operator)?;
}
Expand Down
54 changes: 54 additions & 0 deletions src/api/deprecated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,27 @@ impl Dynamic {
}
}

impl AST {
/// _(internals)_ Get the internal [`Module`][crate::Module] containing all script-defined functions.
/// Exported under the `internals` feature only.
///
/// Not available under `no_function`.
///
/// # Deprecated
///
/// This method is deprecated. Use [`shared_lib`][AST::shared_lib] instead.
///
/// This method will be removed in the next major version.
#[deprecated(since = "1.3.0", note = "use `shared_lib` instead")]
#[cfg(feature = "internals")]
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn lib(&self) -> &crate::Module {
self.shared_lib()
}
}

impl NativeCallContext<'_> {
/// Create a new [`NativeCallContext`].
///
Expand Down Expand Up @@ -1256,3 +1277,36 @@ pub mod deprecated_array_functions {
retain(ctx, array, FnPtr::new(filter)?)
}
}

pub mod config {
pub mod hashing {
/// Set the hashing seed. This is used to hash functions etc.
///
/// # Deprecated
///
/// This method is deprecated.
/// Use [`set_hashing_seed`][crate::config::hashing::set_hashing_seed] instead.
///
/// This method will be removed in the next major version.
#[deprecated(since = "1.17.0", note = "use `set_hashing_seed` instead")]
#[inline(always)]
pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
crate::config::hashing::set_hashing_seed(new_seed)
}

/// Get the current hashing Seed.
///
/// # Deprecated
///
/// This method is deprecated.
/// Use [`get_hashing_seed`][crate::config::hashing::get_hashing_seed] instead.
///
/// This method will be removed in the next major version.
#[deprecated(since = "1.17.0", note = "use `get_hashing_seed` instead")]
#[inline]
#[must_use]
pub fn get_ahash_seed() -> &'static Option<[u64; 4]> {
crate::config::hashing::get_hashing_seed()
}
}
}
7 changes: 2 additions & 5 deletions src/api/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use crate::types::dynamic::Variant;
use crate::types::StringsInterner;
use crate::{
Dynamic, Engine, OptimizationLevel, Position, RhaiResult, RhaiResultOf, Scope, AST, ERR,

Check warning on line 9 in src/api/eval.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --features testing-environ,no_optimize,serde,metadata,internals,debugging, ...

unused import: `OptimizationLevel`

Check warning on line 9 in src/api/eval.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --features testing-environ,no_time,no_function,no_float,no_position,no_inde...

unused import: `OptimizationLevel`

Check warning on line 9 in src/api/eval.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --features testing-environ,sync,no_time,no_function,no_float,no_position,no...

unused import: `OptimizationLevel`
};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
Expand Down Expand Up @@ -69,11 +69,8 @@
scope: &mut Scope,
script: &str,
) -> RhaiResultOf<T> {
let ast = self.compile_with_scope_and_optimization_level(
Some(scope),
[script],
self.optimization_level,
)?;
let ast =
self.compile_scripts_with_scope_raw(Some(scope), [script], self.optimization_level)?;
self.eval_ast_with_scope(scope, &ast)
}
/// Evaluate a string containing an expression, returning the result value or an error.
Expand Down
4 changes: 2 additions & 2 deletions src/api/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ impl Engine {
name: impl AsRef<str>,
get_fn: impl RegisterNativeFunction<(Mut<T>,), 1, C, V, L> + SendSync + 'static,
) -> &mut Self {
self.register_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn)
self.register_fn(crate::engine::make_getter(name.as_ref()), get_fn)
}
/// Register a setter function for a member of a registered type with the [`Engine`].
///
Expand Down Expand Up @@ -373,7 +373,7 @@ impl Engine {
name: impl AsRef<str>,
set_fn: impl RegisterNativeFunction<(Mut<T>, V), 2, C, (), L> + SendSync + 'static,
) -> &mut Self {
self.register_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn)
self.register_fn(crate::engine::make_setter(name.as_ref()), set_fn)
}
/// Short-hand for registering both getter and setter functions
/// of a registered type with the [`Engine`].
Expand Down
29 changes: 4 additions & 25 deletions src/ast/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl AST {
#[inline(always)]
#[must_use]
pub fn source(&self) -> Option<&str> {
self.source.as_ref().map(|s| s.as_str())
self.source.as_deref()
}
/// Get a reference to the source.
#[inline(always)]
Expand Down Expand Up @@ -882,20 +882,20 @@ impl AST {
#[cfg(not(feature = "internals"))]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
pub(crate) fn walk(&self, on_node: &mut impl FnMut(&[ASTNode]) -> bool) -> bool {
pub(crate) fn walk(&self, on_node: &mut (impl FnMut(&[ASTNode]) -> bool + ?Sized)) -> bool {
self._walk(on_node)
}
/// _(internals)_ Recursively walk the [`AST`], including function bodies (if any).
/// Return `false` from the callback to terminate the walk.
/// Exported under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
pub fn walk(&self, on_node: &mut impl FnMut(&[ASTNode]) -> bool) -> bool {
pub fn walk(&self, on_node: &mut (impl FnMut(&[ASTNode]) -> bool + ?Sized)) -> bool {
self._walk(on_node)
}
/// Recursively walk the [`AST`], including function bodies (if any).
/// Return `false` from the callback to terminate the walk.
fn _walk(&self, on_node: &mut impl FnMut(&[ASTNode]) -> bool) -> bool {
fn _walk(&self, on_node: &mut (impl FnMut(&[ASTNode]) -> bool + ?Sized)) -> bool {
let path = &mut Vec::new();

for stmt in self.statements() {
Expand Down Expand Up @@ -1043,24 +1043,3 @@ impl ASTNode<'_> {
}
}
}

impl AST {
/// _(internals)_ Get the internal [`Module`][crate::Module] containing all script-defined functions.
/// Exported under the `internals` feature only.
///
/// Not available under `no_function`.
///
/// # Deprecated
///
/// This method is deprecated. Use [`shared_lib`][AST::shared_lib] instead.
///
/// This method will be removed in the next major version.
#[deprecated(since = "1.3.0", note = "use `shared_lib` instead")]
#[cfg(feature = "internals")]
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub fn lib(&self) -> &crate::Module {
&self.lib
}
}
21 changes: 7 additions & 14 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Module defining script expressions.

use super::{ASTFlags, ASTNode, Ident, Namespace, Stmt, StmtBlock};
use crate::engine::{KEYWORD_FN_PTR, OP_EXCLUSIVE_RANGE, OP_INCLUSIVE_RANGE};
use crate::engine::KEYWORD_FN_PTR;
use crate::tokenizer::Token;
use crate::types::dynamic::Union;
use crate::{
Expand Down Expand Up @@ -30,16 +30,6 @@ pub struct BinaryExpr {
pub rhs: Expr,
}

impl From<(Expr, Expr)> for BinaryExpr {
#[inline(always)]
fn from(value: (Expr, Expr)) -> Self {
Self {
lhs: value.0,
rhs: value.1,
}
}
}

/// _(internals)_ A custom syntax expression.
/// Exported under the `internals` feature only.
///
Expand Down Expand Up @@ -490,7 +480,7 @@ impl Expr {
let mut map = x.1.clone();

for (k, v) in &x.0 {
*map.get_mut(k.name.as_str()).unwrap() = v.get_literal_value().unwrap();
*map.get_mut(k.as_str()).unwrap() = v.get_literal_value().unwrap();
}

Dynamic::from_map(map)
Expand Down Expand Up @@ -518,6 +508,9 @@ impl Expr {

// Binary operators
Self::FnCall(x, ..) if !x.is_qualified() && x.args.len() == 2 => {
pub const OP_EXCLUSIVE_RANGE: &str = Token::ExclusiveRange.literal_syntax();
pub const OP_INCLUSIVE_RANGE: &str = Token::InclusiveRange.literal_syntax();

match x.name.as_str() {
// x..y
OP_EXCLUSIVE_RANGE => match (&x.args[0], &x.args[1]) {
Expand Down Expand Up @@ -590,7 +583,7 @@ impl Expr {
match self {
#[cfg(not(feature = "no_module"))]
Self::Variable(x, ..) if _non_qualified && !x.1.is_empty() => None,
Self::Variable(x, ..) => Some(x.3.as_str()),
Self::Variable(x, ..) => Some(&x.3),
_ => None,
}
}
Expand Down Expand Up @@ -830,7 +823,7 @@ impl Expr {
pub fn walk<'a>(
&'a self,
path: &mut Vec<ASTNode<'a>>,
on_node: &mut impl FnMut(&[ASTNode]) -> bool,
on_node: &mut (impl FnMut(&[ASTNode]) -> bool + ?Sized),
) -> bool {
// Push the current node onto the path
path.push(self.into());
Expand Down
2 changes: 1 addition & 1 deletion src/ast/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl Ident {
#[inline(always)]
#[must_use]
pub fn as_str(&self) -> &str {
self.name.as_str()
&self.name
}
/// Is the identifier empty?
#[inline(always)]
Expand Down
Loading
Loading