Skip to content

Architecture Overview

A Devlish program begins as readable source and runs as a sequence of compiled instructions. The compiler translates the source into bytecode, and the virtual machine (VM) executes that bytecode. The host application supplies external operations such as file reads or model calls.

This section explains that division of responsibility for developers who want to inspect, embed, or contribute to the runtime. You do not need these implementation details to author a first program. Begin with Getting Started for the user-facing workflow.

Compilation gives a reviewed source version an inspectable executable representation. Keeping the VM separate from its host allows native and browser applications to use the same instructions while offering different external capabilities. Repeatable computation depends on the program and its inputs; reproducing external interactions also requires the captured responses described in Audit and Replay.

Read Compiler for translation and source maps, Virtual Machine for execution and effects, and WASM Target for browser embedding.

.dvl source -> Parser -> AST -> Compiler -> Bytecode (.dvlc.json) -> VM

Each stage is independent and inspectable:

  1. Source: Human-readable English-like syntax
  2. Parser: Converts source lines into typed statements
  3. Compiler: Emits bytecode instructions with a constant pool and source map
  4. VM: Executes bytecode with host-provided effects
Terminal window
# Validate source syntax
devlish validate program.dvl
# Compile to bytecode
devlish compile program.dvl --output program.dvlc.json
# Inspect compiled bytecode
devlish disassemble program.dvlc.json
# Execute (from source or bytecode)
devlish run program.dvl --input '{"key": "value"}'
devlish run program.dvlc.json --input '{"key": "value"}'

The source is organized into Rust crates. The following table introduces the main components:

Crate Purpose
devlish_core Parser, compiler, CLI binary. Converts .dvl to bytecode JSON.
devlish_vm Bytecode VM. Executes instructions via the HostEffects trait.
devlish_wasm_runner WASM build of the VM for browser and Node embedding.
devlish_wasm_compiler WASM build of the compiler for in-browser compilation.
devlish_toolrun Command wrapper for token-saving output compression.
devlish_geocivic Domain-specific Energy Community verification tool.

The design goal is that compiled Devlish programs carry no runtime beyond the VM:

  • No Ruby, Python, or Node required to execute
  • The WASM VM runs in any WebAssembly host
  • The native compiler and VM are installed as one application
  • Bytecode packages are self-contained JSON artifacts

A compiled .dvlc.json file contains:

{
"format": "devlish-bytecode",
"format_version": 0,
"compiler_version": "0.1.0",
"constant_pool": [1000000, "approved", true],
"instructions": [
{"op": "CONST", "dest": "r0", "const": 0},
{"op": "STORE", "name": "threshold", "src": "r0"}
],
"source_map": [
{"line": 1, "source": "threshold equals 1000000"}
],
"manifest": null
}

The same bytecode runs in three contexts:

  • Native CLI: devlish run with full host effects (files, HTTP, services)
  • WASM sandbox: devlish-runtime npm package with restricted effects
  • MCP server: devlish mcp serving tools to LLM clients

When a program uses Import, the compiler searches:

  1. The directory containing the source file
  2. The project root (where devlish.toml lives)
  3. devlish/ and lib/ under the project root
  4. Paths in the DEVLISH_PATH environment variable
  5. ~/.devlish/lib/ standard library path

Imports are resolved and inlined at compile time. The resulting bytecode is self-contained.