Skip to main content

Vm

Struct Vm 

Source
pub struct Vm { /* private fields */ }
Expand description

the bytecode virtual machine.

holds the program being run, the value stack, the call-frame stack, the heap, the console buffer, the leak log, the persistent globals, and the original source text (needed to build a line-covering Span for a runtime error and for the REPL pipeline).

Implementations§

Source§

impl Vm

Source

pub fn new(program: Program, src: String) -> Vm

construct a VM ready to run program from its entry point.

pushes the initial CallFrame for program.main_index. src is the program’s source text – the VM keeps it to build a line-covering span for any runtime error and to drive the REPL pipeline.

Source

pub fn new_repl() -> Vm

construct an empty VM ready to receive REPL calls.

unlike Vm::new, there is no Program and no main frame yet – a REPL VM starts blank: an empty program, an empty heap, an empty console, an empty repl_history. the first Vm::repl_eval call builds the first real Program from the first line and runs it; every later call rebuilds the program from the whole accumulated source.

the empty Program has no chunks, so this VM must not be run() directly – repl_eval is the only entry point for a REPL VM. the persistent console / leak_log accumulate across repl_eval calls.

Source

pub fn render_value(&self, v: Value) -> (String, String)

render a runtime Value to its (display string, type name) pair.

the public counterpart of the in-crate Vm::value_to_string and Vm::runtime_type_name helpers, for an external consumer that holds a Value – specifically the qala CLI’s REPL, which evaluates a line against this VM and must display the result. the WASM bridge does not use this method (it is in-crate and reaches the two helpers directly, building a StateValue); this exists so the separate qala-cli crate has the same rendering without the two helpers leaving pub(crate).

purely additive: it calls the two existing helpers and changes no v1 behavior. never panics – the helpers are total over every Value.

Source

pub fn run(&mut self) -> Result<(), QalaError>

run the program from the current state to Halt or the first runtime error.

loops over Vm::dispatch_one; a Ran outcome continues, a Halted outcome returns Ok(()). shares every byte of execution logic with Vm::step – both go through dispatch_one.

Source

pub fn step(&mut self) -> Result<StepOutcome, QalaError>

advance exactly one instruction.

one step() call executes one full instruction including its operands: ip moves by 1 + operand_bytes() of the executed opcode. the playground’s step-through calls this in a loop. a thin wrapper over Vm::dispatch_one – no duplicated dispatch logic.

Source

pub fn get_state(&self) -> VmState

snapshot the VM’s execution state for the playground’s step-through.

the VmState carries the current chunk index and instruction pointer, the value stack (each slot rendered and type-tagged), the current frame’s in-scope variables paired with their REAL source names, the accumulated console output, and the leak log.

the output is deterministic – it iterates Vecs in index order, never a HashMap, so two get_state calls on the same VM state produce byte-identical snapshots (the contract Phase 6’s WASM bridge needs).

never panics. when frames is empty (the program has finished and the last frame returned) it reports a terminal snapshot: the last chunk index and an ip one past that chunk’s code – not an out-of-bounds index, not a panic. an out-of-range chunk_idx is handled the same defensive way.

Source

pub fn repl_eval(&mut self, source: &str) -> Result<Value, QalaError>

evaluate one line of REPL source against the persistent VM state.

the accumulating-source REPL: every prior accepted line plus source is concatenated into one wrapped program, the whole pipeline (lex, parse, typecheck, codegen) runs on it, and the result executes against this VM. because the whole accumulated program is rebuilt and re-run each call, a let binding from an earlier call is simply an earlier statement in the same body and is in scope for the new line – that is how state persists.

the wrapping shape: the accepted statements plus the new line live inside a synthetic fn __repl_main() is io { ... }. when the new line is an expression its value is captured via a let __repl_result = <expr> binding (the result this method returns); a statement line yields void. a line that parses as a top-level item (fn / struct / enum / interface) is placed OUTSIDE __repl_main as a sibling item and the result is void.

on a lexer / parser / typechecker / codegen error the error is returned and source is NOT appended to the history – a line that does not compile cannot poison later evaluations. the persistent console and leak_log survive across calls so output accumulates; the heap is naturally rebuilt each call because the whole program re-runs from scratch (correct and simplest – there is no stale heap state).

Auto Trait Implementations§

§

impl Freeze for Vm

§

impl RefUnwindSafe for Vm

§

impl Send for Vm

§

impl Sync for Vm

§

impl Unpin for Vm

§

impl UnsafeUnpin for Vm

§

impl UnwindSafe for Vm

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, 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.
Source§

impl<S, T> Upcast<T> for S
where T: UpcastFrom<S> + ?Sized, S: ?Sized,

Source§

fn upcast(&self) -> &T
where Self: ErasableGeneric, T: ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider ref type within the Wasm bindgen generics type system. Read more
Source§

fn upcast_into(self) -> T
where Self: Sized + ErasableGeneric, T: ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider type within the Wasm bindgen generics type system. Read more