vihaco / virtual ISA & machine framework

QuEra Computing · Rust · v0.1

vihaco

Rust 2024 License MIT Source github.com/QuEraComputing/vihaco
counter.rs
use eyre::Result;
use vihaco::{Effects, Instruction, Message, component};

/// Bytecode-visible operations. Each variant becomes an opcode; tuple
/// fields become the payload bytes that follow it.
#[derive(Debug, Clone, Instruction)]
pub enum CounterInst {
    Add(i64),
    Print,
}

/// Resolved execution input — supplied by the runtime, not encoded in
/// the instruction stream.
#[derive(Debug, Clone, Message)]
pub struct Prefix(pub String);

/// A value the component returns for the runtime or observers to consume.
#[derive(Debug, Clone, PartialEq)]
pub struct Line(pub String);

#[derive(Debug, Default)]
pub struct Counter {
    value: i64,
}

// One `execute` per component: (instruction, message) in, effects out.
#[component(instruction = CounterInst, message = Prefix, effect = Line)]
impl Counter {
    fn execute(&mut self, inst: CounterInst, msg: Prefix) -> Result<Effects<Line>> {
        match inst {
            CounterInst::Add(v) => {
                self.value += v;
                Ok(Effects::none())
            }
            CounterInst::Print => Ok(Effects::one(Line(format!("{}{}", msg.0, self.value)))),
        }
    }
}

A component is an execution unit: it takes a typed instruction plus a resolved message and returns typed effects. The derives handle opcodes, encoding, and the runtime glue.

i. Instruction sets

Bytecode as Rust enums

#[derive(Instruction)] turns an enum into an opcode set with inferred (or fixed) encoding width. Nest enums to compose several component instruction families under one machine type.

ii. Components & effects

Execute, then observe

Components consume a resolved Message and return typed Effects. Observers react to those effects with #[observe], keeping execution and delivery cleanly separated.

iii. Parsers for free

From source text to module

#[derive(Parse)] generates a chumsky parser for your instruction syntax; a two-pass resolver expands sugar, interns strings, and resolves labels into a runtime module.

§Install

vihaco is a Cargo workspace of focused crates. vihaco is the foundation — add the others as your project needs them. There is no umbrella crate and no published release yet, so depend on the git repo:

[dependencies]
vihaco        = { git = "https://github.com/QuEraComputing/vihaco" }
vihaco-cpu    = { git = "https://github.com/QuEraComputing/vihaco" }  # optional: a ready-made CPU component
vihaco-parser = { git = "https://github.com/QuEraComputing/vihaco" }  # optional: #[derive(Parse)] for source text

Requires Rust edition 2024.

Continue to the Quick Start →

Continue to the Quick Start, work through the Guides, or browse the API Reference.