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..3adea37 100644 --- a/evaluator/property.go +++ b/evaluator/property.go @@ -59,6 +59,18 @@ func evaluateInstanceProperty(left object.Object, node *ast.Property) object.Obj return val } + 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)