diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-20 11:57:16 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-20 11:57:16 +0000 |
| commit | 62b605c6c0ea13e9763c0a0115464007b13a8831 (patch) | |
| tree | 53c27965f5a365682e0d79fd96e25b228ecb9dca /tests | |
| parent | bfe2e75d7e3b372e55369677028429990c49bc54 (diff) | |
refactor(strings): replace compiler builtins with the STRING library
Construct literals as STRING values and route string operations through
ordinary library functions and operators. Preserve value ownership in
records, arrays, constants and file I/O.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/i/custom-string/case.json | 1 | ||||
| -rw-r--r-- | tests/i/custom-string/expected.txt | 1 | ||||
| -rw-r--r-- | tests/i/custom-string/notes.md | 3 | ||||
| -rw-r--r-- | tests/i/custom-string/program.cps | 13 | ||||
| -rw-r--r-- | tests/i/string-values/case.json | 1 | ||||
| -rw-r--r-- | tests/i/string-values/expected.txt | 8 | ||||
| -rw-r--r-- | tests/i/string-values/notes.md | 5 | ||||
| -rw-r--r-- | tests/i/string-values/program.cps | 40 | ||||
| -rw-r--r-- | tests/iii/builtin-arity/case.json | 2 | ||||
| -rw-r--r-- | tests/iii/identifier-builtin-collision/case.json | 2 | ||||
| -rw-r--r-- | tests/iii/string-class-required/case.json | 1 | ||||
| -rw-r--r-- | tests/iii/string-class-required/notes.md | 3 | ||||
| -rw-r--r-- | tests/iii/string-class-required/program.cps | 1 | ||||
| -rw-r--r-- | tests/iii/string-type-mismatch/case.json | 2 | ||||
| -rw-r--r-- | tests/library/exp-string/case.json | 2 | ||||
| -rw-r--r-- | tests/library/exp-string/program.cps | 168 |
16 files changed, 165 insertions, 88 deletions
diff --git a/tests/i/custom-string/case.json b/tests/i/custom-string/case.json new file mode 100644 index 0000000..85acec5 --- /dev/null +++ b/tests/i/custom-string/case.json @@ -0,0 +1 @@ +{"compiler_args":["-no-std"]} diff --git a/tests/i/custom-string/expected.txt b/tests/i/custom-string/expected.txt new file mode 100644 index 0000000..b3ac0a3 --- /dev/null +++ b/tests/i/custom-string/expected.txt @@ -0,0 +1 @@ +custom STRING:42 diff --git a/tests/i/custom-string/notes.md b/tests/i/custom-string/notes.md new file mode 100644 index 0000000..a5ead49 --- /dev/null +++ b/tests/i/custom-string/notes.md @@ -0,0 +1,3 @@ +# Custom STRING + +Human review: pending. With -no-std, a user-defined STRING class constructs ordinary literals through NEW(C_STRING). OUTPUT obtains its text through C_STR. LENGTH is an ordinary user function without a compiler builtin intercept. diff --git a/tests/i/custom-string/program.cps b/tests/i/custom-string/program.cps new file mode 100644 index 0000000..cf2bb24 --- /dev/null +++ b/tests/i/custom-string/program.cps @@ -0,0 +1,13 @@ +CLASS STRING + Text : C_STRING + PROCEDURE NEW(Value : C_STRING) + Text <- Value + ENDPROCEDURE + FUNCTION C_STR() RETURNS C_STRING + RETURN Text + ENDFUNCTION +ENDCLASS +FUNCTION LENGTH(Value : INTEGER) RETURNS INTEGER + RETURN Value + 1 +ENDFUNCTION +OUTPUT "custom STRING", ":", LENGTH(41) diff --git a/tests/i/string-values/case.json b/tests/i/string-values/case.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/tests/i/string-values/case.json @@ -0,0 +1 @@ +{} diff --git a/tests/i/string-values/expected.txt b/tests/i/string-values/expected.txt new file mode 100644 index 0000000..e8badf2 --- /dev/null +++ b/tests/i/string-values/expected.txt @@ -0,0 +1,8 @@ +constant:independent:global:local +changed:two +one +two +TRUE:TRUE:TRUE:TRUE:TRUE +1:1 +matched +B diff --git a/tests/i/string-values/notes.md b/tests/i/string-values/notes.md new file mode 100644 index 0000000..1e821cc --- /dev/null +++ b/tests/i/string-values/notes.md @@ -0,0 +1,5 @@ +# String values + +Human review: pending. Expected output is traced from independent string values. + +Record copies and BYVAL array calls must preserve the source when a copy changes. Self-assignment preserves the value. Global and constant strings remain available to functions. Comparisons use case-sensitive content ordering. Ordinary literals retain the legacy NUL truncation; CHR can construct an owning one-byte NUL string. diff --git a/tests/i/string-values/program.cps b/tests/i/string-values/program.cps new file mode 100644 index 0000000..46822fc --- /dev/null +++ b/tests/i/string-values/program.cps @@ -0,0 +1,40 @@ +GLOBAL + DECLARE Label : STRING + Label <- "global" +ENDGLOBAL +CONSTANT Greeting = "constant" +TYPE Item + DECLARE Text : STRING +ENDTYPE +FUNCTION ReadConstant() RETURNS STRING + CONSTANT Local = "local" + RETURN Local +ENDFUNCTION +FUNCTION Echo(Value : Item) RETURNS Item + RETURN Value +ENDFUNCTION +PROCEDURE Change(Values : ARRAY OF STRING) + Values[1] <- "changed" + OUTPUT Values[1], ":", Values[2] +ENDPROCEDURE +DECLARE A : Item +DECLARE B : Item +A.Text <- Greeting +B <- Echo(A) +B.Text <- "independent" +B <- B +OUTPUT A.Text, ":", B.Text, ":", Label, ":", ReadConstant() +DECLARE Values : ARRAY[1:2] OF STRING +Values[1] <- "one" +Values[2] <- "two" +CALL Change(Values) +OUTPUT Values +OUTPUT "A" < "B", ":", "B" > "A", ":", "A" <= "A", ":", "B" >= "A", ":", "a" <> "A" +OUTPUT LENGTH("a\0b"), ":", LENGTH(CHR(0)) +DECLARE Selected : STRING +Selected <- "B" +CASE OF Selected + "A" : OUTPUT "wrong" + "B" : OUTPUT "matched" +ENDCASE +OUTPUT Selected diff --git a/tests/iii/builtin-arity/case.json b/tests/iii/builtin-arity/case.json index 3b9e9a7..8d0e653 100644 --- a/tests/iii/builtin-arity/case.json +++ b/tests/iii/builtin-arity/case.json @@ -1,7 +1,7 @@ { "errors": [ { - "reason": "LENGTH\\ expects\\ 1\\ arg", + "reason": "Incorrect # arguments passed to LENGTH", "line": 2 } ] diff --git a/tests/iii/identifier-builtin-collision/case.json b/tests/iii/identifier-builtin-collision/case.json index df7c2b6..a3a67e6 100644 --- a/tests/iii/identifier-builtin-collision/case.json +++ b/tests/iii/identifier-builtin-collision/case.json @@ -1,7 +1,7 @@ { "errors": [ { - "reason": "'lENGTH'\\ is\\ a\\ built\\-in\\ function\\ and\\ cannot\\ be\\ redefined", + "reason": "Duplicate definition LENGTH", "line": 1 } ] diff --git a/tests/iii/string-class-required/case.json b/tests/iii/string-class-required/case.json new file mode 100644 index 0000000..1d88c75 --- /dev/null +++ b/tests/iii/string-class-required/case.json @@ -0,0 +1 @@ +{"compiler_args":["-no-std"],"errors":[{"reason":"visible STRING class","line":1}]} diff --git a/tests/iii/string-class-required/notes.md b/tests/iii/string-class-required/notes.md new file mode 100644 index 0000000..ef8b67d --- /dev/null +++ b/tests/iii/string-class-required/notes.md @@ -0,0 +1,3 @@ +# STRING class required + +Human review: pending. With -no-std and no STRING class declaration, an ordinary string literal must produce a compiler diagnostic at its source line. diff --git a/tests/iii/string-class-required/program.cps b/tests/iii/string-class-required/program.cps new file mode 100644 index 0000000..91b5da7 --- /dev/null +++ b/tests/iii/string-class-required/program.cps @@ -0,0 +1 @@ +OUTPUT "missing class" diff --git a/tests/iii/string-type-mismatch/case.json b/tests/iii/string-type-mismatch/case.json index 199909e..975c57c 100644 --- a/tests/iii/string-type-mismatch/case.json +++ b/tests/iii/string-type-mismatch/case.json @@ -1,7 +1,7 @@ { "errors": [ { - "reason": "STRING\\ comparison\\ requires\\ two\\ STRING\\ operands", + "reason": "Operator = cannot be applied to a record value \\(type STRING\\)", "line": 2 } ] diff --git a/tests/library/exp-string/case.json b/tests/library/exp-string/case.json index e1ed21a..4e37b1c 100644 --- a/tests/library/exp-string/case.json +++ b/tests/library/exp-string/case.json @@ -1 +1 @@ -{"sources":["program.cps","../../../pseudocode-lib/_exp_string.cps"],"compiler_args":["-no-std"]} +{"sources":["program.cps","../../../pseudocode-lib/string.cps"],"compiler_args":["-no-std"]} diff --git a/tests/library/exp-string/program.cps b/tests/library/exp-string/program.cps index 0adf86c..2e45dc3 100644 --- a/tests/library/exp-string/program.cps +++ b/tests/library/exp-string/program.cps @@ -1,43 +1,43 @@ -INCLUDE "../../../pseudocode-lib/_exp_string.cps" -FUNCTION Echo(S : _EXP_STRING) RETURNS _EXP_STRING +INCLUDE "../../../pseudocode-lib/string.cps" +FUNCTION Echo(S : STRING) RETURNS STRING RETURN S ENDFUNCTION -DECLARE A : _EXP_STRING((C_STRING)"hello") -DECLARE B : _EXP_STRING(A) +DECLARE A : STRING((C_STRING)"hello") +DECLARE B : STRING(A) B <- (C_STRING)"world" B <- B -CALL _EXP_STRING_OUTPUT(A & B) -DECLARE Empty : _EXP_STRING -OUTPUT _EXP_STRING_LENGTH(Empty) -DECLARE Nuls : _EXP_STRING(3, (C_CHAR)'\0') -OUTPUT _EXP_STRING_LENGTH(Nuls) -DECLARE Long : _EXP_STRING(20000, (C_CHAR)'x') +OUTPUT (A & B) +DECLARE Empty : STRING +OUTPUT LENGTH(Empty) +DECLARE Nuls : STRING(3, (C_CHAR)'\0') +OUTPUT LENGTH(Nuls) +DECLARE Long : STRING(20000, (C_CHAR)'x') DECLARE I : INTEGER FOR I <- 1 TO 100 Long <- Long & A NEXT I -OUTPUT _EXP_STRING_LENGTH(Long) +OUTPUT LENGTH(Long) Long <- Echo(Long) -OUTPUT _EXP_STRING_LENGTH(Long) -CALL _EXP_STRING_OUTPUT(_EXP_STRING_NUM_TO_STR(42) & _EXP_STRING_NUM_TO_STR(1.25)) -DECLARE Number : _EXP_STRING((C_STRING)"12.5") -OUTPUT _EXP_STRING_STR_TO_NUM(Number) = 12.5 +OUTPUT LENGTH(Long) +OUTPUT (NUM_TO_STR(42) & NUM_TO_STR(1.25)) +DECLARE Number : STRING((C_STRING)"12.5") +OUTPUT STR_TO_NUM(Number) = 12.5 TRY Number <- (C_STRING)"12x" - OUTPUT _EXP_STRING_STR_TO_NUM(Number) + OUTPUT STR_TO_NUM(Number) CATCH OUTPUT "conversion caught" ENDTRY TRY - DECLARE Invalid : _EXP_STRING(-1, (C_CHAR)'x') + DECLARE Invalid : STRING(-1, (C_CHAR)'x') CATCH OUTPUT "length caught" ENDTRY -CALL _EXP_STRING_NUM_TO_STR(99) +CALL NUM_TO_STR(99) CALL Echo(Long) -DECLARE Heap : _EXP_STRING -Heap <- NEW _EXP_STRING((C_STRING)"heap") -CALL _EXP_STRING_OUTPUT(Heap) +DECLARE Heap : STRING +Heap <- NEW STRING((C_STRING)"heap") +OUTPUT (Heap) DELETE Heap CALL CheckLeft() CALL CheckRight() @@ -49,90 +49,90 @@ CALL CheckChr() CALL CheckIsNum() PROCEDURE CheckLeft() - DECLARE Letters : _EXP_STRING((C_STRING)"ABCDEFGH") - DECLARE Empty : _EXP_STRING - DECLARE Nuls : _EXP_STRING(3, (C_CHAR)'\0') - DECLARE A : _EXP_STRING((C_STRING)"hello") - CALL _EXP_STRING_OUTPUT(_EXP_STRING_LEFT(Letters, 3)) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Empty, 2)), ":", _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Letters, 0)), ":", _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Letters, -1)) - CALL _EXP_STRING_OUTPUT(_EXP_STRING_LEFT(Letters, 20)) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Nuls & A, 4)) + DECLARE Letters : STRING((C_STRING)"ABCDEFGH") + DECLARE Empty : STRING + DECLARE Nuls : STRING(3, (C_CHAR)'\0') + DECLARE A : STRING((C_STRING)"hello") + OUTPUT (LEFT(Letters, 3)) + OUTPUT LENGTH(LEFT(Empty, 2)), ":", LENGTH(LEFT(Letters, 0)), ":", LENGTH(LEFT(Letters, -1)) + OUTPUT (LEFT(Letters, 20)) + OUTPUT LENGTH(LEFT(Nuls & A, 4)) ENDPROCEDURE PROCEDURE CheckRight() - DECLARE Letters : _EXP_STRING((C_STRING)"ABCDEFGH") - DECLARE Empty : _EXP_STRING - DECLARE Nuls : _EXP_STRING(3, (C_CHAR)'\0') - DECLARE A : _EXP_STRING((C_STRING)"hello") - CALL _EXP_STRING_OUTPUT(_EXP_STRING_RIGHT(Letters, 3)) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_RIGHT(Empty, 2)), ":", _EXP_STRING_LENGTH(_EXP_STRING_RIGHT(Letters, 0)), ":", _EXP_STRING_LENGTH(_EXP_STRING_RIGHT(Letters, -1)) - CALL _EXP_STRING_OUTPUT(_EXP_STRING_RIGHT(Letters, 20)) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_RIGHT(A & Nuls, 4)) + DECLARE Letters : STRING((C_STRING)"ABCDEFGH") + DECLARE Empty : STRING + DECLARE Nuls : STRING(3, (C_CHAR)'\0') + DECLARE A : STRING((C_STRING)"hello") + OUTPUT (RIGHT(Letters, 3)) + OUTPUT LENGTH(RIGHT(Empty, 2)), ":", LENGTH(RIGHT(Letters, 0)), ":", LENGTH(RIGHT(Letters, -1)) + OUTPUT (RIGHT(Letters, 20)) + OUTPUT LENGTH(RIGHT(A & Nuls, 4)) ENDPROCEDURE PROCEDURE CheckMid() - DECLARE Letters : _EXP_STRING((C_STRING)"ABCDEFGH") - DECLARE Empty : _EXP_STRING - DECLARE Nuls : _EXP_STRING(3, (C_CHAR)'\0') - CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(Letters, 2, 3)) - CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(Letters, -9223372036854775808, 2)) - CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(Letters, 7, 9223372036854775807)) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_MID(Empty, 1, 2)), ":", _EXP_STRING_LENGTH(_EXP_STRING_MID(Letters, 9223372036854775807, 2)) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_MID(Letters, 2, 0)), ":", _EXP_STRING_LENGTH(_EXP_STRING_MID(Letters, 2, -1)) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_MID(Nuls & Letters, 2, 4)) + DECLARE Letters : STRING((C_STRING)"ABCDEFGH") + DECLARE Empty : STRING + DECLARE Nuls : STRING(3, (C_CHAR)'\0') + OUTPUT (MID(Letters, 2, 3)) + OUTPUT (MID(Letters, -9223372036854775808, 2)) + OUTPUT (MID(Letters, 7, 9223372036854775807)) + OUTPUT LENGTH(MID(Empty, 1, 2)), ":", LENGTH(MID(Letters, 9223372036854775807, 2)) + OUTPUT LENGTH(MID(Letters, 2, 0)), ":", LENGTH(MID(Letters, 2, -1)) + OUTPUT LENGTH(MID(Nuls & Letters, 2, 4)) ENDPROCEDURE PROCEDURE CheckLCase() - DECLARE Mixed : _EXP_STRING((C_STRING)"AbC@19") - DECLARE Empty : _EXP_STRING - DECLARE Nuls : _EXP_STRING(2, (C_CHAR)'\0') - CALL _EXP_STRING_OUTPUT(_EXP_STRING_LCASE(Mixed)) - CALL _EXP_STRING_OUTPUT(Mixed) + DECLARE Mixed : STRING((C_STRING)"AbC@19") + DECLARE Empty : STRING + DECLARE Nuls : STRING(2, (C_CHAR)'\0') + OUTPUT (LCASE(Mixed)) + OUTPUT (Mixed) DECLARE Lower : CHAR - Lower <- _EXP_STRING_LCASE('W') - OUTPUT Lower, ":", _EXP_STRING_LCASE('w'), ":", _EXP_STRING_LCASE('@') - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_LCASE(Empty)), ":", _EXP_STRING_LENGTH(_EXP_STRING_LCASE(Nuls & Mixed)) - CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(_EXP_STRING_LCASE(Nuls & Mixed), 3, 3)) + Lower <- LCASE('W') + OUTPUT Lower, ":", LCASE('w'), ":", LCASE('@') + OUTPUT LENGTH(LCASE(Empty)), ":", LENGTH(LCASE(Nuls & Mixed)) + OUTPUT (MID(LCASE(Nuls & Mixed), 3, 3)) ENDPROCEDURE PROCEDURE CheckUCase() - DECLARE Mixed : _EXP_STRING((C_STRING)"AbC@19") - DECLARE Empty : _EXP_STRING - DECLARE Nuls : _EXP_STRING(2, (C_CHAR)'\0') - CALL _EXP_STRING_OUTPUT(_EXP_STRING_UCASE(Mixed)) - CALL _EXP_STRING_OUTPUT(Mixed) + DECLARE Mixed : STRING((C_STRING)"AbC@19") + DECLARE Empty : STRING + DECLARE Nuls : STRING(2, (C_CHAR)'\0') + OUTPUT (UCASE(Mixed)) + OUTPUT (Mixed) DECLARE Upper : CHAR - Upper <- _EXP_STRING_UCASE('h') - OUTPUT Upper, ":", _EXP_STRING_UCASE('H'), ":", _EXP_STRING_UCASE('@') - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_UCASE(Empty)), ":", _EXP_STRING_LENGTH(_EXP_STRING_UCASE(Nuls & Mixed)) - CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(_EXP_STRING_UCASE(Nuls & Mixed), 3, 3)) + Upper <- UCASE('h') + OUTPUT Upper, ":", UCASE('H'), ":", UCASE('@') + OUTPUT LENGTH(UCASE(Empty)), ":", LENGTH(UCASE(Nuls & Mixed)) + OUTPUT (MID(UCASE(Nuls & Mixed), 3, 3)) ENDPROCEDURE PROCEDURE CheckAsc() - DECLARE Letters : _EXP_STRING((C_STRING)"ABCDEFGH") - DECLARE Empty : _EXP_STRING - DECLARE Nuls : _EXP_STRING(2, (C_CHAR)'\0') - DECLARE High : _EXP_STRING(1, (C_CHAR)255) - OUTPUT _EXP_STRING_ASC('A'), ":", _EXP_STRING_ASC(Letters) - OUTPUT _EXP_STRING_ASC(Empty), ":", _EXP_STRING_ASC(Nuls), ":", _EXP_STRING_ASC('\0') - OUTPUT _EXP_STRING_ASC(High) + DECLARE Letters : STRING((C_STRING)"ABCDEFGH") + DECLARE Empty : STRING + DECLARE Nuls : STRING(2, (C_CHAR)'\0') + DECLARE High : STRING(1, (C_CHAR)255) + OUTPUT ASC('A'), ":", ASC(Letters) + OUTPUT ASC(Empty), ":", ASC(Nuls), ":", ASC('\0') + OUTPUT ASC(High) ENDPROCEDURE PROCEDURE CheckChr() - CALL _EXP_STRING_OUTPUT(_EXP_STRING_CHR(65) & _EXP_STRING_CHR(90)) - OUTPUT _EXP_STRING_ASC(_EXP_STRING_CHR(_EXP_STRING_ASC('A'))) - OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_CHR(0)), ":", _EXP_STRING_ASC(_EXP_STRING_CHR(0)) - OUTPUT _EXP_STRING_ASC(_EXP_STRING_CHR(321)), ":", _EXP_STRING_ASC(_EXP_STRING_CHR(-1)) + OUTPUT (CHR(65) & CHR(90)) + OUTPUT ASC(CHR(ASC('A'))) + OUTPUT LENGTH(CHR(0)), ":", ASC(CHR(0)) + OUTPUT ASC(CHR(321)), ":", ASC(CHR(-1)) ENDPROCEDURE PROCEDURE CheckIsNum() - DECLARE Number : _EXP_STRING((C_STRING)"12.5") - DECLARE Junk : _EXP_STRING((C_STRING)"12x") - DECLARE Empty : _EXP_STRING - DECLARE Leading : _EXP_STRING((C_STRING)" 12.5") - DECLARE Trailing : _EXP_STRING((C_STRING)"12.5 ") - DECLARE Whitespace : _EXP_STRING((C_STRING)" ") - OUTPUT _EXP_STRING_IS_NUM(Number), ":", _EXP_STRING_IS_NUM(Junk), ":", _EXP_STRING_IS_NUM(Empty) - OUTPUT _EXP_STRING_IS_NUM(Leading), ":", _EXP_STRING_IS_NUM(Trailing), ":", _EXP_STRING_IS_NUM(Whitespace) - OUTPUT _EXP_STRING_IS_NUM(Number & _EXP_STRING_CHR(0)), ":", _EXP_STRING_IS_NUM(_EXP_STRING_CHR(0) & Number) + DECLARE Number : STRING((C_STRING)"12.5") + DECLARE Junk : STRING((C_STRING)"12x") + DECLARE Empty : STRING + DECLARE Leading : STRING((C_STRING)" 12.5") + DECLARE Trailing : STRING((C_STRING)"12.5 ") + DECLARE Whitespace : STRING((C_STRING)" ") + OUTPUT IS_NUM(Number), ":", IS_NUM(Junk), ":", IS_NUM(Empty) + OUTPUT IS_NUM(Leading), ":", IS_NUM(Trailing), ":", IS_NUM(Whitespace) + OUTPUT IS_NUM(Number & CHR(0)), ":", IS_NUM(CHR(0) & Number) ENDPROCEDURE |
