Runtime: add method dispatch for array/string/dict/number (.len, .push, .pop, .keys, .values, .has, .toInt) Stdlib: delete global len/push/pop/keys/values/has Tests/docs/examples: migrate to method style; add tests/test_builtin_methods_style.bob All tests pass Breaking: global len/push/pop/keys/values/has removed; use methods instead Parser/AST: add class/extends/extension/super, field initializers Runtime: shared methods with this injection; classParents/classTemplates; super resolution; ownerClass/currentClass; extension lookup order Builtins: method dispatch for array/string/dict/number (.len/.push/.pop/.keys/.values/.has/.toInt); remove global forms Tests/docs/examples: add/refresh for classes, inheritance, super, polymorphism; migrate to method style; all tests pass VS Code extension: update grammar/readme/snippets for new features
53 lines
1.8 KiB
Plaintext
53 lines
1.8 KiB
Plaintext
print("\n--- Test: Class Edge Cases ---");
|
|
|
|
// 1) 'this' inside extension should read/write fields
|
|
class E1 { var x = 1; }
|
|
extension E1 { func bump() { this.x = this.x + 1; return this.x; } }
|
|
var e1 = E1();
|
|
assert(e1.bump() == 2, "extension writes this");
|
|
assert(e1.x == 2, "field reflects extension write");
|
|
|
|
// 2) Property overshadowing method: user property wins
|
|
class ShM { func m() { return 10; } }
|
|
var shm = ShM();
|
|
shm.m = 7;
|
|
assert(shm.m == 7, "property overshadows method value lookup");
|
|
|
|
// 3) Field name same as method; property has precedence
|
|
class FvM { var id = 1; func id() { return 99; } }
|
|
var fvm = FvM();
|
|
assert(fvm.id == 1, "property shadows method with same name");
|
|
// Replace with property; still property
|
|
fvm.id = 5;
|
|
assert(fvm.id == 5, "property remains in precedence after reassignment");
|
|
|
|
// 4) Late extension overrides previous extension
|
|
class Redef { }
|
|
extension Redef { func v() { return 1; } }
|
|
assert(Redef().v() == 1, "initial ext");
|
|
extension Redef { func v() { return 2; } }
|
|
assert(Redef().v() == 2, "redefined ext");
|
|
|
|
// 5) Super in multi-level extension chain already covered; add deeper chain guard
|
|
class S0 {}
|
|
class S1 extends S0 {}
|
|
class S2 extends S1 {}
|
|
class S3 extends S2 {}
|
|
extension S0 { func v() { return 1; } }
|
|
extension S1 { func v() { return super.v() + 1; } }
|
|
extension S2 { func v() { return super.v() + 1; } }
|
|
extension S3 { func v() { return super.v() + 1; } }
|
|
assert(S3().v() == 4, "deep super chain");
|
|
|
|
// 6) Built-in type extension coexists with class extension precedence
|
|
class N1 {}
|
|
extension number { func plus1() { return this + 1; } }
|
|
extension N1 { func plus1() { return 100; } }
|
|
var n1 = N1();
|
|
assert(5.plus1() == 6, "builtin number ext works");
|
|
assert(n1.plus1() == 100, "class ext wins over any/builtin");
|
|
|
|
print("Class edge cases: PASS");
|
|
|
|
|