aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitattributes2
-rw-r--r--tests/i/arrays/case.json3
-rw-r--r--tests/i/arrays/expected.txt1
-rw-r--r--tests/i/arrays/notes.md7
-rw-r--r--tests/i/arrays/program.cps12
-rw-r--r--tests/i/calls/case.json3
-rw-r--r--tests/i/calls/expected.txt2
-rw-r--r--tests/i/calls/notes.md7
-rw-r--r--tests/i/calls/program.cps31
-rw-r--r--tests/i/caught-errors/case.json3
-rw-r--r--tests/i/caught-errors/expected.txt10
-rw-r--r--tests/i/caught-errors/notes.md7
-rw-r--r--tests/i/caught-errors/program.cps31
-rw-r--r--tests/i/class-default-public/case.json3
-rw-r--r--tests/i/class-default-public/expected.txt1
-rw-r--r--tests/i/class-default-public/notes.md7
-rw-r--r--tests/i/class-default-public/program.cps6
-rw-r--r--tests/i/constant-scope/case.json3
-rw-r--r--tests/i/constant-scope/expected.txt2
-rw-r--r--tests/i/constant-scope/notes.md7
-rw-r--r--tests/i/constant-scope/program.cps9
-rw-r--r--tests/i/enum-range/case.json1
-rw-r--r--tests/i/enum-range/expected.txt3
-rw-r--r--tests/i/enum-range/notes.md5
-rw-r--r--tests/i/enum-range/program.cps9
-rw-r--r--tests/i/identifier-case/case.json3
-rw-r--r--tests/i/identifier-case/expected.txt1
-rw-r--r--tests/i/identifier-case/notes.md7
-rw-r--r--tests/i/identifier-case/program.cps3
-rw-r--r--tests/i/integer-boundaries/case.json3
-rw-r--r--tests/i/integer-boundaries/expected.txt7
-rw-r--r--tests/i/integer-boundaries/input.txt2
-rw-r--r--tests/i/integer-boundaries/notes.md7
-rw-r--r--tests/i/integer-boundaries/program.cps11
-rw-r--r--tests/i/loops/case.json3
-rw-r--r--tests/i/loops/expected.txt1
-rw-r--r--tests/i/loops/notes.md9
-rw-r--r--tests/i/loops/program.cps28
-rw-r--r--tests/i/real-observations/case.json3
-rw-r--r--tests/i/real-observations/expected.txt2
-rw-r--r--tests/i/real-observations/notes.md7
-rw-r--r--tests/i/real-observations/program.cps7
-rw-r--r--tests/i/scalars/case.json3
-rw-r--r--tests/i/scalars/expected.txt3
-rw-r--r--tests/i/scalars/notes.md7
-rw-r--r--tests/i/scalars/program.cps12
-rw-r--r--tests/i/selection/case.json3
-rw-r--r--tests/i/selection/expected.txt3
-rw-r--r--tests/i/selection/notes.md7
-rw-r--r--tests/i/selection/program.cps19
-rw-r--r--tests/i/signed-zero-division/case.json1
-rw-r--r--tests/i/signed-zero-division/expected.txt2
-rw-r--r--tests/i/signed-zero-division/notes.md5
-rw-r--r--tests/i/signed-zero-division/program.cps7
-rw-r--r--tests/i/standard-while/case.json1
-rw-r--r--tests/i/standard-while/expected.txt1
-rw-r--r--tests/i/standard-while/notes.md5
-rw-r--r--tests/i/standard-while/program.cps6
-rw-r--r--tests/i/stdin/case.json1
-rw-r--r--tests/i/stdin/expected.txt1
-rw-r--r--tests/i/stdin/input.txt4
-rw-r--r--tests/i/stdin/notes.md5
-rw-r--r--tests/i/stdin/program.cps9
-rw-r--r--tests/i/string-extensions/case.json3
-rw-r--r--tests/i/string-extensions/expected.txt5
-rw-r--r--tests/i/string-extensions/notes.md7
-rw-r--r--tests/i/string-extensions/program.cps5
-rw-r--r--tests/i/strings/case.json3
-rw-r--r--tests/i/strings/expected.txt5
-rw-r--r--tests/i/strings/notes.md7
-rw-r--r--tests/i/strings/program.cps9
-rw-r--r--tests/i/text-files/case.json3
-rw-r--r--tests/i/text-files/expected-files/result.txt3
-rw-r--r--tests/i/text-files/expected.txt7
-rw-r--r--tests/i/text-files/files/empty.txt0
-rw-r--r--tests/i/text-files/files/input.txt3
-rw-r--r--tests/i/text-files/files/result.txt1
-rw-r--r--tests/i/text-files/notes.md9
-rw-r--r--tests/i/text-files/program.cps26
-rw-r--r--tests/i/uncaught-error/case.json3
-rw-r--r--tests/i/uncaught-error/expected.txt2
-rw-r--r--tests/i/uncaught-error/notes.md7
-rw-r--r--tests/i/uncaught-error/program.cps4
-rw-r--r--tests/i/unwind-calls/case.json3
-rw-r--r--tests/i/unwind-calls/expected.txt2
-rw-r--r--tests/i/unwind-calls/notes.md7
-rw-r--r--tests/i/unwind-calls/program.cps21
-rw-r--r--tests/i/user-types/case.json3
-rw-r--r--tests/i/user-types/expected.txt2
-rw-r--r--tests/i/user-types/notes.md7
-rw-r--r--tests/i/user-types/program.cps28
91 files changed, 569 insertions, 0 deletions
diff --git a/tests/.gitattributes b/tests/.gitattributes
new file mode 100644
index 0000000..d0a302c
--- /dev/null
+++ b/tests/.gitattributes
@@ -0,0 +1,2 @@
+# Preserve the deliberate CRLF and missing final newline in this input fixture.
+i/text-files/files/input.txt -text whitespace=cr-at-eol
diff --git a/tests/i/arrays/case.json b/tests/i/arrays/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/arrays/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/arrays/expected.txt b/tests/i/arrays/expected.txt
new file mode 100644
index 0000000..23d674d
--- /dev/null
+++ b/tests/i/arrays/expected.txt
@@ -0,0 +1 @@
+-8:13:15
diff --git a/tests/i/arrays/notes.md b/tests/i/arrays/notes.md
new file mode 100644
index 0000000..fc937ad
--- /dev/null
+++ b/tests/i/arrays/notes.md
@@ -0,0 +1,7 @@
+# arrays
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 10-11, 20; explicit negative lower bounds are valid INTEGER bounds.
+
+Trace: Rows contain (-8,-7), (2,3), (12,13). Their sum is 15, including both lower and upper endpoints.
diff --git a/tests/i/arrays/program.cps b/tests/i/arrays/program.cps
new file mode 100644
index 0000000..08b50a8
--- /dev/null
+++ b/tests/i/arrays/program.cps
@@ -0,0 +1,12 @@
+DECLARE Grid : ARRAY[-1:1,2:3] OF INTEGER
+DECLARE Row : INTEGER
+DECLARE Col : INTEGER
+DECLARE Total : INTEGER
+Total <- 0
+FOR Row <- -1 TO 1
+ FOR Col <- 2 TO 3
+ Grid[Row,Col] <- Row * 10 + Col
+ Total <- Total + Grid[Row,Col]
+ NEXT Col
+NEXT Row
+OUTPUT Grid[-1,2], ":", Grid[1,3], ":", Total
diff --git a/tests/i/calls/case.json b/tests/i/calls/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/calls/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/calls/expected.txt b/tests/i/calls/expected.txt
new file mode 100644
index 0000000..da9ed87
--- /dev/null
+++ b/tests/i/calls/expected.txt
@@ -0,0 +1,2 @@
+2:4:3:120
+4:7
diff --git a/tests/i/calls/notes.md b/tests/i/calls/notes.md
new file mode 100644
index 0000000..170c4c8
--- /dev/null
+++ b/tests/i/calls/notes.md
@@ -0,0 +1,7 @@
+# calls
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 22-24; array parameter syntax follows the project manual.
+
+Trace: Sticky BYREF changes A and B, while C is copied. 5!=120. BYVAL array mutation is isolated; BYREF writes 4+3 into the second caller element.
diff --git a/tests/i/calls/program.cps b/tests/i/calls/program.cps
new file mode 100644
index 0000000..0900b5c
--- /dev/null
+++ b/tests/i/calls/program.cps
@@ -0,0 +1,31 @@
+PROCEDURE Change(BYREF A : INTEGER, B : INTEGER, BYVAL C : INTEGER)
+ A <- A + 1
+ B <- B + 2
+ C <- C + 100
+ENDPROCEDURE
+FUNCTION Factorial(N : INTEGER) RETURNS INTEGER
+ IF N <= 1 THEN
+ RETURN 1
+ ENDIF
+ RETURN N * Factorial(N - 1)
+ENDFUNCTION
+PROCEDURE LocalCopy(Values : ARRAY OF INTEGER)
+ Values[1] <- 99
+ENDPROCEDURE
+PROCEDURE Shared(BYREF Values : ARRAY[1:2] OF INTEGER)
+ Values[2] <- Values[1] + 3
+ENDPROCEDURE
+DECLARE A : INTEGER
+DECLARE B : INTEGER
+DECLARE C : INTEGER
+DECLARE Values : ARRAY[1:2] OF INTEGER
+A <- 1
+B <- 2
+C <- 3
+CALL Change(A, B, C)
+Values[1] <- 4
+Values[2] <- 5
+CALL LocalCopy(Values)
+CALL Shared(Values)
+OUTPUT A, ":", B, ":", C, ":", Factorial(5)
+OUTPUT Values[1], ":", Values[2]
diff --git a/tests/i/caught-errors/case.json b/tests/i/caught-errors/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/caught-errors/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/caught-errors/expected.txt b/tests/i/caught-errors/expected.txt
new file mode 100644
index 0000000..ae32ca6
--- /dev/null
+++ b/tests/i/caught-errors/expected.txt
@@ -0,0 +1,10 @@
+[Fatal] line 7: Division by zero
+division caught
+[Fatal] line 12: Array index out of bounds
+bounds caught
+[Fatal] line 17: Dereference of an unset pointer
+pointer caught
+[Fatal] line 22: File 'closed.txt' is not open
+file caught
+throw caught
+alive
diff --git a/tests/i/caught-errors/notes.md b/tests/i/caught-errors/notes.md
new file mode 100644
index 0000000..9535a55
--- /dev/null
+++ b/tests/i/caught-errors/notes.md
@@ -0,0 +1,7 @@
+# caught-errors
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: Project TRY and runtime-check contract; diagnostics precede catch execution on stdout.
+
+Trace: Each failed access transfers to its CATCH, so no attempted value is printed. Source lines 7,12,17,22 identify the operations. Bare THROW has no own diagnostic; execution reaches alive.
diff --git a/tests/i/caught-errors/program.cps b/tests/i/caught-errors/program.cps
new file mode 100644
index 0000000..919696b
--- /dev/null
+++ b/tests/i/caught-errors/program.cps
@@ -0,0 +1,31 @@
+DECLARE X : INTEGER
+DECLARE Values : ARRAY[1:1] OF INTEGER
+TYPE IntPtr = ^INTEGER
+DECLARE P : IntPtr
+X <- 0
+TRY
+ OUTPUT 4 DIV X
+CATCH
+ OUTPUT "division caught"
+ENDTRY
+TRY
+ OUTPUT Values[2]
+CATCH
+ OUTPUT "bounds caught"
+ENDTRY
+TRY
+ OUTPUT P^
+CATCH
+ OUTPUT "pointer caught"
+ENDTRY
+TRY
+ CLOSEFILE "closed.txt"
+CATCH
+ OUTPUT "file caught"
+ENDTRY
+TRY
+ THROW
+CATCH
+ OUTPUT "throw caught"
+ENDTRY
+OUTPUT "alive"
diff --git a/tests/i/class-default-public/case.json b/tests/i/class-default-public/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/class-default-public/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/class-default-public/expected.txt b/tests/i/class-default-public/expected.txt
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/tests/i/class-default-public/expected.txt
@@ -0,0 +1 @@
+7
diff --git a/tests/i/class-default-public/notes.md b/tests/i/class-default-public/notes.md
new file mode 100644
index 0000000..1f5c869
--- /dev/null
+++ b/tests/i/class-default-public/notes.md
@@ -0,0 +1,7 @@
+# class-default-public
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE p. 28: methods and properties are public unless otherwise stated. This conflicts with the current explicit-access requirement.
+
+Trace: Value has default public access. Assigning and reading it must yield 7. A compile rejection is a failure, not an accepted alternative.
diff --git a/tests/i/class-default-public/program.cps b/tests/i/class-default-public/program.cps
new file mode 100644
index 0000000..57f051f
--- /dev/null
+++ b/tests/i/class-default-public/program.cps
@@ -0,0 +1,6 @@
+CLASS Box
+ Value : INTEGER
+ENDCLASS
+DECLARE B : Box
+B.Value <- 7
+OUTPUT B.Value
diff --git a/tests/i/constant-scope/case.json b/tests/i/constant-scope/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/constant-scope/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/constant-scope/expected.txt b/tests/i/constant-scope/expected.txt
new file mode 100644
index 0000000..66962ed
--- /dev/null
+++ b/tests/i/constant-scope/expected.txt
@@ -0,0 +1,2 @@
+7
+3:3
diff --git a/tests/i/constant-scope/notes.md b/tests/i/constant-scope/notes.md
new file mode 100644
index 0000000..6d71b42
--- /dev/null
+++ b/tests/i/constant-scope/notes.md
@@ -0,0 +1,7 @@
+# constant-scope
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE p. 8 allows restricting a constant scope; project lexical binding and function inheritance rules.
+
+Trace: The inner constant shadows 3 only within the IF. The outer binding and the function both retain 3.
diff --git a/tests/i/constant-scope/program.cps b/tests/i/constant-scope/program.cps
new file mode 100644
index 0000000..cec8681
--- /dev/null
+++ b/tests/i/constant-scope/program.cps
@@ -0,0 +1,9 @@
+CONSTANT Limit = 3
+FUNCTION ReadLimit() RETURNS INTEGER
+ RETURN Limit
+ENDFUNCTION
+IF TRUE THEN
+ CONSTANT Limit = 7
+ OUTPUT Limit
+ENDIF
+OUTPUT Limit, ":", ReadLimit()
diff --git a/tests/i/enum-range/case.json b/tests/i/enum-range/case.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/i/enum-range/case.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/i/enum-range/expected.txt b/tests/i/enum-range/expected.txt
new file mode 100644
index 0000000..f91d556
--- /dev/null
+++ b/tests/i/enum-range/expected.txt
@@ -0,0 +1,3 @@
+[Fatal] line 5: Value out of range for enum Season
+enum caught
+TRUE
diff --git a/tests/i/enum-range/notes.md b/tests/i/enum-range/notes.md
new file mode 100644
index 0000000..e689441
--- /dev/null
+++ b/tests/i/enum-range/notes.md
@@ -0,0 +1,5 @@
+# enum-range
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis and trace: Project enum range and exception contract. Incrementing the last ordinal fails before assignment, leaving S=Summer.
diff --git a/tests/i/enum-range/program.cps b/tests/i/enum-range/program.cps
new file mode 100644
index 0000000..7c6d1ef
--- /dev/null
+++ b/tests/i/enum-range/program.cps
@@ -0,0 +1,9 @@
+TYPE Season = (Spring, Summer)
+DECLARE S : Season
+S <- Summer
+TRY
+ S <- S + 1
+CATCH
+ OUTPUT "enum caught"
+ENDTRY
+OUTPUT S = Summer
diff --git a/tests/i/identifier-case/case.json b/tests/i/identifier-case/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/identifier-case/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/identifier-case/expected.txt b/tests/i/identifier-case/expected.txt
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/tests/i/identifier-case/expected.txt
@@ -0,0 +1 @@
+7
diff --git a/tests/i/identifier-case/notes.md b/tests/i/identifier-case/notes.md
new file mode 100644
index 0000000..ac8c200
--- /dev/null
+++ b/tests/i/identifier-case/notes.md
@@ -0,0 +1,7 @@
+# identifier-case
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE p. 7: identifiers should be considered case insensitive. Current symbol lookup is case sensitive.
+
+Trace: Counter and counter denote the same declared variable; the read yields 7.
diff --git a/tests/i/identifier-case/program.cps b/tests/i/identifier-case/program.cps
new file mode 100644
index 0000000..e478abb
--- /dev/null
+++ b/tests/i/identifier-case/program.cps
@@ -0,0 +1,3 @@
+DECLARE Counter : INTEGER
+Counter <- 7
+OUTPUT counter
diff --git a/tests/i/integer-boundaries/case.json b/tests/i/integer-boundaries/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/integer-boundaries/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/integer-boundaries/expected.txt b/tests/i/integer-boundaries/expected.txt
new file mode 100644
index 0000000..5fd67df
--- /dev/null
+++ b/tests/i/integer-boundaries/expected.txt
@@ -0,0 +1,7 @@
+9223372036854775807
+-9223372036854775808
+9223372036854775806
+-9223372036854775807
+-1
+TRUE:TRUE:TRUE
+9223372036854775807:-9223372036854775808:0
diff --git a/tests/i/integer-boundaries/input.txt b/tests/i/integer-boundaries/input.txt
new file mode 100644
index 0000000..e34e602
--- /dev/null
+++ b/tests/i/integer-boundaries/input.txt
@@ -0,0 +1,2 @@
+9223372036854775807
+-9223372036854775808
diff --git a/tests/i/integer-boundaries/notes.md b/tests/i/integer-boundaries/notes.md
new file mode 100644
index 0000000..b89da97
--- /dev/null
+++ b/tests/i/integer-boundaries/notes.md
@@ -0,0 +1,7 @@
+# integer-boundaries
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: Project INTEGER=i64 contract; CIE pp. 7 and 15 do not specify bit width or overflow.
+
+Trace: Inputs are 2^63-1 and -2^63. Every operation stays in range; their sum is -1 and division by 1 preserves both values.
diff --git a/tests/i/integer-boundaries/program.cps b/tests/i/integer-boundaries/program.cps
new file mode 100644
index 0000000..c08b658
--- /dev/null
+++ b/tests/i/integer-boundaries/program.cps
@@ -0,0 +1,11 @@
+DECLARE Hi : INTEGER
+DECLARE Lo : INTEGER
+INPUT Hi
+INPUT Lo
+OUTPUT Hi
+OUTPUT Lo
+OUTPUT Hi - 1
+OUTPUT Lo + 1
+OUTPUT Hi + Lo
+OUTPUT Lo < 0, ":", Hi > 0, ":", Lo < Hi
+OUTPUT Hi DIV 1, ":", Lo DIV 1, ":", Lo MOD 1
diff --git a/tests/i/loops/case.json b/tests/i/loops/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/loops/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/loops/expected.txt b/tests/i/loops/expected.txt
new file mode 100644
index 0000000..4291516
--- /dev/null
+++ b/tests/i/loops/expected.txt
@@ -0,0 +1 @@
+18:3
diff --git a/tests/i/loops/notes.md b/tests/i/loops/notes.md
new file mode 100644
index 0000000..6979d92
--- /dev/null
+++ b/tests/i/loops/notes.md
@@ -0,0 +1,9 @@
+# loops
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 20-21.
+
+Trace: FOR contributions are 0, 2, and 3+1-1=3. WHILE contributes 0+1+2=3. REPEAT contributes 10 once, then counts to 3. Total=18.
+
+The project requires DO after WHILE; this fixture uses that spelling to exercise runtime semantics. The separate standard-while fixture tests the CIE spelling.
diff --git a/tests/i/loops/program.cps b/tests/i/loops/program.cps
new file mode 100644
index 0000000..a858e6c
--- /dev/null
+++ b/tests/i/loops/program.cps
@@ -0,0 +1,28 @@
+DECLARE I : INTEGER
+DECLARE Total : INTEGER
+Total <- 0
+FOR I <- 3 TO 1
+ Total <- Total + 1000
+NEXT I
+FOR I <- 2 TO 2
+ Total <- Total + I
+NEXT I
+FOR I <- 3 TO -1 STEP -2
+ Total <- Total + I
+NEXT I
+WHILE FALSE DO
+ Total <- Total + 1000
+ENDWHILE
+I <- 0
+WHILE I < 3 DO
+ Total <- Total + I
+ I <- I + 1
+ENDWHILE
+REPEAT
+ Total <- Total + 10
+UNTIL TRUE
+I <- 0
+REPEAT
+ I <- I + 1
+UNTIL I = 3
+OUTPUT Total, ":", I
diff --git a/tests/i/real-observations/case.json b/tests/i/real-observations/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/real-observations/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/real-observations/expected.txt b/tests/i/real-observations/expected.txt
new file mode 100644
index 0000000..4a71ded
--- /dev/null
+++ b/tests/i/real-observations/expected.txt
@@ -0,0 +1,2 @@
+TRUE:TRUE:TRUE
+TRUE:TRUE
diff --git a/tests/i/real-observations/notes.md b/tests/i/real-observations/notes.md
new file mode 100644
index 0000000..8600506
--- /dev/null
+++ b/tests/i/real-observations/notes.md
@@ -0,0 +1,7 @@
+# real-observations
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 7, 15-16, 23-24; project REAL is double.
+
+Trace: Division produces 2.5, not integer 2. All fractions here are exactly representable in binary. Doubling 2.5 is 5. Signed zeros compare equal. No REAL text is output.
diff --git a/tests/i/real-observations/program.cps b/tests/i/real-observations/program.cps
new file mode 100644
index 0000000..1df2d0f
--- /dev/null
+++ b/tests/i/real-observations/program.cps
@@ -0,0 +1,7 @@
+FUNCTION Scale(Value : REAL) RETURNS REAL
+ RETURN Value * 2.0
+ENDFUNCTION
+DECLARE R : REAL
+R <- 5 / 2
+OUTPUT R = 2.5, ":", R > 2.0, ":", Scale(R) = 5.0
+OUTPUT (0.5 + 0.25) = 0.75, ":", (-0.0 = 0.0)
diff --git a/tests/i/scalars/case.json b/tests/i/scalars/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/scalars/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/scalars/expected.txt b/tests/i/scalars/expected.txt
new file mode 100644
index 0000000..8ac812e
--- /dev/null
+++ b/tests/i/scalars/expected.txt
@@ -0,0 +1,3 @@
+ready:Q:19:TRUE
+5:3
+TRUE:TRUE:TRUE:TRUE:TRUE
diff --git a/tests/i/scalars/notes.md b/tests/i/scalars/notes.md
new file mode 100644
index 0000000..4c9bc60
--- /dev/null
+++ b/tests/i/scalars/notes.md
@@ -0,0 +1,7 @@
+# scalars
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 7-9, 15-16; final OUTPUT newline follows the project convention.
+
+Trace: 3*4=12, X=19. 15 DIV 3=5 and 15 MOD 4=3. All five relations are true.
diff --git a/tests/i/scalars/program.cps b/tests/i/scalars/program.cps
new file mode 100644
index 0000000..19a7304
--- /dev/null
+++ b/tests/i/scalars/program.cps
@@ -0,0 +1,12 @@
+CONSTANT Rate = 7
+DECLARE X : INTEGER
+DECLARE Flag : BOOLEAN
+DECLARE Letter : CHAR
+DECLARE Text : STRING
+X <- Rate + 3 * 4
+Flag <- (X = 19) AND NOT FALSE
+Letter <- 'Q'
+Text <- "ready"
+OUTPUT Text, ":", Letter, ":", X, ":", Flag
+OUTPUT (X - 4) DIV 3, ":", (X - 4) MOD 4
+OUTPUT 2 < 3, ":", 2 <= 2, ":", 3 > 2, ":", 3 >= 3, ":", 2 <> 3
diff --git a/tests/i/selection/case.json b/tests/i/selection/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/selection/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/selection/expected.txt b/tests/i/selection/expected.txt
new file mode 100644
index 0000000..e3ef2af
--- /dev/null
+++ b/tests/i/selection/expected.txt
@@ -0,0 +1,3 @@
+nested
+first
+otherwise
diff --git a/tests/i/selection/notes.md b/tests/i/selection/notes.md
new file mode 100644
index 0000000..7e605e1
--- /dev/null
+++ b/tests/i/selection/notes.md
@@ -0,0 +1,7 @@
+# selection
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 18-19.
+
+Trace: X=4 enters both IFs and the first inclusive range. CASE stops before the later matching 4 label. X=9 selects OTHERWISE.
diff --git a/tests/i/selection/program.cps b/tests/i/selection/program.cps
new file mode 100644
index 0000000..7edff5c
--- /dev/null
+++ b/tests/i/selection/program.cps
@@ -0,0 +1,19 @@
+DECLARE X : INTEGER
+X <- 4
+IF X > 0 THEN
+ IF X = 4 THEN
+ OUTPUT "nested"
+ ELSE
+ OUTPUT "wrong"
+ ENDIF
+ENDIF
+CASE OF X
+ 1 TO 5 : OUTPUT "first"
+ 4 : OUTPUT "wrong"
+ OTHERWISE : OUTPUT "wrong"
+ENDCASE
+X <- 9
+CASE OF X
+ 1 TO 5 : OUTPUT "wrong"
+ OTHERWISE : OUTPUT "otherwise"
+ENDCASE
diff --git a/tests/i/signed-zero-division/case.json b/tests/i/signed-zero-division/case.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/i/signed-zero-division/case.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/i/signed-zero-division/expected.txt b/tests/i/signed-zero-division/expected.txt
new file mode 100644
index 0000000..0376278
--- /dev/null
+++ b/tests/i/signed-zero-division/expected.txt
@@ -0,0 +1,2 @@
+[Fatal] line 4: Division by zero
+zero caught
diff --git a/tests/i/signed-zero-division/notes.md b/tests/i/signed-zero-division/notes.md
new file mode 100644
index 0000000..95d5a8c
--- /dev/null
+++ b/tests/i/signed-zero-division/notes.md
@@ -0,0 +1,5 @@
+# signed-zero-division
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis and trace: Project division-by-zero contract includes negative floating zero. The division throws before the BOOLEAN result can be printed.
diff --git a/tests/i/signed-zero-division/program.cps b/tests/i/signed-zero-division/program.cps
new file mode 100644
index 0000000..4a90b76
--- /dev/null
+++ b/tests/i/signed-zero-division/program.cps
@@ -0,0 +1,7 @@
+DECLARE Zero : REAL
+Zero <- -0.0
+TRY
+ OUTPUT (1.0 / Zero) = 0.0
+CATCH
+ OUTPUT "zero caught"
+ENDTRY
diff --git a/tests/i/standard-while/case.json b/tests/i/standard-while/case.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/i/standard-while/case.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/i/standard-while/expected.txt b/tests/i/standard-while/expected.txt
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/tests/i/standard-while/expected.txt
@@ -0,0 +1 @@
+2
diff --git a/tests/i/standard-while/notes.md b/tests/i/standard-while/notes.md
new file mode 100644
index 0000000..1d3cc30
--- /dev/null
+++ b/tests/i/standard-while/notes.md
@@ -0,0 +1,5 @@
+# standard-while
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis and trace: CIE p. 21 does not include DO in WHILE syntax. X advances from 0 through 1 to 2, then the loop stops.
diff --git a/tests/i/standard-while/program.cps b/tests/i/standard-while/program.cps
new file mode 100644
index 0000000..b610bca
--- /dev/null
+++ b/tests/i/standard-while/program.cps
@@ -0,0 +1,6 @@
+DECLARE X : INTEGER
+X <- 0
+WHILE X < 2
+ X <- X + 1
+ENDWHILE
+OUTPUT X
diff --git a/tests/i/stdin/case.json b/tests/i/stdin/case.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/i/stdin/case.json
@@ -0,0 +1 @@
+{}
diff --git a/tests/i/stdin/expected.txt b/tests/i/stdin/expected.txt
new file mode 100644
index 0000000..acfc9ae
--- /dev/null
+++ b/tests/i/stdin/expected.txt
@@ -0,0 +1 @@
+-7:TRUE:Z:hello
diff --git a/tests/i/stdin/input.txt b/tests/i/stdin/input.txt
new file mode 100644
index 0000000..604b657
--- /dev/null
+++ b/tests/i/stdin/input.txt
@@ -0,0 +1,4 @@
+-7
+1
+Z
+hello
diff --git a/tests/i/stdin/notes.md b/tests/i/stdin/notes.md
new file mode 100644
index 0000000..62f8727
--- /dev/null
+++ b/tests/i/stdin/notes.md
@@ -0,0 +1,5 @@
+# stdin
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis and trace: CIE p. 15; the project INPUT contract reads BOOLEAN as an integer (nonzero is true) and STRING as a whitespace-delimited token.
diff --git a/tests/i/stdin/program.cps b/tests/i/stdin/program.cps
new file mode 100644
index 0000000..025c634
--- /dev/null
+++ b/tests/i/stdin/program.cps
@@ -0,0 +1,9 @@
+DECLARE N : INTEGER
+DECLARE Flag : BOOLEAN
+DECLARE Letter : CHAR
+DECLARE Text : STRING
+INPUT N
+INPUT Flag
+INPUT Letter
+INPUT Text
+OUTPUT N, ":", Flag, ":", Letter, ":", Text
diff --git a/tests/i/string-extensions/case.json b/tests/i/string-extensions/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/string-extensions/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/string-extensions/expected.txt b/tests/i/string-extensions/expected.txt
new file mode 100644
index 0000000..c158267
--- /dev/null
+++ b/tests/i/string-extensions/expected.txt
@@ -0,0 +1,5 @@
+ab:
+65:Z
+TRUE:FALSE:FALSE
+9223372036854775807
+TRUE
diff --git a/tests/i/string-extensions/notes.md b/tests/i/string-extensions/notes.md
new file mode 100644
index 0000000..5ab3d90
--- /dev/null
+++ b/tests/i/string-extensions/notes.md
@@ -0,0 +1,7 @@
+# string-extensions
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: Project builtin manuals; LEFT, ASC, CHR, IS_NUM and numeric string conversions are extensions, not specified by this CIE guide.
+
+Trace: LEFT keeps two or zero bytes; ASCII A=65 and Z=90. Only 12.5 is a fully consumed nonempty number. Integer conversion preserves all 19 digits; REAL is observed only through equality.
diff --git a/tests/i/string-extensions/program.cps b/tests/i/string-extensions/program.cps
new file mode 100644
index 0000000..f3b4844
--- /dev/null
+++ b/tests/i/string-extensions/program.cps
@@ -0,0 +1,5 @@
+OUTPUT LEFT("abcd", 2), ":", LEFT("abcd", 0)
+OUTPUT ASC('A'), ":", CHR(90)
+OUTPUT IS_NUM("12.5"), ":", IS_NUM("12x"), ":", IS_NUM("")
+OUTPUT NUM_TO_STR(9223372036854775807)
+OUTPUT STR_TO_NUM("12.5") = 12.5
diff --git a/tests/i/strings/case.json b/tests/i/strings/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/strings/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/strings/expected.txt b/tests/i/strings/expected.txt
new file mode 100644
index 0000000..54c5a9c
--- /dev/null
+++ b/tests/i/strings/expected.txt
@@ -0,0 +1,5 @@
+0:8
+BCD:FGH
+Summer Pudding
+w:H:@
+TRUE:TRUE
diff --git a/tests/i/strings/notes.md b/tests/i/strings/notes.md
new file mode 100644
index 0000000..e17c08b
--- /dev/null
+++ b/tests/i/strings/notes.md
@@ -0,0 +1,7 @@
+# strings
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 7, 16-17; byte ordering of ASCII strings is a project convention.
+
+Trace: The empty string has length 0; MID positions 2..4 are BCD; the last three characters are FGH. Case conversion changes only the letters. Concatenation creates equal contents.
diff --git a/tests/i/strings/program.cps b/tests/i/strings/program.cps
new file mode 100644
index 0000000..e1f934b
--- /dev/null
+++ b/tests/i/strings/program.cps
@@ -0,0 +1,9 @@
+DECLARE Empty : STRING
+DECLARE Text : STRING
+Empty <- ""
+Text <- "ABCDEFGH"
+OUTPUT LENGTH(Empty), ":", LENGTH(Text)
+OUTPUT MID(Text, 2, 3), ":", RIGHT(Text, 3)
+OUTPUT "Summer" & " " & "Pudding"
+OUTPUT LCASE('W'), ":", UCASE('h'), ":", LCASE('@')
+OUTPUT "same" = ("sa" & "me"), ":", "A" < "B"
diff --git a/tests/i/text-files/case.json b/tests/i/text-files/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/text-files/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/text-files/expected-files/result.txt b/tests/i/text-files/expected-files/result.txt
new file mode 100644
index 0000000..317dc55
--- /dev/null
+++ b/tests/i/text-files/expected-files/result.txt
@@ -0,0 +1,3 @@
+first
+
+last
diff --git a/tests/i/text-files/expected.txt b/tests/i/text-files/expected.txt
new file mode 100644
index 0000000..7471a77
--- /dev/null
+++ b/tests/i/text-files/expected.txt
@@ -0,0 +1,7 @@
+[alpha]
+[]
+[omega]
+TRUE:3
+[first]
+[]
+[last]
diff --git a/tests/i/text-files/files/empty.txt b/tests/i/text-files/files/empty.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/i/text-files/files/empty.txt
diff --git a/tests/i/text-files/files/input.txt b/tests/i/text-files/files/input.txt
new file mode 100644
index 0000000..4705e80
--- /dev/null
+++ b/tests/i/text-files/files/input.txt
@@ -0,0 +1,3 @@
+alpha
+
+omega \ No newline at end of file
diff --git a/tests/i/text-files/files/result.txt b/tests/i/text-files/files/result.txt
new file mode 100644
index 0000000..6e263ab
--- /dev/null
+++ b/tests/i/text-files/files/result.txt
@@ -0,0 +1 @@
+obsolete
diff --git a/tests/i/text-files/notes.md b/tests/i/text-files/notes.md
new file mode 100644
index 0000000..cc62aea
--- /dev/null
+++ b/tests/i/text-files/notes.md
@@ -0,0 +1,9 @@
+# text-files
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE p. 25; CRLF input handling follows project text-file semantics.
+
+Trace: Input contains three lines, including an empty line and a last line without terminator. Empty-file EOF is true. WRITE replaces old contents; APPEND adds last after the existing blank line.
+
+The project requires DO after WHILE; this fixture uses that spelling to exercise runtime semantics. The separate standard-while fixture tests the CIE spelling.
diff --git a/tests/i/text-files/program.cps b/tests/i/text-files/program.cps
new file mode 100644
index 0000000..1d6d5bb
--- /dev/null
+++ b/tests/i/text-files/program.cps
@@ -0,0 +1,26 @@
+DECLARE Line : STRING
+DECLARE Count : INTEGER
+OPENFILE "input.txt" FOR READ
+Count <- 0
+WHILE NOT EOF("input.txt") DO
+ READFILE "input.txt", Line
+ OUTPUT "[", Line, "]"
+ Count <- Count + 1
+ENDWHILE
+CLOSEFILE "input.txt"
+OPENFILE "empty.txt" FOR READ
+OUTPUT EOF("empty.txt"), ":", Count
+CLOSEFILE "empty.txt"
+OPENFILE "result.txt" FOR WRITE
+WRITEFILE "result.txt", "first"
+WRITEFILE "result.txt", ""
+CLOSEFILE "result.txt"
+OPENFILE "result.txt" FOR APPEND
+WRITEFILE "result.txt", "last"
+CLOSEFILE "result.txt"
+OPENFILE "result.txt" FOR READ
+WHILE NOT EOF("result.txt") DO
+ READFILE "result.txt", Line
+ OUTPUT "[", Line, "]"
+ENDWHILE
+CLOSEFILE "result.txt"
diff --git a/tests/i/uncaught-error/case.json b/tests/i/uncaught-error/case.json
new file mode 100644
index 0000000..9dc1e30
--- /dev/null
+++ b/tests/i/uncaught-error/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+}
diff --git a/tests/i/uncaught-error/expected.txt b/tests/i/uncaught-error/expected.txt
new file mode 100644
index 0000000..8b66756
--- /dev/null
+++ b/tests/i/uncaught-error/expected.txt
@@ -0,0 +1,2 @@
+[Fatal] line 3: Division by zero
+Unhandled exception. Program terminated.
diff --git a/tests/i/uncaught-error/notes.md b/tests/i/uncaught-error/notes.md
new file mode 100644
index 0000000..d4e2d65
--- /dev/null
+++ b/tests/i/uncaught-error/notes.md
@@ -0,0 +1,7 @@
+# uncaught-error
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: Project runtime-check and final-handler contract.
+
+Trace: MOD by zero throws on line 3. The final handler prints termination and returns 1; unreachable is never printed.
diff --git a/tests/i/uncaught-error/program.cps b/tests/i/uncaught-error/program.cps
new file mode 100644
index 0000000..dd6e53f
--- /dev/null
+++ b/tests/i/uncaught-error/program.cps
@@ -0,0 +1,4 @@
+DECLARE Zero : INTEGER
+Zero <- 0
+OUTPUT 1 MOD Zero
+OUTPUT "unreachable"
diff --git a/tests/i/unwind-calls/case.json b/tests/i/unwind-calls/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/unwind-calls/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/unwind-calls/expected.txt b/tests/i/unwind-calls/expected.txt
new file mode 100644
index 0000000..bae07ac
--- /dev/null
+++ b/tests/i/unwind-calls/expected.txt
@@ -0,0 +1,2 @@
+7
+outer catch
diff --git a/tests/i/unwind-calls/notes.md b/tests/i/unwind-calls/notes.md
new file mode 100644
index 0000000..20baa77
--- /dev/null
+++ b/tests/i/unwind-calls/notes.md
@@ -0,0 +1,7 @@
+# unwind-calls
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: Project exception extension and C++ unwinding ABI.
+
+Trace: Fail unwinds into the caller catch, which returns 7 while finishing that catch. A new throw inside the nested catch transfers to the outer catch.
diff --git a/tests/i/unwind-calls/program.cps b/tests/i/unwind-calls/program.cps
new file mode 100644
index 0000000..4855151
--- /dev/null
+++ b/tests/i/unwind-calls/program.cps
@@ -0,0 +1,21 @@
+PROCEDURE Fail()
+ THROW
+ENDPROCEDURE
+FUNCTION CatchAndReturn() RETURNS INTEGER
+ TRY
+ CALL Fail()
+ CATCH
+ RETURN 7
+ ENDTRY
+ RETURN 0
+ENDFUNCTION
+OUTPUT CatchAndReturn()
+TRY
+ TRY
+ THROW
+ CATCH
+ THROW
+ ENDTRY
+CATCH
+ OUTPUT "outer catch"
+ENDTRY
diff --git a/tests/i/user-types/case.json b/tests/i/user-types/case.json
new file mode 100644
index 0000000..1f18635
--- /dev/null
+++ b/tests/i/user-types/case.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 0
+}
diff --git a/tests/i/user-types/expected.txt b/tests/i/user-types/expected.txt
new file mode 100644
index 0000000..6b16f10
--- /dev/null
+++ b/tests/i/user-types/expected.txt
@@ -0,0 +1,2 @@
+9:7:first:TRUE
+4:8
diff --git a/tests/i/user-types/notes.md b/tests/i/user-types/notes.md
new file mode 100644
index 0000000..9d762ca
--- /dev/null
+++ b/tests/i/user-types/notes.md
@@ -0,0 +1,7 @@
+# user-types
+
+Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
+
+Basis: CIE pp. 12-14 and 28; CLASS value copying follows the implemented project subset.
+
+Trace: Record B is a value copy before pointer P changes A.X. Spring+2 is Autumn. Copying First into Second isolates the public field.
diff --git a/tests/i/user-types/program.cps b/tests/i/user-types/program.cps
new file mode 100644
index 0000000..7c048e8
--- /dev/null
+++ b/tests/i/user-types/program.cps
@@ -0,0 +1,28 @@
+TYPE Point
+ DECLARE X : INTEGER
+ DECLARE Name : STRING
+ENDTYPE
+TYPE PointPtr = ^Point
+TYPE Season = (Spring, Summer, Autumn, Winter)
+CLASS Box
+ PUBLIC Value : INTEGER
+ PRIVATE Hidden : INTEGER
+ENDCLASS
+DECLARE A : Point
+DECLARE B : Point
+DECLARE P : PointPtr
+DECLARE S : Season
+DECLARE First : Box
+DECLARE Second : Box
+A.X <- 7
+A.Name <- "first"
+B <- A
+P <- ^A
+P^.X <- 9
+S <- Spring
+S <- S + 2
+First.Value <- 4
+Second <- First
+Second.Value <- 8
+OUTPUT A.X, ":", B.X, ":", B.Name, ":", S = Autumn
+OUTPUT First.Value, ":", Second.Value