From 3f4dcd7a63d9a39d97d99aff260c50e29ac60067 Mon Sep 17 00:00:00 2001 From: "Shea Lewis (Kai)" <355659+kaidesu@users.noreply.github.com> Date: Mon, 12 Jan 2026 23:47:36 -0800 Subject: [PATCH 1/2] add superclass chain traversal --- evaluator/evaluator_test.go | 65 +++++++++++++++++++++++++++++++++++++ evaluator/property.go | 11 +++++++ 2 files changed, 76 insertions(+) diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index e9c905a..e1a1824 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -307,6 +307,71 @@ func TestTraitMethodLookup(t *testing.T) { } } +func TestInheritedProperties(t *testing.T) { + tests := []struct { + name string + input string + expected int64 + }{ + { + name: "access parent class property", + input: ` + class Animal { + species = 42 + } + + class Dog extends Animal { + } + + d = Dog.new() + d.species + `, + expected: 42, + }, + { + name: "access grandparent class property", + input: ` + class Animal { + legs = 4 + } + + class Mammal extends Animal { + } + + class Dog extends Mammal { + } + + d = Dog.new() + d.legs + `, + expected: 4, + }, + { + name: "child property overrides parent", + input: ` + class Animal { + sound = 1 + } + + class Dog extends Animal { + sound = 2 + } + + d = Dog.new() + d.sound + `, + expected: 2, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := evaluate(tt.input) + isNumberObject(t, result, tt.expected) + }) + } +} + // ============================================================================= // Helper functions diff --git a/evaluator/property.go b/evaluator/property.go index 0bb7566..a1c8aed 100644 --- a/evaluator/property.go +++ b/evaluator/property.go @@ -59,6 +59,17 @@ func evaluateInstanceProperty(left object.Object, node *ast.Property) object.Obj return val } + // Check superclass chain + class := instance.Class.Super + for class != nil { + if class.Environment.Has(property.Value) { + val, _ = class.Environment.Get(property.Value) + + return val + } + class = class.Super + } + for _, trait := range instance.Class.Traits { if trait.Environment.Has(property.Value) { val, _ = trait.Environment.Get(property.Value) From 20c3418105850cba8ba10e80892f011b4c8bfb77 Mon Sep 17 00:00:00 2001 From: "Shea Lewis (Kai)" <355659+kaidesu@users.noreply.github.com> Date: Mon, 12 Jan 2026 23:49:52 -0800 Subject: [PATCH 2/2] whitespace --- evaluator/property.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/evaluator/property.go b/evaluator/property.go index a1c8aed..3adea37 100644 --- a/evaluator/property.go +++ b/evaluator/property.go @@ -59,14 +59,15 @@ func evaluateInstanceProperty(left object.Object, node *ast.Property) object.Obj return val } - // Check superclass chain class := instance.Class.Super + for class != nil { if class.Environment.Has(property.Value) { val, _ = class.Environment.Get(property.Value) return val } + class = class.Super }