aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-20 11:57:16 +0000
committer_ov4 <ov4@ov4.org>2026-10-20 11:57:16 +0000
commit62b605c6c0ea13e9763c0a0115464007b13a8831 (patch)
tree53c27965f5a365682e0d79fd96e25b228ecb9dca /tests
parentbfe2e75d7e3b372e55369677028429990c49bc54 (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.json1
-rw-r--r--tests/i/custom-string/expected.txt1
-rw-r--r--tests/i/custom-string/notes.md3
-rw-r--r--tests/i/custom-string/program.cps13
-rw-r--r--tests/i/string-values/case.json1
-rw-r--r--tests/i/string-values/expected.txt8
-rw-r--r--tests/i/string-values/notes.md5
-rw-r--r--tests/i/string-values/program.cps40
-rw-r--r--tests/iii/builtin-arity/case.json2
-rw-r--r--tests/iii/identifier-builtin-collision/case.json2
-rw-r--r--tests/iii/string-class-required/case.json1
-rw-r--r--tests/iii/string-class-required/notes.md3
-rw-r--r--tests/iii/string-class-required/program.cps1
-rw-r--r--tests/iii/string-type-mismatch/case.json2
-rw-r--r--tests/library/exp-string/case.json2
-rw-r--r--tests/library/exp-string/program.cps168
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