# Owa A small experimental virtual machine and interpreter for an interpreted language, written in Zig. Owa provides a minimal bytecode format, a stack-based VM, and an object model with prototype inheritance and "magic" hooks. It is designed as a playground for building a compact interpreter, adding opcodes, and experimenting with native/built-in functions. ## Features - **Stack-based VM**: executes a custom bytecode (`OwaInstruction`). - **Interpreter/threads**: `OwaInterpreter` manages `OwaThread` instances that run frames and bytecode. - **Frames and locals**: each call executes in an `OwaFrame` with its own instruction pointer and locals map. - **Object model**: `OwaObject` supports attributes, prototype chain, and a callable function slot. - **Magic hooks**: predefined magic names (`__call`, `__str`, etc.) enable dynamic behavior. - **Builtins module**: includes basic objects such as `OWA_NULL` and a native `print` function. ## Getting Started ### Prerequisites - Zig (0.12+ recommended) ### Build and Run ```bash zig build zig build run ``` This builds the `Owa` executable and runs the demo program from `src/main.zig`. ## How It Works ### Bytecode and Instructions Instructions are defined in `src/vm/instruction.zig` as a tagged union `OwaInstruction` with an underlying `enum(u8)` opcode. Examples include `Nop`, `LoadConst`, `Call`, `Return`, and simple stack/rotation ops. Programs are encoded to bytes and then decoded during execution. ```zig const encoded = try OwaInstruction.encode_program(&.{ OwaInstruction{ .LoadConst = 0 }, // push builtins.print OwaInstruction{ .LoadConst = 1 }, // push OWA_NULL OwaInstruction{ .Call = 1 }, // call print with 1 arg OwaInstruction{ .Return = {} }, }, allocator); ``` ### Interpreter and Threads - `OwaInterpreter` initializes memory, holds thread and module lists, and can `spawn()` new `OwaThread`s. - `OwaThread` manages a value stack and a current `OwaFrame`; it repeatedly decodes bytecode and dispatches instructions. - `OwaFrame` tracks the function being executed, the instruction pointer (`ip`), a link to the previous frame, and a locals map. ### Object Model `OwaObject` holds: - `attrs`: attribute map (`StringHashMapUnmanaged`) - `prototype`: optional prototype link - `call_fn`: optional function (either bytecode-backed or native) The VM resolves attribute access via `getAttr` and prototype chaining. Callability is resolved through `call_fn` or the `__call` magic attribute. ### Builtins The `modules/builtins` module defines core objects and natives: - `OWA_NULL`: the null value - `print`: a native function printing its arguments ## Example `src/main.zig` demonstrates creating an interpreter and running a tiny program that calls the builtin `print` with `OWA_NULL`: ```zig const std = @import("std"); const owa = @import("Owa"); const modules = @import("modules"); pub fn main() !void { const allocator = std.heap.page_allocator; var interpreter = try owa.OwaInterpreter.init(allocator); var thread1 = try interpreter.spawn(); var func = owa.OwaFunction{ .owa = .{ .code = try owa.OwaInstruction.encode_program(&.{ owa.OwaInstruction{ .LoadConst = 0 }, // builtins.print owa.OwaInstruction{ .LoadConst = 1 }, // OWA_NULL owa.OwaInstruction{ .Call = 1 }, owa.OwaInstruction{ .Return = {} }, }, allocator), .var_const = &.{ &modules.builtins.print, &modules.builtins.OWA_NULL, }, }, }; try thread1.execute(&func); interpreter.deinit(); } ``` ## Project Structure - `src/mod.zig`: re-exports core VM types (instructions, objects, interpreter, etc.). - `src/main.zig`: demo entry point. - `src/vm/instruction.zig`: opcodes and encode/decode utilities. - `src/core/object.zig`: object model and attribute logic. - `src/core/function.zig`: function union (bytecode vs native) and flags. - `src/core/frame.zig`: call frame and locals. - `src/core/thread.zig`: thread state, dispatch loop, and call mechanics. - `src/core/interpreter.zig`: interpreter lifecycle and thread management. - `src/core/magic.zig`: magic names like `__call`, `__str`, etc. - `src/modules/builtins/`: built-in objects and native functions. - `build.zig`: Zig build configuration (modules, executable, run step). ## Roadmap - More opcodes (arithmetic, control flow, comparisons, etc.). - Exception handling and error objects. - Strings, numbers, and collections as first-class runtime objects. - Module system and loader. - Basic standard library. ## License See `LICENSE` for details.