This repository has been archived on 2025-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
rhaj/rhai_engine/rhaibook/engine/optimize/eager.md
2025-04-03 09:18:05 +02:00

75 lines
2.6 KiB
Markdown

Eager Function Evaluation When Using Full Optimization Level
============================================================
{{#include ../../links.md}}
When the optimization level is [`OptimizationLevel::Full`], the [`Engine`] assumes all functions to
be _pure_ and will _eagerly_ evaluated all function calls with constant arguments, using the result
to replace the call.
This also applies to all operators (which are implemented as functions).
```rust
// When compiling the following with OptimizationLevel::Full...
const DECISION = 1;
// this condition is now eliminated because 'sign(DECISION) > 0'
if sign(DECISION) > 0 // <- is a call to the 'sign' and '>' functions, and they return 'true'
{
print("hello!"); // <- this block is promoted to the parent level
} else {
print("boo!"); // <- this block is eliminated because it is never reached
}
print("hello!"); // <- the above is equivalent to this
// ('print' and 'debug' are handled specially)
```
~~~admonish danger "Won't this be dangerous?"
Yes! _Very!_
```rust
// Nuclear silo control
if launch_nukes && president_okeyed {
print("This is NOT a drill!");
update_defcon(1);
start_world_war(3);
launch_all_nukes();
} else {
print("This is a drill. Thank you for your cooperation.");
}
```
In the script above (well... as if nuclear silos will one day be controlled by Rhai scripts),
the functions `update_defcon`, `start_world_war` and `launch_all_nukes` will be evaluated
during _compilation_ because they have constant arguments.
The [variables] `launch_nukes` and `president_okeyed` are never checked, because the script
actually has not yet been run! The functions are called during compilation.
This is, _obviously_, not what you want.
**Moral of the story: compile with an [`Engine`] that does not have any functions registered.
Register functions _AFTER_ compilation.**
~~~
~~~admonish question "Why would I ever want to do this then?"
Good question! There are two reasons:
* A function call may result in cleaner code than the resultant value.
In Rust, this would have been handled via a `const` function.
* Evaluating a value to a [custom type] that has no representation in script.
```rust
// A complex function that returns a unique ID based on the arguments
let id = make_unique_id(123, "hello", true);
// The above is arguably clearer than:
// let id = 835781293546; // generated from 123, "hello" and true
// A custom type that cannot be represented in script
let complex_obj = make_complex_obj(42);
```
~~~