diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-22 13:59:48 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-22 13:59:48 +0000 |
| commit | f694cc443ccc17a494cd195151882ab5e491bbb2 (patch) | |
| tree | 4a74ec68a1406073c5d70d8a0a71b5d839e0c3ef /tests | |
| parent | 312a19c781da1c31ff1e3dc71c319663a8be9148 (diff) | |
feat(codegen): accept ^x of C values as variadic arguments
In a variadic EXTERN position, ^x now passes the address of x as a plain
pointer when x has a C type or is a C struct, like C's f(n, &x). The
address of a pseudocode-typed value keeps the "must be a C value" error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/i/extern-c-struct/expected.txt | 1 | ||||
| -rw-r--r-- | tests/i/extern-c-struct/notes.md | 2 | ||||
| -rw-r--r-- | tests/i/extern-c-struct/program.cps | 1 | ||||
| -rw-r--r-- | tests/iii/extern-variadic-type/case.json | 4 | ||||
| -rw-r--r-- | tests/iii/extern-variadic-type/notes.md | 4 | ||||
| -rw-r--r-- | tests/iii/extern-variadic-type/program.cps | 2 |
6 files changed, 11 insertions, 3 deletions
diff --git a/tests/i/extern-c-struct/expected.txt b/tests/i/extern-c-struct/expected.txt index 816b4e3..04931ae 100644 --- a/tests/i/extern-c-struct/expected.txt +++ b/tests/i/extern-c-struct/expected.txt @@ -4,3 +4,4 @@ G 0.500000 7 14 3 G 9 +14 diff --git a/tests/i/extern-c-struct/notes.md b/tests/i/extern-c-struct/notes.md index 494c510..b32bcc1 100644 --- a/tests/i/extern-c-struct/notes.md +++ b/tests/i/extern-c-struct/notes.md @@ -4,4 +4,4 @@ Human review: pending. Expected output was independently traced by AI, not captu Basis: compiler extension (EXTERN "C", INCLUDE_OBJ of a user object); a record whose fields are all C types has the layout of the matching C struct. -Trace: the harness compiles `lib.c` with the host C compiler. Sample matches `struct Sample {char; double; int}`, including the padding after the char. S is 'S', 1.5, 5. scale_sample(^S, 3) multiplies the value through the pointer to 4.5 and leaves tag and count alone, so the first line is `S 4.500000 5`. shared_sample returns the address of the static struct in lib.c, initialised to 'G', 0.5, 7, giving `G 0.500000 7`. P^.Count <- 9 writes through that pointer into the C object, so shared_count() returns 9. sum_counts receives P and Q as variadic arguments; pointers are passed unchanged and read back with va_arg(ap, struct Sample *). P points to the shared struct, whose count is now 9, and Q points to S, whose count is 5, so the last line is 9 + 5 = 14. N starts at 1. bump(^N) receives a PInt, an int * in C, and increments N to 2. Counter matches `struct Counter {int *}`; bump_counter(^C) increments through C.Target, which points to N, giving 3. get_shared(^R) receives a struct Sample ** and stores the address of the shared struct into R, so R^ shows tag G and the count 9 written earlier: `G 9`. +Trace: the harness compiles `lib.c` with the host C compiler. Sample matches `struct Sample {char; double; int}`, including the padding after the char. S is 'S', 1.5, 5. scale_sample(^S, 3) multiplies the value through the pointer to 4.5 and leaves tag and count alone, so the first line is `S 4.500000 5`. shared_sample returns the address of the static struct in lib.c, initialised to 'G', 0.5, 7, giving `G 0.500000 7`. P^.Count <- 9 writes through that pointer into the C object, so shared_count() returns 9. sum_counts receives P and Q as variadic arguments; pointers are passed unchanged and read back with va_arg(ap, struct Sample *). P points to the shared struct, whose count is now 9, and Q points to S, whose count is 5, so the last line is 9 + 5 = 14. N starts at 1. bump(^N) receives a PInt, an int * in C, and increments N to 2. Counter matches `struct Counter {int *}`; bump_counter(^C) increments through C.Target, which points to N, giving 3. get_shared(^R) receives a struct Sample ** and stores the address of the shared struct into R, so R^ shows tag G and the count 9 written earlier: `G 9`. Finally sum_counts((C_INT)2, ^S, P) passes the address of S directly, like C's `&s`, together with P: 5 + 9 = 14. diff --git a/tests/i/extern-c-struct/program.cps b/tests/i/extern-c-struct/program.cps index 62370d3..210e10d 100644 --- a/tests/i/extern-c-struct/program.cps +++ b/tests/i/extern-c-struct/program.cps @@ -43,3 +43,4 @@ CALL bump_counter(^C) OUTPUT N CALL get_shared(^R) OUTPUT R^.Tag, " ", R^.Count +OUTPUT sum_counts((C_INT)2, ^S, P) diff --git a/tests/iii/extern-variadic-type/case.json b/tests/iii/extern-variadic-type/case.json index 45fea44..a114299 100644 --- a/tests/iii/extern-variadic-type/case.json +++ b/tests/iii/extern-variadic-type/case.json @@ -3,6 +3,10 @@ { "reason": "Variadic\\ argument\\ 2\\ to\\ printf\\ must\\ be\\ a\\ C\\ value", "line": 5 + }, + { + "reason": "Variadic\\ argument\\ 2\\ to\\ printf\\ must\\ be\\ a\\ C\\ value", + "line": 7 } ] } diff --git a/tests/iii/extern-variadic-type/notes.md b/tests/iii/extern-variadic-type/notes.md index 3de1d69..73456b5 100644 --- a/tests/iii/extern-variadic-type/notes.md +++ b/tests/iii/extern-variadic-type/notes.md @@ -1,5 +1,5 @@ # extern-variadic-type -Compiler extension: variadic EXTERN arguments must be C values; the INTEGER literal 1 is not cast. +Compiler extension: variadic EXTERN arguments must be C values; the INTEGER literal 1 is not cast, and ^I points to an INTEGER rather than a C value. -Require exit 1 and the cause on the call line. +Require exit 1 and each cause on its call line. diff --git a/tests/iii/extern-variadic-type/program.cps b/tests/iii/extern-variadic-type/program.cps index 23f1fe9..0a967f3 100644 --- a/tests/iii/extern-variadic-type/program.cps +++ b/tests/iii/extern-variadic-type/program.cps @@ -3,3 +3,5 @@ INCLUDE_OBJ "__libc" EXTERN "C" EXTERN_FUNCTION printf(C_STRING, ...) RETURNS C_INT DECLARE N : C_INT N <- printf((C_STRING)"%d", 1) +DECLARE I : INTEGER +N <- printf((C_STRING)"%p", ^I) |
