reorganize module
This commit is contained in:
85
_archive/rhai_engine/rhaibook/engine/optimize/semantics.md
Normal file
85
_archive/rhai_engine/rhaibook/engine/optimize/semantics.md
Normal file
@@ -0,0 +1,85 @@
|
||||
Subtle Semantic Changes After Optimization
|
||||
==========================================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
|
||||
Some optimizations can alter subtle semantics of the script, causing the script to behave
|
||||
differently when run with or without optimization.
|
||||
|
||||
Typically, this involves some form of error that may arise in the original, unoptimized script but
|
||||
is optimized away by the [script optimizer][script optimization].
|
||||
|
||||
```admonish danger.small "DO NOT depend on runtime errors"
|
||||
|
||||
Needless to say, it is usually a _Very Bad Idea™_ to depend on a script failing with a runtime error
|
||||
or such kind of subtleties.
|
||||
|
||||
If it turns out to be necessary (why? I would never guess), turn script optimization off by setting
|
||||
the optimization level to [`OptimizationLevel::None`].
|
||||
```
|
||||
|
||||
|
||||
Disappearing Runtime Errors
|
||||
---------------------------
|
||||
|
||||
For example:
|
||||
|
||||
```rust
|
||||
if true { // condition always true
|
||||
123.456; // eliminated
|
||||
hello; // eliminated, EVEN THOUGH the variable doesn't exist!
|
||||
foo(42) // promoted up-level
|
||||
}
|
||||
|
||||
foo(42) // <- the above optimizes to this
|
||||
```
|
||||
|
||||
If the original script were evaluated instead, it would have been an error –
|
||||
the variable `hello` does not exist, so the script would have been terminated at that point
|
||||
with a runtime error.
|
||||
|
||||
In fact, any errors inside a statement that has been eliminated will silently _disappear_.
|
||||
|
||||
```rust
|
||||
print("start!");
|
||||
if my_decision { /* do nothing... */ } // eliminated due to no effect
|
||||
print("end!");
|
||||
|
||||
// The above optimizes to:
|
||||
|
||||
print("start!");
|
||||
print("end!");
|
||||
```
|
||||
|
||||
In the script above, if `my_decision` holds anything other than a boolean value,
|
||||
the script should have been terminated due to a type error.
|
||||
|
||||
However, after optimization, the entire [`if`] statement is removed (because an access to
|
||||
`my_decision` produces no side-effects), thus the script silently runs to completion without errors.
|
||||
|
||||
|
||||
Eliminated Useless Work
|
||||
-----------------------
|
||||
|
||||
Another example is more subtle – that of an empty loop body.
|
||||
|
||||
```rust
|
||||
// ... say, the 'Engine' is limited to no more than 10,000 operations...
|
||||
|
||||
// The following should fail because it exceeds the operations limit:
|
||||
for n in 0..42000 {
|
||||
// empty loop
|
||||
}
|
||||
|
||||
// The above is optimized away because the loop body is empty
|
||||
// and the iterations simply do nothing.
|
||||
()
|
||||
```
|
||||
|
||||
Normally, and empty loop body inside a [`for`] statement with a pure iterator does nothing and can
|
||||
be safely eliminated.
|
||||
|
||||
Thus the script now runs silently to completion without errors.
|
||||
|
||||
Without optimization, the script may fail by exceeding the [maximum number of operations] allowed.
|
Reference in New Issue
Block a user