Variable Definition Filter

Although it is easy to disable variable shadowing via Engine::set_allow_shadowing, sometimes more fine-grained control is needed.

For example, it may be the case that not all variables shadowing must be disallowed, but that only a particular variable name needs to be protected and not others. Or only under very special circumstances.

Under this scenario, it is possible to provide a filter closure to the Engine via Engine::on_def_var that traps variable definitions (i.e. let or const statements) in a Rhai script.

The filter is called when a variable or constant is defined both during runtime and compilation.

let mut engine = Engine::new();

// Register a variable definition filter.
engine.on_def_var(|is_runtime, info, context| {
    match (info.name, info.is_const) {
        // Disallow defining 'MYSTIC_NUMBER' as a constant!
        ("MYSTIC_NUMBER", true) => Ok(false),
        // Disallow defining constants not at global level!
        (_, true) if info.nesting_level > 0 => Ok(false),
        // Throw any exception you like...
        ("hello", _) => Err(EvalAltResult::ErrorVariableNotFound(info.name.to_string(), Position::NONE).into()),
        // Return Ok(true) to continue with normal variable definition.
        _ => Ok(true)
    }
});

Function Signature

The function signature passed to Engine::on_def_var takes the following form.

Fn(is_runtime: bool, info: VarDefInfo, context: EvalContext) -> Result<bool, Box<EvalAltResult>>

where:

ParameterTypeDescription
is_runtimebooltrue if the variable definition event happens during runtime, false if during compilation
infoVarDefInfoinformation on the variable being defined
contextEvalContextthe current evaluation context

and VarDefInfo is a simple struct that contains the following fields:

FieldTypeDescription
name&strvariable name
is_constbooltrue if the definition is a const; false if it is a let
nesting_levelusizethe current nesting level; the global level is zero
will_shadowboolwill this variable shadow an existing variable of the same name?

and EvalContext is a type that encapsulates the current evaluation context.

Return value

The return value is Result<bool, Box<EvalAltResult>> where:

ValueDescription
Ok(true)normal variable definition should continue
Ok(false)throws a runtime or compilation error
Err(Box<EvalAltResult>)error that is reflected back to the Engine

During compilation (i.e. when is_runtime is false), EvalAltResult::ErrorParsing is passed through as the compilation error.

All other errors map to ParseErrorType::ForbiddenVariable.