aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-22 15:33:17 +0000
committer_ov4 <ov4@ov4.org>2026-10-22 15:35:05 +0000
commit8745f421b4cf7e1d54c17a360d46fab889ca12cc (patch)
tree4c2a3508627db04493af35643580417d41b63f89 /tests
parent5e84edbe1a79c6a7752ee276ea6c1a4daef4fa8e (diff)
feat(input)!: validate INPUT and read whole lines into STRING
Scalar INPUT now reads one whitespace-delimited token through module-local IR helpers instead of scanf, then skips spaces and tabs and consumes one newline. INTEGER, REAL, BOOLEAN (TRUE or FALSE in any case) and CHAR are validated, and bad input or end of input is a runtime error. STRING INPUT reads the rest of the line. The unused scanf and REAL printf format globals are removed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/i/input-targets/input.txt4
-rw-r--r--tests/i/input-targets/notes.md4
-rw-r--r--tests/i/stdin/input.txt2
-rw-r--r--tests/i/stdin/notes.md2
-rw-r--r--tests/ii/files/program.cps11
-rw-r--r--tests/ii/generator-vectors.json2
-rw-r--r--tests/ii/strings/generate.pl14
-rw-r--r--tests/ii/strings/notes.md2
-rw-r--r--tests/ii/strings/program.cps2
-rw-r--r--tests/ii/strings/reference.cc5
10 files changed, 30 insertions, 18 deletions
diff --git a/tests/i/input-targets/input.txt b/tests/i/input-targets/input.txt
index dc0af77..8d0376e 100644
--- a/tests/i/input-targets/input.txt
+++ b/tests/i/input-targets/input.txt
@@ -1,2 +1,4 @@
10 20 30
-40 50 Ada 1 A 2.5 -7 60 70 80 90 100
+40 50
+Ada
+TRUE A 2.5 -7 60 70 80 90 100
diff --git a/tests/i/input-targets/notes.md b/tests/i/input-targets/notes.md
index dded40c..57c7db4 100644
--- a/tests/i/input-targets/notes.md
+++ b/tests/i/input-targets/notes.md
@@ -2,6 +2,6 @@
Human review: pending. Expected output was independently traced by AI, not captured from cpsc.
-Basis: CIE guide p. 15 section 5.1 allows individual data-structure elements. Native C input, numeric BOOLEAN input, whitespace-delimited STRING input and exceptions follow project behavior.
+Basis: CIE guide p. 15 section 5.1 allows individual data-structure elements. Native C input, token-based scalar input, rest-of-line STRING input and exceptions follow project behavior.
-Trace: the loop stores 10, 20, 30; the grid receives 40. Student 2 receives 50, Ada, true, A, 2.5 and -7, then its score becomes 80 through P. The class fields receive 60 and 70. NextIndex prints once and selects Scores[1], which receives 90. Bounds and null-pointer failures occur before reading input, leaving 100 for the final valid input.
+Trace: the loop stores 10, 20, 30; the grid receives 40. Student 2 receives 50, the line Ada, true, A, 2.5 and -7, then its score becomes 80 through P. The class fields receive 60 and 70. NextIndex prints once and selects Scores[1], which receives 90. Bounds and null-pointer failures occur before reading input, leaving 100 for the final valid input.
diff --git a/tests/i/stdin/input.txt b/tests/i/stdin/input.txt
index 604b657..4ac051f 100644
--- a/tests/i/stdin/input.txt
+++ b/tests/i/stdin/input.txt
@@ -1,4 +1,4 @@
-7
-1
+TRUE
Z
hello
diff --git a/tests/i/stdin/notes.md b/tests/i/stdin/notes.md
index 62f8727..63f1a22 100644
--- a/tests/i/stdin/notes.md
+++ b/tests/i/stdin/notes.md
@@ -2,4 +2,4 @@
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.
+Basis and trace: CIE p. 15; the project INPUT contract reads BOOLEAN as TRUE or FALSE in any case, other scalars as whitespace-delimited tokens, and STRING as the rest of the line.
diff --git a/tests/ii/files/program.cps b/tests/ii/files/program.cps
index f825118..a9f22c0 100644
--- a/tests/ii/files/program.cps
+++ b/tests/ii/files/program.cps
@@ -3,12 +3,19 @@ DECLARE Index : INTEGER
DECLARE Text : STRING
DECLARE Extra : STRING
DECLARE Line : STRING
+DECLARE Pair : STRING
+DECLARE Cut : INTEGER
DECLARE Combined : STRING
DECLARE Lines : INTEGER
INPUT Count
FOR Index <- 1 TO Count
- INPUT Text
- INPUT Extra
+ INPUT Pair
+ Cut <- 1
+ WHILE MID(Pair, Cut, 1) <> " "
+ Cut <- Cut + 1
+ ENDWHILE
+ Text <- LEFT(Pair, Cut - 1)
+ Extra <- RIGHT(Pair, LENGTH(Pair) - Cut)
OPENFILE "roundtrip.txt" FOR WRITE
WRITEFILE "roundtrip.txt", Text
WRITEFILE "roundtrip.txt", ""
diff --git a/tests/ii/generator-vectors.json b/tests/ii/generator-vectors.json
index d6a95a6..daa542d 100644
--- a/tests/ii/generator-vectors.json
+++ b/tests/ii/generator-vectors.json
@@ -7,5 +7,5 @@
"overload-functions": "1c2c3aedfed36812d8f7cd1648046b134eebac1fd73260558ed4d486e3d72c6e",
"overload-methods": "f02d8d7e31c3c03ccf647d7e2bda18cdedd706db38308cdd35f8a3b5f87b2905",
"real": "8ffb0244589eff8a1d873ca6f1e1d66cc84944ab68d8bfafa118e941891ac518",
- "strings": "c8b1aa74413d7e2a673baa27e495745b5fdf799ba423e0180620b8427cd1c42a"
+ "strings": "2f5d7100ff29871403d339402681d8974f7955387ebddca36ec61cbf8b391a8e"
}
diff --git a/tests/ii/strings/generate.pl b/tests/ii/strings/generate.pl
index f3ac098..57aeef0 100644
--- a/tests/ii/strings/generate.pl
+++ b/tests/ii/strings/generate.pl
@@ -6,18 +6,18 @@ use Random;
my ($seed, $count) = @ARGV;
my $rng = Random->new($seed, "strings");
my @edges = (
- '1 placeholder 1 0',
- '0 A 1 1',
- '0 Ab09 4 1',
- '0 Ab09 1 4',
- '0 Ab09 2 0',
+ '1 1 0 placeholder',
+ '0 1 1 A',
+ '0 4 1 Ab09',
+ '0 1 4 Ab09',
+ '0 2 0 Ab09',
);
$rng->emit($count, \@edges, sub {
my $size = $rng->integer(0,24);
-return '1 placeholder 1 0' if $size == 0;
+return '1 1 0 placeholder' if $size == 0;
my @alphabet = split //, 'ABCXYZabcxyz019@_-';
my $text = join '', map { $alphabet[$rng->integer(0,$#alphabet)] } 1 .. $size;
my $start = $rng->integer(1,$size);
my $width = $rng->integer(0,$size-$start+1);
-return "0 $text $start $width";
+return "0 $start $width $text";
});
diff --git a/tests/ii/strings/notes.md b/tests/ii/strings/notes.md
index 01ea90a..468cff4 100644
--- a/tests/ii/strings/notes.md
+++ b/tests/ii/strings/notes.md
@@ -1,5 +1,5 @@
# strings
-CIE pp. 16-17 for LENGTH/MID/RIGHT/concatenation; full-STRING LCASE/UCASE is a project extension. Inputs are ASCII under the default C locale. Empty input is encoded with a flag because project INPUT reads tokens. Substrings remain in range; zero width is a documented project boundary.
+CIE pp. 16-17 for LENGTH/MID/RIGHT/concatenation; full-STRING LCASE/UCASE is a project extension. Inputs are ASCII under the default C locale. The text is the last field of each record because INPUT into a STRING reads the rest of the line; empty text is still encoded with a flag so that every record has a visible text field. Substrings remain in range; zero width is a documented project boundary.
Each record produces exactly one output line. Random records are preceded by fixed boundary records; every arithmetic intermediate is bounded.
diff --git a/tests/ii/strings/program.cps b/tests/ii/strings/program.cps
index 55e7541..8a5e509 100644
--- a/tests/ii/strings/program.cps
+++ b/tests/ii/strings/program.cps
@@ -7,9 +7,9 @@ DECLARE Width : INTEGER
INPUT Count
FOR Index <- 1 TO Count
INPUT Empty
- INPUT Text
INPUT Start
INPUT Width
+ INPUT Text
IF Empty = 1 THEN
Text <- ""
ENDIF
diff --git a/tests/ii/strings/reference.cc b/tests/ii/strings/reference.cc
index 54d6efc..ec67b8c 100644
--- a/tests/ii/strings/reference.cc
+++ b/tests/ii/strings/reference.cc
@@ -8,7 +8,10 @@ int main() {
for (int i = 0; i < count; ++i) {
int empty, start, width;
std::string text;
- if (!(std::cin >> empty >> text >> start >> width)) return 1;
+ if (!(std::cin >> empty >> start >> width)) return 1;
+ // The text is the rest of the line, as for INPUT into a STRING.
+ if (!std::getline(std::cin >> std::ws, text)) return 1;
+ if (!text.empty() && text.back() == '\r') text.pop_back();
if (empty) text.clear();
auto lower = text, upper = text;
for (auto &c : lower) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));