A complete bytecode virtual machine for the Noxy programming language, written in Go. Official Website.
For a complete guide, consult the NOXY_LANGUAGE_SPEC.md.
Noxy VM is a bytecode compiler and virtual machine for the Noxy language created by EstΓͺvΓ£o Fonseca. This implementation compiles source code into bytecode and executes it on a stack-based VM, offering high performance.
- β Bytecode compiler
- β High-performance stack-based VM
- β
Primitive types:
int,float,string,bool,bytes - β Structs with typed fields (global and local scope)
- β
Dynamic arrays with
append,pop,contains - β
Maps (hashmaps) with literals
{key: value} - β Functions with recursion
- β
Reference system (
ref) - β F-strings with interpolation
- β Single and double quote support
- β Line tracking for debugging
- β SQLite database support (Thread-safe)
- β HTTP server support
- β First-class functions
- β Closures
- β Concurrency (noxy routines) docs/CONCURRENCY.md
- β Garbage collection
- β Built-in modules (io, net, http, sqlite)
- β Package manager (see docs/PACKAGE_MANAGER.md)
# Clone the repository
git clone https://github.com/estevaofon/noxy.git
cd noxy-vm
# Build
go build -o noxy ./cmd/noxy
# Or run directly
go run ./cmd/noxy/main.go file.nx# Run a Noxy program
./noxy program.nx
# Or with go run
go run ./cmd/noxy/main.go program.nx
# Start Interactive REPL
./noxyNoxy includes a powerful REPL (Read-Eval-Print Loop) for interactive coding. Just run noxy without arguments.
Noxy REPL v1.2.0
Type 'exit' to quit.
>>> let x: int = 10
>>> x + 5
15
>>> if true then
... print("Multiline support!")
... end
Multiline support!
func main()
let x: int = 10
let y: int = 20
print(f"Sum: {x + y}")
struct Person
name: string
age: int
end
let p: Person = Person("Ana", 25)
print(p.name)
// Dynamic arrays
let nums: int[] = []
append(nums, 1)
append(nums, 2)
print(f"Length: {length(nums)}")
// Maps
let scores: map[string, int] = {"Alice": 100, "Bob": 95}
print(f"Alice: {scores['Alice']}")
end
main()
Output:
Sum: 30
Ana
Length: 2
Alice: 100
How to run the interpreter tests:
# Run all unit tests (Lexer, Parser, Compiler, VM)
go test ./...
# Run integration tests (Noxy scripts)
go run cmd/noxy/main.go noxy_examples/run_all_tests_concurrent.nxnoxy-vm/
βββ cmd/noxy/main.go # Main CLI
βββ internal/
β βββ lexer/ # Tokenization
β βββ token/ # Token types
β βββ parser/ # Recursive descent parser β AST
β βββ ast/ # AST nodes
β βββ compiler/ # AST β Bytecode Compiler
β βββ chunk/ # Bytecode and operations
β βββ value/ # Value system (int, float, string, etc.)
β βββ vm/ # Stack-based virtual machine
flowchart TB
subgraph INPUT["π SOURCE"]
A[("program.nx")]
end
subgraph FRONTEND["π FRONTEND"]
direction TB
B["π€ <b>LEXER</b><br/><i>Tokenization</i><br/><code>let, func, if β Tokens</code>"]
C["π³ <b>PARSER</b><br/><i>Syntax Analysis</i><br/><code>Tokens β AST</code>"]
end
subgraph BACKEND["βοΈ BACKEND"]
direction TB
D["π¦ <b>COMPILER</b><br/><i>Code Generation</i><br/><code>AST β Bytecode</code>"]
E["πΎ <b>CHUNK</b><br/><i>Bytecode Storage</i><br/><code>OpCodes + Constants</code>"]
end
subgraph RUNTIME["π RUNTIME"]
direction TB
F["π₯οΈ <b>VIRTUAL MACHINE</b><br/><i>Stack-Based Execution</i><br/><code>Interpret Bytecode</code>"]
G["π <b>STDLIB</b><br/><i>Native Modules</i><br/><code>io, net, http, sqlite...</code>"]
end
subgraph OUTPUT["β¨ RESULT"]
H[("Execution<br/>Output")]
end
A ==> B
B ==> C
C ==> D
D ==> E
E ==> F
G <-.-> F
F ==> H
let x: int = 42
let pi: float = 3.14159
let name: string = "Noxy"
let active: bool = true
let data: bytes = b"hello"
let nums: int[] = []
append(nums, 10)
append(nums, 20)
print(length(nums)) // 2
print(pop(nums)) // 20
print(contains(nums, 10)) // true
let scores: map[string, int] = {"Alice": 100, "Bob": 95}
scores["Charlie"] = 88
print(has_key(scores, "Alice")) // true
print(scores["Alice"]) // 100
let b: bytes = b"hello"
print(b[0]) // 104 (ASCII 'h')
let from_str: bytes = to_bytes("text")
let from_int: bytes = to_bytes(65) // b"A"
| Function | Description |
|---|---|
print(expr) |
Prints value |
to_str(val) |
Converts to string |
length(arr) |
Length of array/string |
append(arr, val) |
Appends element to array |
pop(arr) |
Removes and returns last element |
contains(arr, val) |
Checks if value exists |
has_key(map, key) |
Checks if key exists in map |
to_bytes(val) |
Converts string/int/array to bytes |
zeros(n) |
Array of n zeros |
time_now() |
Current timestamp in ms |
The VM uses the following main opcodes:
| Opcode | Description |
|---|---|
OP_CONSTANT |
Loads constant |
OP_ADD/SUB/MUL/DIV |
Arithmetic operations |
OP_EQUAL/LESS/GREATER |
Comparisons |
OP_JUMP/JUMP_IF_FALSE |
Flow control |
OP_CALL/RETURN |
Function calls |
OP_ARRAY/OP_MAP |
Collection creation |
OP_GET_INDEX/SET_INDEX |
Index access |
The compiler generates bytecode that can be visualized:
== main ==
0000 1 OP_CONSTANT 0 '<fn main>'
0002 | OP_SET_GLOBAL 1 'main'
0004 | OP_POP
0005 | OP_GET_GLOBAL 2 'main'
0007 | OP_CALL 0
== main ==
0000 3 OP_CONSTANT 0 '10'
0002 | OP_CONSTANT 1 '20'
0004 5 OP_GET_LOCAL 1
...
The bytecode VM offers high performance, especially for:
- Intensive loops
- Recursive function calls
- Operations with large arrays
MIT License
Bytecode implementation of the Noxy language in Go.
