Eager Operator Evaluation
Most operators are actually function calls, and those functions can be overridden, so whether they are optimized away depends on the situation:
Rhai guarantees that no external function will be run, which may trigger side-effects
(unless the optimization level is OptimizationLevel::Full
).
-
if the operands are not constant values, it is not optimized;
-
if the operator is overloaded, it is not optimized because the overloading function may not be pure (i.e. may cause side-effects when called);
-
if the operator is not built-in (see list of built-in operators), it is not optimized;
-
if the operator is a built-in operator for a standard type, it is called and replaced by a constant result.
// The following is most likely generated by machine.
const DECISION = 1; // this is an integer, one of the standard types
if DECISION == 1 { // this is optimized into 'true'
:
} else if DECISION == 2 { // this is optimized into 'false'
:
} else if DECISION == 3 { // this is optimized into 'false'
:
} else {
:
}
// Or an equivalent using 'switch':
switch DECISION {
1 => ..., // this statement is promoted
2 => ..., // this statement is eliminated
3 => ..., // this statement is eliminated
_ => ... // this statement is eliminated
}
Pre-Evaluation of Constant Expressions
Because of the eager evaluation of operators for standard types, many constant expressions will be evaluated and replaced by the result.
let x = (1+2) * 3 - 4/5 % 6; // will be replaced by 'let x = 9'
let y = (1 > 2) || (3 <= 4); // will be replaced by 'let y = true'
For operators that are not optimized away due to one of the above reasons, the function calls are simply left behind.
// Assume 'new_state' returns some custom type that is NOT one of the standard types.
// Also assume that the '==' operator is defined for that custom type.
const DECISION_1 = new_state(1);
const DECISION_2 = new_state(2);
const DECISION_3 = new_state(3);
if DECISION == 1 { // NOT optimized away because the operator is not built-in
: // and may cause side-effects if called!
:
} else if DECISION == 2 { // same here, NOT optimized away
:
} else if DECISION == 3 { // same here, NOT optimized away
:
} else {
:
}
Alternatively, turn the optimizer to OptimizationLevel::Full
.