Skip to content

plawk: array element reads in END (arrays PR 3c) - #4355

Draft
s243a wants to merge 2 commits into
claude/plawk-llvm-wam-hybrid-p9ujutfrom
claude/plawk-llvm-wam-hybrid-p9ujut-array-reads-3c
Draft

s243a wants to merge 2 commits into
claude/plawk-llvm-wam-hybrid-p9ujutfrom
claude/plawk-llvm-wam-hybrid-p9ujut-array-reads-3c

Conversation

@s243a

@s243a s243a commented Oct 6, 2026

Copy link
Copy Markdown
Owner

Arrays PR 3c (docs/design/PLAWK_ARRAY_VALUE_MODEL.md §8, item 3c).

Base: the feature line, not stacked. Until #4354 (3b) merges, this PR's diff also shows 3b's commit a95163dc3; after that it shows only 3c. Merging #4354 first is cleaner, but either order lands everything on the feature line.

What (matching gawk)

program before
END { for (k in c) if (c[k] > 1) print k } (braceless) parse error
END { for (k in c) print k, c[k] * 2 }, c[k] / 4, c[k] + d[k] exit 3
END { print c["a"] + c["b"] }, print c[5] + c[7] exit 3
END { for (k in c) print k, c[k]; print "total", c["a"] + c["b"] + c["c"] } exit 3
  • Braceless guard: for (k in c) if (G) print … now parses to the same term as the braced form, which already lowered. A braceless for (k in c) printf … now parses too, but its codegen is still open, so it declines.
  • Arithmetic print fields in a for-in: the iterated table is read by its slot (value_at), any other table by the loop key (get, absent → 0). The reads become ssa leaves, and the value prints the awk way: an integer, or %g with floating-point division.
  • END literal-key arithmetic: the key bytes go through a stack buffer stored from an inline c"…" constant, because this route's line stream has no global channel. The names carry end_, so the statement-list renaming keeps them unique. plawk_assoc_print_array/2 now reports the arrays inside such a field.
  • Refactor: END's numeric printer is factored into plawk_numeric_print_lines/6, which takes the names as parameters; the existing names are unchanged (corpus-verified).
  • Counter tables only. Double tables and an END scalar if over an element decline.

Verification

  • IR corpus: ir_corpus.pl dump + diff vs the 3b commit over all 2602 programs: 1 changed, the intended decline → compiled END { print c["a"] + c["b"] }. It moved from 3b's decline list into the new tests.
  • Tests: tests/test_plawk_array_reads.pl, now 15; all expected outputs are gawk 5.1.0's.
  • plawk sweep: 224/224.

Still open (3d)

  • an END scalar if over an element;
  • scalar state inside an END for-in (the max idiom if (c[k] > max) { max = c[k]; mk = k });
  • for-in printf bodies;
  • guards combining && or key comparisons;
  • double-table reads.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QrQistdoYMNpVtecwims6g

s243a and others added 2 commits October 4, 2026 23:48
`n = c[$1] * 10`, `t += c[$1]`, `print c[$1] * 2, n` declined, and `t += c[$1]`
was a parse error. In the mixed walker an element read whose parent is binary
arithmetic -- or the right side of a scalar `+=` / `-=` -- is now read before
the action and replaced by an ssa(Ref) leaf (plawk_arith_elem_reads/12, reusing
the condition reader: counter tables only, key interned as the writes intern
it, absent -> 0). The rewritten action lowers through the existing emitters;
admission takes the element and its ssa leaf as operands of scalar update
expressions and print arithmetic. A bare copy (`n = c[$1]`) still declines
(the element may be unset, spec section 3).

A scalar used as an element KEY is never an unsafe strnum read (every key path
uses the slot's atom id), so plawk_strnum_term_mentions/2 skips it -- otherwise
`k = $1; c[k]++; n = c[k] * 2; print k` printed 0 for k (caught against gawk).

Verified: ir_corpus diff over all 2591 programs: 0 changed (purely additive).
tests/test_plawk_array_reads.pl: 11 (5 new); expected outputs are gawk 5.1.0's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrQistdoYMNpVtecwims6g
- `for (k in c) if (c[k] > 1) print k` -- the usual braceless spelling -- was a
  parse error; it now parses to the same term as the braced form, which already
  lowered. A braceless `for (k in c) printf ...` parses too (its codegen is
  still open, so it declines).
- Arithmetic print fields over loop-keyed elements: `print k, c[k] * 2`,
  `c[k] / 4`, `c[k] + d[k]`. The iterated table is read by its slot
  (value_at), any other by the loop key (get, absent -> 0), substituted as
  ssa leaves and printed the awk way (integer, or %g with fdiv).
- END arithmetic over literal-key elements: `print c["a"] + c["b"]`,
  `print c[5] + c[7]`, also after a for-in in a statement list. The key bytes
  go through a stack buffer stored from an inline c"..." constant (this route
  has no global channel); names carry `end_` so the statement-list rename keeps
  them unique. plawk_assoc_print_array/2 reports the arrays inside such a field.
- END's numeric printer is factored into plawk_numeric_print_lines/6 (names as
  parameters; existing names unchanged).
Counter tables only; double tables and an END scalar `if` over an element
decline.

Verified: ir_corpus diff vs the 3b commit over all 2602 programs: 1 changed,
the intended decline -> compiled `END { print c["a"] + c["b"] }` (moved from
3b's decline list to the new tests). tests/test_plawk_array_reads.pl: 15;
expected outputs are gawk 5.1.0's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrQistdoYMNpVtecwims6g

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant