mirror of
https://github.com/bearlanguageorg/bear.git
synced 2026-08-26 16:07:01 +00:00
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:
@@ -0,0 +1,211 @@
|
||||
// gc.v — mark-and-sweep garbage collector for the VuurRaaf VM.
|
||||
//
|
||||
// The collector runs between opcodes (never mid-instruction, so no live value
|
||||
// is ever hidden in a temporary). Roots are the value stack, which also holds
|
||||
// every frame's locals (they live at bp+idx). Arrays and structs are traced
|
||||
// transitively. The sweep compacts each pool and remaps surviving handles.
|
||||
//
|
||||
// String constants baked into the bytecode (op_push_s operands) live in
|
||||
// strings[0..const_strs] and are never collected; only runtime-allocated
|
||||
// strings participate in the cycle.
|
||||
module vm
|
||||
|
||||
const gc_alloc_trigger = 4096
|
||||
|
||||
// collect marks all heap values reachable from the stack, then sweeps and
|
||||
// compacts the pools, remapping handles on the stack and inside live
|
||||
// containers.
|
||||
fn (mut v Vm) collect() {
|
||||
// ---- mark ----
|
||||
mut str_mark := []bool{len: v.strings.len}
|
||||
mut arr_mark := []bool{len: v.arrays.len}
|
||||
mut struct_mark := []bool{len: v.structs.len}
|
||||
mut float_mark := []bool{len: v.floats.len}
|
||||
mut closure_mark := []bool{len: v.closures.len}
|
||||
for i in 0..v.sp {
|
||||
v.mark_value(v.stack[i], mut str_mark, mut arr_mark, mut struct_mark, mut float_mark, mut closure_mark)
|
||||
}
|
||||
// ---- remap tables: old index -> new index (-1 = collected) ----
|
||||
mut str_new := []int{len: v.strings.len, init: -1}
|
||||
mut arr_new := []int{len: v.arrays.len, init: -1}
|
||||
mut struct_new := []int{len: v.structs.len, init: -1}
|
||||
mut float_new := []int{len: v.floats.len, init: -1}
|
||||
mut closure_new := []int{len: v.closures.len, init: -1}
|
||||
mut nstr := v.const_strs
|
||||
for i in v.const_strs..v.strings.len {
|
||||
if str_mark[i] {
|
||||
str_new[i] = nstr
|
||||
nstr++
|
||||
}
|
||||
}
|
||||
mut narr := 0
|
||||
for i in 0..v.arrays.len {
|
||||
if arr_mark[i] {
|
||||
arr_new[i] = narr
|
||||
narr++
|
||||
}
|
||||
}
|
||||
mut nstruct := 0
|
||||
for i in 0..v.structs.len {
|
||||
if struct_mark[i] {
|
||||
struct_new[i] = nstruct
|
||||
nstruct++
|
||||
}
|
||||
}
|
||||
mut nfloat := 0
|
||||
for i in 0..v.floats.len {
|
||||
if float_mark[i] {
|
||||
float_new[i] = nfloat
|
||||
nfloat++
|
||||
}
|
||||
}
|
||||
mut nclosure := 0
|
||||
for i in 0..v.closures.len {
|
||||
if closure_mark[i] {
|
||||
closure_new[i] = nclosure
|
||||
nclosure++
|
||||
}
|
||||
}
|
||||
// ---- rewrite live references ----
|
||||
for i in 0..v.sp {
|
||||
v.stack[i] = v.remap(v.stack[i], str_new, arr_new, struct_new, float_new, closure_new)
|
||||
}
|
||||
for h in 0..v.arrays.len {
|
||||
if arr_mark[h] {
|
||||
for j in 0..v.arrays[h].len {
|
||||
v.arrays[h][j] = v.remap(v.arrays[h][j], str_new, arr_new, struct_new, float_new, closure_new)
|
||||
}
|
||||
}
|
||||
}
|
||||
for h in 0..v.structs.len {
|
||||
if struct_mark[h] {
|
||||
for j in 0..v.structs[h].fields.len {
|
||||
v.structs[h].fields[j].val = v.remap(v.structs[h].fields[j].val, str_new, arr_new, struct_new, float_new, closure_new)
|
||||
}
|
||||
}
|
||||
}
|
||||
// ---- compact pools ----
|
||||
mut strings := v.strings[..v.const_strs]
|
||||
for i in v.const_strs..v.strings.len {
|
||||
if str_mark[i] {
|
||||
strings << v.strings[i]
|
||||
}
|
||||
}
|
||||
v.strings = strings
|
||||
mut arrays := [][]i64{}
|
||||
for i in 0..v.arrays.len {
|
||||
if arr_mark[i] {
|
||||
arrays << v.arrays[i]
|
||||
}
|
||||
}
|
||||
v.arrays = arrays
|
||||
mut structs := []StructVal{}
|
||||
for i in 0..v.structs.len {
|
||||
if struct_mark[i] {
|
||||
structs << v.structs[i]
|
||||
}
|
||||
}
|
||||
v.structs = structs
|
||||
mut floats := []f64{}
|
||||
for i in 0..v.floats.len {
|
||||
if float_mark[i] {
|
||||
floats << v.floats[i]
|
||||
}
|
||||
}
|
||||
v.floats = floats
|
||||
mut closures := []Closure{}
|
||||
for i in 0..v.closures.len {
|
||||
if closure_mark[i] {
|
||||
closures << v.closures[i]
|
||||
}
|
||||
}
|
||||
v.closures = closures
|
||||
}
|
||||
|
||||
// mark_value traces a value and everything it references using an explicit
|
||||
// worklist (arrays of arrays can nest deeply; recursion could overflow).
|
||||
fn (mut v Vm) mark_value(x i64, mut str_mark []bool, mut arr_mark []bool, mut struct_mark []bool, mut float_mark []bool, mut closure_mark []bool) {
|
||||
mut work := []i64{}
|
||||
work << x
|
||||
for work.len > 0 {
|
||||
val := work.pop()
|
||||
match v.tag(val) {
|
||||
tag_str {
|
||||
h := v.hand(val)
|
||||
if h >= v.const_strs && h < str_mark.len && !str_mark[h] {
|
||||
str_mark[h] = true
|
||||
}
|
||||
}
|
||||
tag_arr {
|
||||
h := v.hand(val)
|
||||
if h >= 0 && h < arr_mark.len && !arr_mark[h] {
|
||||
arr_mark[h] = true
|
||||
for el in v.arrays[h] {
|
||||
work << el
|
||||
}
|
||||
}
|
||||
}
|
||||
tag_struct {
|
||||
h := v.hand(val)
|
||||
if h >= 0 && h < struct_mark.len && !struct_mark[h] {
|
||||
struct_mark[h] = true
|
||||
for f in v.structs[h].fields {
|
||||
work << f.val
|
||||
}
|
||||
}
|
||||
}
|
||||
tag_float {
|
||||
h := v.hand(val)
|
||||
if h >= 0 && h < float_mark.len && !float_mark[h] {
|
||||
float_mark[h] = true
|
||||
}
|
||||
}
|
||||
tag_closure {
|
||||
h := v.hand(val)
|
||||
if h >= 0 && h < closure_mark.len && !closure_mark[h] {
|
||||
closure_mark[h] = true
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remap translates a handle to its post-compaction index, leaving integers
|
||||
// and uncollected values untouched.
|
||||
fn (mut v Vm) remap(x i64, str_new []int, arr_new []int, struct_new []int, float_new []int, closure_new []int) i64 {
|
||||
match v.tag(x) {
|
||||
tag_str {
|
||||
h := v.hand(x)
|
||||
if h >= v.const_strs && h < str_new.len && str_new[h] >= 0 {
|
||||
return v.mkstr(str_new[h])
|
||||
}
|
||||
}
|
||||
tag_arr {
|
||||
h := v.hand(x)
|
||||
if h >= 0 && h < arr_new.len && arr_new[h] >= 0 {
|
||||
return v.mkarr(arr_new[h])
|
||||
}
|
||||
}
|
||||
tag_struct {
|
||||
h := v.hand(x)
|
||||
if h >= 0 && h < struct_new.len && struct_new[h] >= 0 {
|
||||
return v.mkstruct_handle(struct_new[h])
|
||||
}
|
||||
}
|
||||
tag_float {
|
||||
h := v.hand(x)
|
||||
if h >= 0 && h < float_new.len && float_new[h] >= 0 {
|
||||
return v.mkfloat(float_new[h])
|
||||
}
|
||||
}
|
||||
tag_closure {
|
||||
h := v.hand(x)
|
||||
if h >= 0 && h < closure_new.len && closure_new[h] >= 0 {
|
||||
return v.mkclosure(closure_new[h])
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return x
|
||||
}
|
||||
Reference in New Issue
Block a user