Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ target
CLAUDE.md
.agents/skills/agents-update
.claude/skills/agents-update

# docs site
node_modules
.pnpm-store
14 changes: 14 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug vihaco demo",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/target/debug/examples/demo",
"cwd": "${workspaceFolder}",
"preLaunchTask": "build demo",
"sourceLanguages": ["rust"]
}
]
}
11 changes: 11 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build demo",
"type": "shell",
"command": "cargo build --package vihaco-demos --example demo",
"problemMatcher": ["$rustc"]
}
]
}
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"crates/vihaco-runtime-derive",
"crates/vihaco-stdlib",
"crates/vihaco-syntax",
"demos",
]

[workspace.package]
Expand Down
69 changes: 29 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,37 @@ machine.

vihaco is a framework for building small virtual machines. You define

- the **instruction set** — an enum, with `#[derive(Instruction)]`;
- the **components** that execute it — with `#[component]`;
- the **effects** they emit; and
- (optionally) **SST source syntax** — with `#[derive(Parse)]`,
- reusable **components** and their instruction products with `component!`;
- one `Execute<I>` implementation per product, with typed messages and effects;
- **composite routes** with `composite!`;
- executable composite **surface syntax and program loading** with the parser
derives; and
- (optionally) standalone **SST source syntax** with the parser derives,

all as ordinary Rust, then compose them into a machine. A component is one
`execute(instruction, message) -> effects`:
all as ordinary Rust. A component step is
`execute(&instruction, message) -> StepResult<effect>`:

```rust
use eyre::Result;
use vihaco::{Effects, Instruction, Message, component};
use vihaco::{component, Effects, Execute, Execution, StepResult};

// Bytecode-visible operations: each variant is an opcode, tuple fields its payload.
#[derive(Debug, Clone, Instruction)]
pub enum CounterInst {
Add(i64),
Print,
component! {
component Counter { value: i64, }
runtime {
instruction { Add(i64), Read, }
}
}

// Runtime-supplied input, not encoded in the instruction stream.
#[derive(Debug, Clone, Message)]
pub struct Prefix(pub String);

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

#[derive(Debug, Default)]
pub struct Counter {
value: i64,
}
// `component!` generates the component and these instruction structs.
// A containing `composite!` owns the machine-local instruction sum.

#[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)))),
}
impl Execute<counter::runtime::instruction::Add> for counter::Counter {
type Message = ();
type Effect = ();
type Fault = eyre::Report;
fn execute(&mut self, instruction: &counter::runtime::instruction::Add, _: ()) -> Result<StepResult<()>> {
self.value += instruction.0;
Ok(StepResult { effects: Effects::none(), execution: Execution::Complete })
}
}
```
Expand All @@ -65,16 +54,16 @@ needs; there is no umbrella crate.

| Crate | Role |
|---|---|
| [`vihaco`](crates/vihaco) | The batteries-included facade: re-exports every crate below at stable paths (`Instruction` / `Message` / `Effects`, the `#[component]` / `#[observe]` / `#[composite]` macros, the module / syntax / runtime layers, the `Value` / `Type` model), so most projects depend only on this crate. |
| [`vihaco`](crates/vihaco) | The batteries-included facade: re-exports the instruction, message, effects, execution, component, and composite APIs, plus the module / syntax / runtime layers and `Value` / `Type` model. |
| [`vihaco-abi`](crates/vihaco-abi) | The ISA vocabulary: the `Instruction` / `Effects` types, the `Value` / `Type` model, and the encoding + host-VM traits. |
| [`vihaco-abi-derive`](crates/vihaco-abi-derive) | `#[derive(Instruction)]`, re-exported through `vihaco-abi`'s `derive` feature. |
| [`vihaco-bytecode`](crates/vihaco-bytecode) | The binary / SST container format: headers, sections, and instruction (de)coding. |
| [`vihaco-module`](crates/vihaco-module) | The loadable `Module` model, program loader, host-VM traits, and assembly-style `Display`. |
| [`vihaco-runtime`](crates/vihaco-runtime) | The component/machine runtime: `GeneratedComponent`, effect sinks, and observation machinery. |
| [`vihaco-runtime-derive`](crates/vihaco-runtime-derive) | `#[derive(Message)]`, `#[component]`, `#[composite]`, `#[observe]`, re-exported through `vihaco-runtime`'s `derive` feature. |
| [`vihaco-runtime`](crates/vihaco-runtime) | The component/machine runtime: `Execute<I>`, `StepResult`, `Execution`, `Supply`, `Absorb`, `Observe`, `Handle`, and effect machinery. |
| [`vihaco-runtime-derive`](crates/vihaco-runtime-derive) | The `component!` and `composite!` declaration macros, re-exported through `vihaco` and `vihaco-runtime`'s `derive` feature. |
| [`vihaco-stdlib`](crates/vihaco-stdlib) | Standard-library components and observers, including `StdoutObserver`. |
| [`vihaco-syntax`](crates/vihaco-syntax) | Typed SST parsing and module construction (`Resolve`). |
| [`vihaco-cpu`](crates/vihaco-cpu) | A ready-made CPU/host component — a small stack machine (constants, arithmetic, branches, halt, …) with a `StepOutcome` control-flow effect. Use directly, or as a reference for writing your own. |
| [`vihaco-cpu`](crates/vihaco-cpu) | A ready-made CPU/host component — a small stack machine (constants, arithmetic, branches, halt, …). Use directly, or as a reference for writing your own. |
| [`vihaco-parser`](crates/vihaco-parser) | The `Parse<'src>` and `SurfaceInstruction` traits plus lexical, primitive, and collection implementations shared by the parser derive. |
| [`vihaco-parser-derive`](crates/vihaco-parser-derive) | `#[derive(Parse)]` — turns instruction, value, and type enums or structs into [chumsky](https://github.com/zesterer/chumsky) parsers via `#[syntax_class]` and `#[pattern]`. |

Expand Down Expand Up @@ -109,8 +98,8 @@ No mise? A stable Rust 2024 toolchain is enough — `cargo test --workspace

Guides and the API reference are published to GitHub Pages:
**<https://queracomputing.github.io/vihaco/>**. The guides walk through defining
instructions, pattern parser integration, messages, components, observers, and
composites.
instructions, pattern parser integration, typed module resolution, messages,
components, observers, composites, and composite-owned program loading.

Every code block in the guides and on the site is compiled — and, where
runnable, executed — in CI (via the `vihaco-doctests` crate), so the examples
Expand Down
Loading
Loading