Production pass: floats, GC, type checking, and tooling

Adds floats, bitwise ops, UTF-8 strings with methods, try/catch,
closures, generics validation, a compile-time type checker, a
mark-and-sweep GC, source-level debug info, constant folding, and
the repl/fmt/package-manager commands.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
allexanderbergmns
2026-08-25 14:29:15 +02:00
parent b0a4da7e2f
commit 9b22be48a5
27 changed files with 3638 additions and 166 deletions
+90 -16
View File
@@ -1,49 +1,101 @@
// value.v — tagged value encoding and helpers for the VuurRaaf VM.
//
// Stack values are 64-bit tagged integers with two tag bits:
// low bits 00 -> encoded number (value = raw << 2)
// low bits 01 -> string handle (handle = value >> 2, into v.strings)
// low bits 10 -> struct handle (handle = value >> 2, into v.structs)
// low bits 11 -> array handle (handle = value >> 2, into v.arrays)
// Stack values are 64-bit tagged integers with three tag bits:
// low bits 000 -> encoded integer (value = raw << 3)
// low bits 001 -> string handle (handle = value >> 3, into v.strings)
// low bits 010 -> struct handle (handle = value >> 3, into v.structs)
// low bits 011 -> array handle (handle = value >> 3, into v.arrays)
// low bits 100 -> float handle (handle = value >> 3, into v.floats)
module vm
fn (mut v Vm) is_str(x i64) bool {
return x & 3 == 1
const tag_mask = u64(7)
const tag_int = u64(0)
const tag_str = u64(1)
const tag_struct = u64(2)
const tag_arr = u64(3)
const tag_float = u64(4)
const tag_closure = u64(5)
fn (mut v Vm) tag(x i64) u64 {
return u64(x) & tag_mask
}
fn (mut v Vm) is_arr(x i64) bool {
return x & 3 == 3
fn (mut v Vm) is_int(x i64) bool {
return u64(x) & tag_mask == tag_int
}
fn (mut v Vm) is_str(x i64) bool {
return u64(x) & tag_mask == tag_str
}
fn (mut v Vm) is_struct(x i64) bool {
return x & 3 == 2
return u64(x) & tag_mask == tag_struct
}
fn (mut v Vm) is_arr(x i64) bool {
return u64(x) & tag_mask == tag_arr
}
fn (mut v Vm) is_float(x i64) bool {
return u64(x) & tag_mask == tag_float
}
fn (mut v Vm) is_closure(x i64) bool {
return u64(x) & tag_mask == tag_closure
}
// is_num reports whether x is an integer (tag 0). Floats are a distinct type.
fn (mut v Vm) is_num(x i64) bool {
return u64(x) & tag_mask == tag_int
}
fn (mut v Vm) enc_int(x i64) i64 {
return u64(x) << 2
return i64(u64(x) << 3)
}
fn (mut v Vm) dec_int(x i64) i64 {
return x >> 2
return x >> 3
}
fn (mut v Vm) hand(x i64) int {
return int(x >> 2)
return int(x >> 3)
}
fn (mut v Vm) mkstr(idx int) i64 {
return (u64(idx) << 2) | 1
return i64((u64(idx) << 3) | tag_str)
}
fn (mut v Vm) mkarr(idx int) i64 {
return (u64(idx) << 2) | 3
return i64((u64(idx) << 3) | tag_arr)
}
fn (mut v Vm) mkstruct_handle(idx int) i64 {
return (u64(idx) << 2) | 2
return i64((u64(idx) << 3) | tag_struct)
}
fn (mut v Vm) mkfloat(idx int) i64 {
return i64((u64(idx) << 3) | tag_float)
}
fn (mut v Vm) mkclosure(idx int) i64 {
return i64((u64(idx) << 3) | tag_closure)
}
// push_float interns a float into the pool and returns its tagged handle.
fn (mut v Vm) push_float(f f64) i64 {
v.floats << f
return v.mkfloat(v.floats.len - 1)
}
// fval returns the f64 value of a float handle.
fn (mut v Vm) fval(x i64) f64 {
return v.floats[v.hand(x)]
}
fn (mut v Vm) truthy(x i64) bool {
if v.is_float(x) {
return v.fval(x) != 0.0
}
return x != 0
}
@@ -61,3 +113,25 @@ fn (mut v Vm) valid_struct_handle(x i64) bool {
h := v.hand(x)
return h >= 0 && h < v.structs.len
}
fn (mut v Vm) valid_float_handle(x i64) bool {
h := v.hand(x)
return h >= 0 && h < v.floats.len
}
fn (mut v Vm) valid_closure_handle(x i64) bool {
h := v.hand(x)
return h >= 0 && h < v.closures.len
}
// valid_handle_for bounds-checks a handle against the pool matching its tag.
fn (mut v Vm) valid_handle_for(x i64) bool {
return match v.tag(x) {
tag_str { v.valid_handle(x) }
tag_struct { v.valid_struct_handle(x) }
tag_arr { v.valid_arr_handle(x) }
tag_float { v.valid_float_handle(x) }
tag_closure { v.valid_closure_handle(x) }
else { true }
}
}