feat: add instance field support with lexer, compiler, and GC tracing
Add TOKEN_FIELD token type and '_' prefix handling in lexer to distinguish field identifiers from regular names. Extend Compiler struct with fields symbol table pointer for tracking enclosing class fields. Implement field() parse function and CODE_LOAD_FIELD/CODE_STORE_FIELD bytecodes in VM. Modify ObjClass to store numFields count and ObjInstance to use flexible array member for field storage. Update GC markInstance to trace all instance fields. Add newClass signature to accept numFields parameter. Include test cases for field default null, multiple fields, object references with GC, and use-before-set ordering.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
class Foo {
|
||||
write { io.write(_field) }
|
||||
}
|
||||
|
||||
Foo.new.write // expect: null
|
||||
@@ -0,0 +1,29 @@
|
||||
class Foo {
|
||||
set(a, b, c, d, e) {
|
||||
_a = a
|
||||
_b = b
|
||||
_c = c
|
||||
_d = d
|
||||
_e = e
|
||||
}
|
||||
write {
|
||||
io.write(_a)
|
||||
io.write(_b)
|
||||
io.write(_c)
|
||||
io.write(_d)
|
||||
io.write(_e)
|
||||
}
|
||||
}
|
||||
|
||||
var foo = Foo.new
|
||||
foo.set(1, 2, 3, 4, 5)
|
||||
foo.write
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
// expect: 4
|
||||
// expect: 5
|
||||
|
||||
// TODO(bob): Inherited fields.
|
||||
// TODO(bob): Trying to get or set a field outside of a class.
|
||||
// TODO(bob): Fields in nested classes.
|
||||
@@ -0,0 +1,37 @@
|
||||
// This test exists mainly to make sure the GC traces instance fields.
|
||||
class Node {
|
||||
set(left, value, right) {
|
||||
_left = left
|
||||
_value = value
|
||||
_right = right
|
||||
}
|
||||
|
||||
write {
|
||||
if (_left is Node) {
|
||||
_left.write
|
||||
}
|
||||
|
||||
io.write(_value)
|
||||
|
||||
if (_right is Node) {
|
||||
_right.write
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var a = Node.new
|
||||
a.set(null, "a", null)
|
||||
var b = Node.new
|
||||
b.set(null, "b", null)
|
||||
var c = Node.new
|
||||
c.set(a, "c", b)
|
||||
a = null
|
||||
b = null
|
||||
var d = Node.new
|
||||
d.set(c, "d", null)
|
||||
c = null
|
||||
d.write
|
||||
// expect: a
|
||||
// expect: c
|
||||
// expect: b
|
||||
// expect: d
|
||||
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
write { io.write(_field) } // Compile a use of the field...
|
||||
init { _field = "value" } // ...before an assignment to it.
|
||||
}
|
||||
|
||||
var foo = Foo.new
|
||||
// But invoke them in the right order.
|
||||
foo.init
|
||||
foo.write // expect: value
|
||||
@@ -0,0 +1 @@
|
||||
var _field = "value" // expect error
|
||||
Reference in New Issue
Block a user