Crate cas_vm

Crate cas_vm 

Source
Expand description

Virtual machine for cas-rs.

This crate provides Vm, a virtual machine that executes bytecode instructions generated by the CalcScript Compiler. It maintains its own state and allows you to inspect and manipulate its variables over the course of program execution.

§Usage

To run a program, you can easily create a Vm by compiling a program with Vm::compile_program, then calling Vm::run to execute it. It returns a Value that contains the return value of the program.

use cas_compute::numerical::value::Value;
use cas_parser::parser::Parser;
use cas_vm::Vm;

let source = "5sin(pi/2) * 6!";
let mut parser = Parser::new(source);
let stmts = parser.try_parse_full_many().unwrap();

let mut vm = Vm::compile_program(stmts).unwrap();

use cas_compute::primitive::float;
// 5sin(pi/2) * 6!
// = 5 * 1 * 720 = 3600
assert_eq!(vm.run().unwrap(), 3600.into());

It is also possible to programatically manipulate the Vm’s variables, although this will take some work. You’ll have to manually declare the variable in the compilation phase to obtain an index for it, and then use that index to set the variable in the Vm. Here’s an example of how to do that:

use cas_compiler::Compiler;
use cas_compiler::expr::compile_stmts;
use cas_parser::parser::ast::LitSym;
use cas_parser::parser::Parser;
use cas_vm::Vm;

let source = "x^2 + 5x + 6";
let mut parser = Parser::new(source);
let stmts = parser.try_parse_full_many().unwrap();

let mut compiler = Compiler::new();

// declare existence of `x` in the compiler (or a compilation error will occur)
// while also obtaining an index for `x` in the compiler
let x_id = compiler.add_symbol(&LitSym {
    name: String::from("x"),
    span: 0..0
}).unwrap();

// `x` must be initialized before we execute the vm (or a runtime error will occur)!

// helper function to compile the statements in place of `Compiler::compile_program`
compile_stmts(&stmts, &mut compiler).unwrap();

// create the virtual machine from the compiler and run test cases
let mut vm = Vm::from(compiler);

let cases = [
    // (x, expected)
    (2, 20),
    (5, 56),
    (9, 132),
    (14, 272),
    (35, 1406),
    (256, 66822),
];

for (x, expected) in cases.into_iter() {
    // set the value of `x` in the vm
    vm.variables.insert(x_id, x.into());

    // ensure `x^2 + 5x + 6` is equal to `expected`
    let result = vm.run().unwrap();
    assert_eq!(result, expected.into());
}

This process will likely be simplified in the future.

Modules§

error

Structs§

ReplVm
A virtual machine that can compile and execute bytecode instructions in a REPL-like environment by maintaining state.
Vm
A virtual machine that executes bytecode instructions generated by the compiler (see Compiler).