pub struct ScriptFn { /* private fields */ }
Expand description
Assembly code for the Ad Astra Virtual Machine, ready for execution.
You can create this object using the compile function, and then run it using the ScriptFn::run function.
The ScriptFn object is cheap to Clone. In the case of cloning, each clone shares the same assembly code memory, but the execution context is unique to each clone.
§Virtual Machine Design Overview
The assembly code design is currently an implementation detail and is subject to continuous improvements, optimizations, and changes in future minor versions of Ad Astra. For this reason, the crate API does not provide direct access to manually alter the assembly code. However, for debugging purposes, you can print the internals to the terminal using the Debug implementation of the ScriptFn object.
The ScriptFn consists of Ad Astra assembly commands for the main script module function (the top-level source code of a module itself serves as the body of a function with zero parameters), as well as the assembly commands for other script functions from this module.
The runtime executes each assembly command of the script function sequentially. Some commands can conditionally or unconditionally jump to other commands in the list.
The commands interact with the stack of the current thread by pulling some Cells from the stack and pushing new Cells onto the stack. Therefore, the Virtual Machine is a stack-based machine.
§Isolation
Each assembly command is evaluated in a virtual environment. If for any reason a command fails, the Virtual Machine immediately stops execution and returns a RuntimeError from the ScriptFn::run function.
You can manually interrupt script function execution using the hook
mechanism. By setting a hook function with the
set_runtime_hook function, you enforce
the Virtual Machine to report every command execution to the hook. The hook,
in turn, can return false
to signal the Virtual Machine to stop execution
and return from ScriptFn::run with a RuntimeError::Interrupted error.
use ad_astra::interpret::set_runtime_hook;
set_runtime_hook(|_origin| true);
The hook function is configured per OS process thread. By default, the thread from which you call the ScriptFn::run function does not have a configured hook, meaning that you trust the script to finish its job without interruptions. In this trusting mode, script functions are executed slightly faster than with a configured hook, but the downside is that you cannot revoke control flow back to Rust until the Virtual Machine finishes its job. This could be an issue, for example, if the script code contains unconditional infinite loops.
Additionally, the hook function receives an Origin object as an argument that roughly points to the original source code statements and expressions of the script module that are about to be evaluated. You can use this feature to organize interactive script evaluation.
§Source Maps
In addition to the assembly commands, the ScriptFn object also holds a mapping between the assembly commands and the source ranges from which these commands were compiled.
The Virtual Machine uses this metadata to provide proper and descriptive runtime errors if a script execution flow ends with a script evaluation error.
§Concurrent Evaluation
Each script function is executed on the current OS thread from which it was run.
The Ad Astra base language does not provide a built-in mechanism for asynchronous script evaluation or thread management. However, you can organize a multi-threaded execution environment depending on your design goals using the export system.
For example, you can export a function from Rust to a script that takes another function as a parameter (e.g., Fn0). In the script, the author can call this exported Rust function, passing a script-defined function as an argument. The Rust function can then execute the provided script function in another thread.
#[export]
pub fn foo(f: Fn0<()>) {
spawn(move || {
let f = f;
let _ = f();
});
}
Implementations§
Source§impl ScriptFn
impl ScriptFn
Sourcepub fn run(&self) -> RuntimeResult<Cell>
pub fn run(&self) -> RuntimeResult<Cell>
Evaluates the script.
The function returns the evaluation result in the form of a Cell,
representing an object returned by the script using the return 100;
statement. If the script does not return any value, the function returns
Cell::nil.
If the script encounters a runtime error during execution, the function halts script execution immediately and returns a RuntimeError.
If the script execution is interrupted by the execution hook (configured via set_runtime_hook), this function returns a RuntimeError::Interrupted error.
By default, the current OS thread does not have a script hook, meaning that the Virtual Machine will execute the script until the end of the script’s control flow.
Sourcepub fn set_context(&mut self, context: Cell)
pub fn set_context(&mut self, context: Cell)
Sets the value of the self
script variable, allowing the module’s
source code to read script input data.
You can create the Cell using the Cell::give constructor by passing a value of any type known to the Ad Astra Runtime (either any built-in Rust type or any type exported using the export macro).
Each clone of the ScriptFn object may have a unique context value, but
the context can only be set once per ScriptFn instance. Subsequent calls
to the set_context
function will not change the previously set
context.
By default, the ScriptFn instance does not have an evaluation context,
and the self
variable is interpreted as “nil” within the script code.
Note that the script’s self
variable is generally mutable if the type
of the value supports mutations (e.g., number types are mutable). Thus,
the self
script variable can serve as both a data input and output
channel. If the value you set as the context is intended as the script’s
output, consider reading this value after the script
evaluation using the get_context
function.
Sourcepub fn get_context(&self) -> &Cell
pub fn get_context(&self) -> &Cell
Provides access to the value of the script’s self
variable, as
previously set by the set_context function.
By default, if the ScriptFn instance does not have an evaluation context value, this function returns Cell::nil.