Skip to content
Draft
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
7 changes: 1 addition & 6 deletions fuzz/fuzz_targets/grain_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,7 @@ fn compare(engine: &Engine, source: &str) -> Option<(String, String)> {

let program = Compiler::new().compile(&ast);
let mut vm_scope = Scope::new();
let ours = if program.makes_fn_pointers() {
let program = program.into_shared();
Vm::new(engine).eval_with_callbacks(&mut vm_scope, &program)
} else {
Vm::new(engine).eval_with_scope(&mut vm_scope, &program)
};
let ours = Vm::new(engine).eval_with_callbacks(&mut vm_scope, &program);
Some((outcome(&vm_scope, ours)?, expected))
}

Expand Down
10 changes: 2 additions & 8 deletions fuzz/fuzz_targets/grain_roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,12 @@ fuzz_target!(|source: String| {
return;
};

let program = Compiler::new().compile(&ast);
let program = Compiler::new().compile(&ast).into_shared();

let expected = outcome(|scope| engine.eval_ast_with_scope::<Dynamic>(scope, &ast));
// A program that can hand a pointer to a native has to be run the way such
// a program is meant to be run, or every one of them reads as a divergence.
let shared = program
.makes_fn_pointers()
.then(|| Compiler::new().compile(&ast).into_shared());
let run = |scope: &mut Scope| match &shared {
Some(shared) => Vm::new(&engine).eval_with_callbacks(scope, shared),
None => Vm::new(&engine).eval_with_scope(scope, &program),
};
let run = |scope: &mut Scope| Vm::new(&engine).eval_with_callbacks(scope, program);

let direct = outcome(run);
if expected == "budget" || direct == "budget" {
Expand Down
4 changes: 2 additions & 2 deletions src/eval/chaining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
impl Engine {
/// Call a get indexer.
#[inline]
fn call_indexer_get(
pub(crate) fn call_indexer_get(
&self,
global: &mut GlobalRuntimeState,
caches: &mut Caches,
Expand All @@ -78,7 +78,7 @@

/// Call a set indexer.
#[inline]
fn call_indexer_set(
pub(crate) fn call_indexer_set(
&self,
global: &mut GlobalRuntimeState,
caches: &mut Caches,
Expand Down Expand Up @@ -119,7 +119,7 @@
use_indexers: bool,
) -> RhaiResultOf<Target<'t>> {
#[cfg(not(feature = "no_index"))]
use std::convert::TryFrom;

Check warning on line 122 in src/eval/chaining.rs

View workflow job for this annotation

GitHub Actions / msrv

the item `TryFrom` is imported redundantly

self.track_operation(global, Position::NONE)?;

Expand Down
4 changes: 2 additions & 2 deletions src/eval/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::{Caches, GlobalRuntimeState};
use crate::ast::FnCallHashes;
use crate::tokenizer::{is_valid_function_name, Token};
use crate::tokenizer::{is_valid_identifier, Token};
use crate::types::dynamic::Variant;
use crate::{
calc_fn_hash, expose_under_internals, Dynamic, Engine, FnArgsVec, FuncArgs, ImmutableString,
Expand Down Expand Up @@ -351,7 +351,7 @@ impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
args: &mut [&mut Dynamic],
) -> RhaiResult {
let name = fn_name.as_ref();
let native_only = !is_valid_function_name(name);
let native_only = !is_valid_identifier(name);
#[cfg(not(feature = "no_function"))]
let native_only = native_only && !crate::parser::is_anonymous_fn(name);

Expand Down
10 changes: 5 additions & 5 deletions src/func/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#[cfg(feature = "internals")]
use crate::eval::EvalContext;
use crate::eval::{Caches, FnResolutionCacheEntry, GlobalRuntimeState};
use crate::tokenizer::{is_valid_function_name, Token};
use crate::tokenizer::{is_valid_identifier, Token};
use crate::types::{dynamic::Union, fn_ptr::FnPtrType};
use crate::{
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString, Position,
Expand All @@ -30,7 +30,7 @@

#[cfg(not(feature = "no_float"))]
#[cfg(feature = "no_std")]
use num_traits::Float;

Check warning on line 33 in src/func/call.rs

View workflow job for this annotation

GitHub Actions / NoStdBuild (ubuntu-latest, --profile unix, false)

unused import: `num_traits::Float`

Check warning on line 33 in src/func/call.rs

View workflow job for this annotation

GitHub Actions / NoStdBuild (macos-latest, --profile macos, false)

unused import: `num_traits::Float`

Check warning on line 33 in src/func/call.rs

View workflow job for this annotation

GitHub Actions / NoStdBuild (windows-latest, --profile windows, true)

unused import: `num_traits::Float`

/// Arguments to a function call, which is a list of [`&mut Dynamic`][Dynamic].
pub type FnCallArgs<'a> = [&'a mut Dynamic];
Expand Down Expand Up @@ -587,8 +587,8 @@
/// functions but provided by Rhai.
pub(crate) fn exec_syntactic_fn_call(
&self,
global: &mut GlobalRuntimeState,

Check warning on line 590 in src/func/call.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --tests --features testing-environ,no_float,only_i32,no_object,no_index,no_...

unused variable: `global`

Check warning on line 590 in src/func/call.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 variable: `global`

Check warning on line 590 in src/func/call.rs

View workflow job for this annotation

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

unused variable: `global`

Check warning on line 590 in src/func/call.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 variable: `global`
caches: &mut Caches,

Check warning on line 591 in src/func/call.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --tests --features testing-environ,no_float,only_i32,no_object,no_index,no_...

unused variable: `caches`

Check warning on line 591 in src/func/call.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 variable: `caches`

Check warning on line 591 in src/func/call.rs

View workflow job for this annotation

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

unused variable: `caches`

Check warning on line 591 in src/func/call.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 variable: `caches`
fn_name: &str,
args: &FnCallArgs,
pos: Position,
Expand Down Expand Up @@ -899,7 +899,7 @@
let _is_anon = fn_ptr.is_anonymous();

// Recalculate hashes
let new_hash = if !_is_anon && !is_valid_function_name(fn_name) {
let new_hash = if !_is_anon && !is_valid_identifier(fn_name) {
FnCallHashes::from_native_only(calc_fn_hash(None, fn_name, args.len()))
} else {
FnCallHashes::from_hash(calc_fn_hash(None, fn_name, args.len()))
Expand Down Expand Up @@ -1001,7 +1001,7 @@
// Recalculate hash
let num_args = args.len();

let new_hash = if !_is_anon && !is_valid_function_name(&name) {
let new_hash = if !_is_anon && !is_valid_identifier(&name) {
FnCallHashes::from_native_only(calc_fn_hash(None, &name, num_args))
} else {
#[cfg(not(feature = "no_function"))]
Expand Down Expand Up @@ -1106,7 +1106,7 @@
// Recalculate the hash based on the new function name and new arguments
let num_args = call_args.len() + 1;

hash = if !_is_anon && !is_valid_function_name(fn_name) {
hash = if !_is_anon && !is_valid_identifier(fn_name) {
FnCallHashes::from_native_only(calc_fn_hash(
None, fn_name, num_args,
))
Expand Down Expand Up @@ -1312,7 +1312,7 @@
// Recalculate hash
let args_len = num_args + curry.len();

hashes = if !_is_anon && !is_valid_function_name(fn_name) {
hashes = if !_is_anon && !is_valid_identifier(fn_name) {
FnCallHashes::from_native_only(calc_fn_hash(None, fn_name, args_len))
} else {
FnCallHashes::from_hash(calc_fn_hash(None, fn_name, args_len))
Expand Down
4 changes: 2 additions & 2 deletions src/func/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::call::FnCallArgs;
use crate::ast::FnCallHashes;
use crate::eval::{Caches, GlobalRuntimeState};
use crate::plugin::PluginFunc;
use crate::tokenizer::{is_valid_function_name, Token, TokenizeState};
use crate::tokenizer::{is_valid_identifier, Token, TokenizeState};
use crate::types::dynamic::Variant;
use crate::{
calc_fn_hash, expose_under_internals, Dynamic, Engine, EvalContext, FnArgsVec, FuncArgs,
Expand Down Expand Up @@ -468,7 +468,7 @@ impl<'a> NativeCallContext<'a> {
args: &mut [&mut Dynamic],
) -> RhaiResult {
let name = fn_name.as_ref();
let native_only = !is_valid_function_name(name);
let native_only = !is_valid_identifier(name);
#[cfg(not(feature = "no_function"))]
let native_only = native_only && !crate::parser::is_anonymous_fn(name);

Expand Down
33 changes: 0 additions & 33 deletions src/grain/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
.map(|()| (code, offsets)),
Err(..) => None,
};
let (code, offsets, main_ops, functions, skipped) = match assembled {

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --tests --features testing-environ,no_float,only_i32,no_object,no_index,no_...

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / NoStdBuild (ubuntu-latest, --profile unix, false)

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --features testing-environ,grain, stable, false)

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / msrv

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.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 variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / NoStdBuild (macos-latest, --profile macos, false)

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --tests --features testing-environ,only_i32,serde,metadata,internals,debugg...

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / NoStdBuild (windows-latest, --profile windows, true)

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, --tests --features testing-environ,f32_float,only_i32,serde,metadata,intern...

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.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 variable: `skipped`

Check warning on line 135 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused variable: `skipped`
Some((code, offsets)) => (code, offsets, main_ops, functions, skipped),
None => {
lowering = fresh();
Expand All @@ -157,9 +157,6 @@
name: f.name,
params: f.params,
this_type: f.this_type,
// Derived from the chunk by `Program::new`, which is the one
// place that can see the assembled bytes.
takes_this: false,
chunk: Chunk::new(
offsets[f.first_op],
offsets[f.first_op + f.op_count],
Expand All @@ -168,35 +165,6 @@
})
.collect();

// Rhai's own functions are carried whenever anything might still reach
// for them: a function this compiler skipped, or a fragment that could
// call one. With neither, every call resolves in the table above and
// the library — an `AST`'s whole function tree — can be dropped.
//
// The third case is a pointer to a `this`-taking chunk. Rhai reaches a
// compiled function through a registered wrapper, and a wrapper is
// registered at one arity — but a native calling a pointer against a
// receiver decides for itself how many arguments to append beside it,
// so no single arity is right. Rhai's own pointer carries the body and
// sizes the call from it, which is what its copy is kept here for. See
// `callback::wrappers`, which skips exactly these.
#[cfg(not(feature = "no_function"))]
let lib = {
let escapes_as_pointer = crate::grain::program::makes_fn_pointers(&code)
&& functions
.iter()
.any(|f| crate::grain::program::takes_this(&code, f.chunk, &lowering.chains));
let needs_walker = skipped > 0 || !lowering.residuals.is_empty() || escapes_as_pointer;
(needs_walker && !ast.shared_lib().is_empty()).then(|| ast.shared_lib().clone())
};
// Under `no_function` there is no function tree to carry, whichever way
// the fallbacks above went.
#[cfg(feature = "no_function")]
let lib = {
let _ = skipped;
None
};

let mut program = Program::new(
code.into(),
main,
Expand All @@ -212,7 +180,6 @@
assign_ops: lowering.assign_ops,
chains: lowering.chains,
switches: lowering.switches,
lib,
#[cfg(not(feature = "no_module"))]
resolver: ast.resolver.clone(),
source: ast.source().map(Into::into),
Expand Down Expand Up @@ -2426,7 +2393,7 @@
#[cfg(not(feature = "no_function"))]
mod tests {
use super::*;
use crate::grain::bytecode::StepFlags;

Check warning on line 2396 in src/grain/compile/mod.rs

View workflow job for this annotation

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

unused import: `crate::grain::bytecode::StepFlags`

/// Lowering order fixes every address inside a function, so it has to come
/// from the source rather than from a hash map.
Expand Down
11 changes: 11 additions & 0 deletions src/grain/compile/poolable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ use rust_decimal::Decimal;
/// created against. Keeping it out of the pool leaves it as a fragment, which
/// evaluates through the path that does the attaching.
pub(crate) fn is_poolable(value: &Dynamic) -> bool {
// A shared cell first, because every question below sees through one:
// `is_array` and friends unwrap `Union::Shared`, so a shared array of ints
// would answer yes and be pooled by cloning the `Rc` — leaving the pool
// aliasing a cell the host can still write to. Nothing a `Program` owns may
// alias mutable state: the pool is immutable after `Program::new`, and that
// is what makes the reference graph among programs acyclic.
#[cfg(not(feature = "no_closure"))]
if value.is_shared() {
return false;
}

// Under `no_float` Rhai has no float type and no `is_float` to ask, so
// there is nothing here for the question to be about.
#[cfg(not(feature = "no_float"))]
Expand Down
6 changes: 0 additions & 6 deletions src/grain/format/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ pub(super) fn read(bytes: &[u8]) -> Result<Program<'_>, ReadError> {
name,
this_type,
params,
// Not encoded: derived from the chunk by `Program::new`, so a loaded
// program and a compiled one cannot disagree about it.
takes_this: false,
chunk: get_chunk(&mut cursor)?,
});
}
Expand Down Expand Up @@ -248,9 +245,6 @@ pub(super) fn read(bytes: &[u8]) -> Result<Program<'_>, ReadError> {
assign_ops,
chains,
switches,
// Script functions are still ASTs, so `write` refuses a program
// that has any and a loaded one never does.
lib: None,
#[cfg(not(feature = "no_module"))]
resolver: None,
source,
Expand Down
3 changes: 0 additions & 3 deletions src/grain/format/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ pub(super) fn write(program: &Program, positions: Positions) -> Result<Vec<u8>,
pos,
});
}
if program.lib().is_some() {
return Err(WriteError::HasScriptFunctions);
}

let mut out = Vec::new();
out.extend_from_slice(&MAGIC);
Expand Down
2 changes: 1 addition & 1 deletion src/grain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,5 +149,5 @@ mod vm;

pub use compile::Compiler;
pub use format::{Sidecar, Stripped};
pub use program::Program;
pub use program::{Program, SharedProgram};
pub use vm::{Fault, Vm};
Loading
Loading