aboutsummaryrefslogtreecommitdiff
path: root/tests/i
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-17 06:58:13 +0000
committer_ov4 <ov4@ov4.org>2026-10-17 06:58:13 +0000
commitc372c08dc940db58f1da9cadeb64b4cb3c837704 (patch)
tree70636fd3a485eaf16fb7f442c294ac066c76e1a1 /tests/i
parent74b6d06711afd3efbbc47436f1491900994313f3 (diff)
fix(classes): preserve method-only heap objects and document NEW
Allocate at least one byte for method-only classes so their heap addresses remain usable through pointers. Complete constructor diagnostics, field-order and exception coverage, document construction and rebinding, and highlight NEW. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/i')
-rw-r--r--tests/i/class-heap-new/expected.txt9
-rw-r--r--tests/i/class-heap-new/notes.md4
-rw-r--r--tests/i/class-heap-new/program.cps65
3 files changed, 78 insertions, 0 deletions
diff --git a/tests/i/class-heap-new/expected.txt b/tests/i/class-heap-new/expected.txt
index 37e731a..27bf128 100644
--- a/tests/i/class-heap-new/expected.txt
+++ b/tests/i/class-heap-new/expected.txt
@@ -14,3 +14,12 @@ declare caught
new caught
loop:1
loop:1
+failed rebind:71,71
+nested heap:80,1
+first
+second
+outer
+first
+second
+outer
+method only:99
diff --git a/tests/i/class-heap-new/notes.md b/tests/i/class-heap-new/notes.md
index 3a6435c..a395599 100644
--- a/tests/i/class-heap-new/notes.md
+++ b/tests/i/class-heap-new/notes.md
@@ -3,3 +3,7 @@
Human review: pending. Expected output was independently traced by AI.
Project semantics extend guide section 10.2. Each Box constructor sets Value to 1. Rebinding A preserves the old stack object's 7 while the new object becomes 9. Ordinary A <- B copies 4 into the current heap object, leaving B and the old stack object independent. BYVAL copies 4, then independently rebinds and changes its local object to 20. BYREF NEW copies 1 into A's current object, observed through CurrentA. Replacing this likewise copies into that same object; explicit Reset calls the ordinary constructor method. Array-element, field, bare field alias and pointer-dereference NEW assignments preserve their destination addresses and copy 1. Named's argument is 42. Failing throws in both DECLARE and heap construction, reaching the surrounding catches. Loop DECLARE restores its original stack object and constructs it on every iteration, so the previous heap object's 99 is never printed.
+
+Fragile's failed constructor leaves Stable bound to its original object, whose Value remains 71 through both names. Heap construction of Holder constructs its Box field as 1 while the old Holder's field remains 80 through Field. Ordered prints first, second, outer for stack and heap construction, proving field declaration order before the enclosing constructor. PrivateFactory's unused Build method checks that same-class access permits private automatic and explicit construction.
+
+A method-only Marker class has no fields, but heap NEW must still provide a non-null object address so a pointer receiver can call Get and print 99.
diff --git a/tests/i/class-heap-new/program.cps b/tests/i/class-heap-new/program.cps
index 7b8363f..aff248a 100644
--- a/tests/i/class-heap-new/program.cps
+++ b/tests/i/class-heap-new/program.cps
@@ -98,3 +98,68 @@ FOR Index <- 1 TO 2
Local <- NEW Box
Local.Value <- 99
NEXT Index
+CLASS Fragile
+ Value : INTEGER
+ PROCEDURE NEW(Fail : BOOLEAN)
+ Value <- 70
+ IF Fail THEN
+ THROW
+ ENDIF
+ ENDPROCEDURE
+ENDCLASS
+TYPE FragilePointer = ^Fragile
+DECLARE Stable : Fragile(FALSE)
+DECLARE Original : FragilePointer
+Original <- ^Stable
+Stable.Value <- 71
+TRY
+ Stable <- NEW Fragile(TRUE)
+CATCH
+ OUTPUT "failed rebind:", Stable.Value, ",", Original^.Value
+ENDTRY
+H.Item.Value <- 80
+H <- NEW Holder()
+OUTPUT "nested heap:", Field^.Value, ",", H.Item.Value
+CLASS OrderedFirst
+ PROCEDURE NEW()
+ OUTPUT "first"
+ ENDPROCEDURE
+ENDCLASS
+CLASS OrderedSecond
+ PROCEDURE NEW()
+ OUTPUT "second"
+ ENDPROCEDURE
+ENDCLASS
+CLASS Ordered
+ First : OrderedFirst
+ Second : OrderedSecond
+ PROCEDURE NEW()
+ OUTPUT "outer"
+ ENDPROCEDURE
+ENDCLASS
+DECLARE Order : Ordered
+Order <- NEW Ordered
+CLASS PrivateFactory
+ Value : INTEGER
+ PRIVATE PROCEDURE NEW()
+ Value <- 1
+ ENDPROCEDURE
+ PROCEDURE Build()
+ DECLARE Local : PrivateFactory
+ Local <- NEW PrivateFactory
+ Local.NEW()
+ ENDPROCEDURE
+ENDCLASS
+CLASS Marker
+ PROCEDURE NEW()
+ ENDPROCEDURE
+ FUNCTION Get() RETURNS INTEGER
+ RETURN 99
+ ENDFUNCTION
+ENDCLASS
+TYPE MarkerPointer = ^Marker
+DECLARE M : Marker
+DECLARE MarkerAddress : MarkerPointer
+M <- NEW Marker
+MarkerAddress <- ^M
+OUTPUT "method only:", MarkerAddress^.Get()