Skip to main content

Evaluator

Struct Evaluator 

Source
pub struct Evaluator {
Show 19 fields pub globals: Vec<EnvironmentItem>, pub environment: Vec<Vec<EnvironmentItem>>, pub scope_pool: Vec<Vec<EnvironmentItem>>, pub source_file: Option<SourceFile>, pub root_module: Module, pub return_value: Option<Value>, pub is_breaking: bool, pub is_continuing: bool, pub output_buffer: Option<String>, pub rng: Xoshiro256, pub resolver: Resolver, pub fn_names: HashMap<String, usize>, pub user_args_offset: usize, pub net_handles: HashMap<i64, NetHandle>, pub net_next_handle: i64, pub http_handles: HashMap<i64, HttpHandle>, pub http_next_handle: i64, pub records: HashMap<String, Vec<(String, TypeAnnotation)>>, pub tags: HashMap<String, Vec<String>>,
}
Expand description

The tree-walking interpreter, carrying all runtime state.

Fields§

§globals: Vec<EnvironmentItem>

Global scope, addressed at the outermost depth

§environment: Vec<Vec<EnvironmentItem>>

The environment stack - each frame is a scope; innermost is last. Holds only local call frames

§scope_pool: Vec<Vec<EnvironmentItem>>

Pool of previously-used, now-empty scope frames. push_scope/ pop_scope recycle through here instead of allocating a fresh Vec on every function call and block entry - a hot recursive function otherwise pays one malloc+free per call just for its frame.

§source_file: Option<SourceFile>

Source file for Ariadne error rendering; None in embedded/test contexts.

§root_module: Module

The stdlib module tree, used for resolving std::* calls.

§return_value: Option<Value>

Set by a return statement; cleared when the enclosing function call collects it.

§is_breaking: bool

Set by break; cleared by the enclosing loop after it exits.

§is_continuing: bool

Set by continue; cleared by the enclosing loop at the top of the next iteration.

§output_buffer: Option<String>

When Some, print/println write here instead of stdout (used by the LSP and REPL).

§rng: Xoshiro256

The Xoshiro256** PRNG instance shared across all std::random calls.

§resolver: Resolver

The resolver, kept alive so import statements can resolve newly loaded files inline. Also owns ast_arena: Ast - the single expression arena for this session, shared by the resolver and evaluator alike. Never construct a second Ast anywhere else; everything reads/writes through self.resolver.ast_arena.

§fn_names: HashMap<String, usize>

Maps top-level function names to their environment slot for call_path shortcut.

§user_args_offset: usize§net_handles: HashMap<i64, NetHandle>

Side-table of native networking resources (std::net), keyed by handle id.

§net_next_handle: i64

Next handle id to hand out for std::net resources; only ever increments.

§http_handles: HashMap<i64, HttpHandle>

Side-table of native HTTP resources (std::http), keyed by handle id.

§http_next_handle: i64

Next handle id to hand out for std::http resources; only ever increments.

§records: HashMap<String, Vec<(String, TypeAnnotation)>>

Maps record type names to their declared (field name, field type) list, in declaration order. Populated when a RecordDeclaration statement runs.

§tags: HashMap<String, Vec<String>>

Maps tag (enum) type names to their declared variant name list, in declaration order. Populated when a TagDeclaration statement runs.

Implementations§

Source§

impl Evaluator

Source

pub fn new() -> Self

Source

pub fn with_source_file(self, file: SourceFile) -> Self

Attaches a source file for error rendering.

Source

pub fn set_source_file(&mut self, file: SourceFile)

Attaches a source file for error rendering (mutable reference variant).

Source

pub fn with_module(self, m: Module) -> Self

Registers a Module as a submodule of the root module.

Source

pub fn with_function<F, A>(self, name: impl Into<String>, f: F) -> Self
where F: IntoNativeFn<A>,

Registers a typed Rust function directly on the root module.

Source

pub fn with_stdlib(self) -> Self

Loads the full stdlib into the root module under std::*.

Source

pub fn with_user_args_offset(self, offset: usize) -> Self

Source

pub fn err(&self, message: impl Into<String>, span: Span) -> Error

Build a Reason::Runtime error anchored at span, with source attached when known.

Source

pub fn infer_type(value: &Value, is_const: bool) -> TypeAnnotation

Infers the TypeAnnotation of a runtime Value.

For arrays, uses the type of the first element; empty arrays infer Null. is_const controls whether the result is the mutable or const variant.

Source

pub fn value_compatible(value: &Value, expected: &TypeAnnotation) -> bool

Returns true if value’s inferred type is compatible with expected.

Source

pub fn types_compatible( actual: &TypeAnnotation, expected: &TypeAnnotation, ) -> bool

Returns true if actual and expected types are assignment-compatible.

Compatibility rules (beyond equality):

  • Null is compatible with anything
  • Byte widens to Int / CInt
  • Arrays are compatible if their element types are compatible (recursive)
Source

pub fn check_not_null(&self, value: &Value, span: Span) -> Result<(), Error>

Return an error if value is Value::Null, pointing at span.

Source

pub fn evaluate(&mut self, id: ExprId) -> Result<Value, Error>

Source

pub fn call_value( &mut self, func: Value, args: Vec<Value>, span: Span, ) -> Result<Value, Error>

Calls a Value::Function, setting up the captured environment, inserting arguments into a new scope, running the body, and validating the return type.

Global scope mutations made inside the call are propagated back to the caller.

Source

pub fn call_path( &mut self, path: &[String], args: Vec<Value>, span: Span, ) -> Result<Value, Error>

Resolves a call path and dispatches to either a stdlib [NativeFn] or a user-defined function looked up via [fn_names].

Resolution order:

  1. Full stdlib path via [root_module.resolve]
  2. Single-name shorthand via [fn_names]
  3. Error with “did you mean?” suggestion from stdlib keywords
Source§

impl Evaluator

Source

pub fn slot_ref(&self, depth: usize, slot: usize) -> Option<&EnvironmentItem>

Source

pub fn slot_mut( &mut self, depth: usize, slot: usize, ) -> Option<&mut EnvironmentItem>

Source

pub fn index_read_value( &self, arr: &Value, idx: &Value, target_span: Span, index_span: Span, span: Span, ) -> Result<Value, Error>

Reads arr[idx] given already-evaluated arr/idx values. Used by the general (non-fast-path) Index evaluation, for arrays, tuples, and maps alike.

Source

pub fn index_read( &self, depth: usize, slot: usize, indices: &[usize], span: Span, ) -> Result<Value, Error>

Reads a value by walking indices from the root (depth, slot), borrowing at every step and cloning only the single final element avoids cloning the whole container just to read one item out of it.

Source§

impl Evaluator

Source

pub fn index_assign( &mut self, target: ExprId, index: ExprId, value: ExprId, span: Span, ) -> Result<Value, Error>

Source§

impl Evaluator

Source

pub fn push_scope(&mut self)

Pushes a new empty scope frame onto the scope pool stack.

Source

pub fn pop_scope(&mut self)

Pops the innermost scope frame.

Source

fn ensure_slot( frame: &mut Vec<EnvironmentItem>, slot: usize, item: EnvironmentItem, )

Source

pub fn get_value( &self, depth: usize, slot: usize, span: Span, ) -> Result<Value, Error>

Reads the value at (depth, slot) in the environment.

depth counts from the innermost frame outward (0 = current). depth >= environment.len() means the target is the global scope.

Source

pub fn insert_value( &mut self, slot: usize, value: Value, type_annotation: TypeAnnotation, _: Span, ) -> Result<(), Error>

Inserts a mutable value at slot in the current (innermost) frame.

Grows the frame with Null placeholders if slot is past the end.

Source

pub fn insert_global( &mut self, slot: usize, value: Value, type_annotation: TypeAnnotation, )

Inserts a mutable value at slot in the global scope.

Used for top-level dec declarations, which live in self.globals rather than the local environment stack.

Source

pub fn insert_const( &mut self, slot: usize, value: Value, type_annotation: TypeAnnotation, span: Span, ) -> Result<(), Error>

Inserts an immutable (const) value at slot in the current frame.

Returns an error if the slot already holds a const.

Source

pub fn insert_const_global( &mut self, slot: usize, value: Value, type_annotation: TypeAnnotation, span: Span, ) -> Result<(), Error>

Inserts an immutable (const) value at slot in the global scope.

Used for top-level const declarations. Returns an error if the slot already holds a const.

Source

pub fn assign_value( &mut self, depth: usize, slot: usize, value: Value, value_type: TypeAnnotation, span: Span, ) -> Result<(), Error>

Overwrites the value at (depth, slot), enforcing type compatibility and immutability.

depth >= environment.len() means the target is the global scope.

Source

pub fn get_value_raw(&self, name: &str) -> Option<Value>

Looks up a variable by name via the resolver - used only in tests.

Source

pub fn get_declared_type( &self, depth: usize, slot: usize, ) -> Option<TypeAnnotation>

Returns the declared TypeAnnotation of the slot at (depth, slot), if it exists.

Source§

impl Evaluator

Source

fn type_mismatch_binary( &self, op: &str, left: &Value, left_span: Span, right: &Value, right_span: Span, span: Span, ) -> Error

Source

pub fn match_binary_operator( &mut self, left: Value, left_span: Span, right: Value, right_span: Span, operator: &TokenType, span: Span, ) -> Result<Value, Error>

Source§

impl Evaluator

Source

pub fn evaluate_statement(&mut self, statement: &Statement) -> Result<(), Error>

Evaluates a single statement, mutating the environment and control-flow flags.

Loop control (break, continue) and function return (return) are signalled via is_breaking, is_continuing, and return_value flags on Evaluator rather than exceptions, so callers must check these flags after each statement.

Source

fn evaluate_branch(&mut self, statement: &Statement) -> Result<bool, Error>

Evaluates a [ConditionalBranch] or [Conditional] and returns true if the branch was taken (condition was true or it was an else).

Source

pub fn evaluate_program( &mut self, statements: &[Statement], ) -> Result<(), Error>

The top-level entry point for a full rl program.

If a function is annotated !#[entry] or named main, only declarations and imports are evaluated first, then that function is called with no arguments. If no entry point exists, all statements are evaluated top-to-bottom (script mode).

Returns an error if multiple !#[entry] functions are found.

Source

pub fn evaluate_block(&mut self, statements: &[Statement]) -> Result<(), Error>

Evaluates a list of statements inside a fresh scope, used for inline blocks.

Source§

impl Evaluator

Source

fn type_mismatch_unary( &self, op: &str, operand: &Value, operand_span: Span, span: Span, ) -> Error

Source

pub fn match_unary_operator( &mut self, operand: Value, operand_span: Span, operator: &TokenType, span: Span, ) -> Result<Value, Error>

Trait Implementations§

Source§

impl Default for Evaluator

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Paint for T
where T: ?Sized,

§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling [Attribute] value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi [Quirk] value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the [Condition] value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new [Painted] with a default [Style]. Read more
§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.