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/_archive/rhai_engine/rhaibook/engine/optimize/op-eval.md
2025-04-04 08:28:07 +02:00

2.7 KiB

Eager Operator Evaluation

{{#include ../../links.md}}

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][operator overloading], 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][standard types], 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][built-in 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].