Give argument lists their own link, not each argument's .right

An identifier's subscript list, a unary's operand and a binary's right-hand
side all lived in the same field the argument chain used, so ABS(-9),
MOD(A#, B# + 12) and any array reference in a parameter list were counted as
extra arguments and refused. Subscript lists move to .expr and arguments now
chain through a dedicated .next.

This is the third time the same collision was fixed; the first two moved it
along rather than removing it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 11:58:15 -04:00
parent 5b7b7d2ed9
commit f4007d80d4
14 changed files with 133 additions and 55 deletions

View File

@@ -132,6 +132,28 @@ int main(void)
expect_int("A# = SHL(-1, 0)", -1);
expect_int("A# = MOD(-7, 3)", -1);
expect_int("A# = INSTR(\"HELLO\", \"L\")", 2);
/*
* An argument that is itself an expression, and one that is an array
* reference. Both used to be counted as several arguments, because the
* argument chain and the leaves' own `.right` were the same field: a binary
* argument's right-hand side and an identifier's subscript list both looked
* like more arguments. Arguments now chain through `.next`. TODO.md section
* 4, "array references in parameter lists", which turned out to be section 6
* item 13 a second time.
*/
expect_int("A# = MOD(7, 1 + 2)", 1);
expect_int("A# = SHL(1 + 1, 2 + 1)", 16);
expect_int("A# = ABS(0 - 4)", 4);
/*
* Subscript zero rather than a DIM: every scalar is really a one-element
* array, so `N#(0)` is a subscripted reference to an ordinary variable and
* exercises the same parse path a DIMmed array would, without needing one.
*/
TEST_REQUIRE_OK(akbasic_environment_zero(HARNESS_RUNTIME.environment));
expect_int("N#(0) = -9", -9);
expect_int("A# = ABS(N#(0))", 9);
expect_int("A# = MOD(N#(0) + 16, 4)", 3);
expect_int("A# = LEN(\"HELLO\")", 5);
expect_int("A# = SHL(1, 4)", 16);
expect_int("A# = SHR(16, 4)", 1);