initial commit
This commit is contained in:
commit
4a08b87af4
20 changed files with 967 additions and 0 deletions
127
README.md
Normal file
127
README.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue