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:
Bob Nystrom
2013-11-23 22:55:05 +00:00
parent f4982f7b21
commit f50453e24e
11 changed files with 229 additions and 19 deletions
+5
View File
@@ -0,0 +1,5 @@
class Foo {
write { io.write(_field) }
}
Foo.new.write // expect: null
+29
View File
@@ -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.
+37
View File
@@ -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
+9
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
var _field = "value" // expect error