boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

commit ff130e4a25e02fe7231bf399779b0bcf38d2903b
parent 5e19b52523881a930b8d0464a769727677be950e
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sun, 26 Apr 2026 22:46:28 -0700

cc/parse: multi-dim arrays via right-to-left suffix wrap (§D.6)

parse-decl-suf-cont was applying [N]/(...) suffixes left-to-right
(outermost first), so `int a[2][3]` produced `arr (arr int 2) 3`
(outer dim 3, inner 2) — the opposite of C's spiral rule. Same
issue with chained fn suffixes.

Fix: in the recursive form, build the inner result first then wrap
this level — `(%mk-arr (r b) ln)` rather than `(r (%mk-arr b ln))`.
Same shape change in the fn arm. Now `int a[2][3]` is `arr (arr int 3) 2`
as expected, and §D.5's decay+pointer-arithmetic path produces the
right element address for `a[i][j]`.

Lock with cc-parse/41-array-2d.c: int a[2][3] with distinct values
0..2/10..12 in each row sums to 36; a stride bug yields a different
sum.

Diffstat:
Mcc/parse.scm | 9+++++++--
Mdocs/CC-PUNCHLIST.md | 10+++++++---
Atests/cc-parse/41-array-2d.c | 17+++++++++++++++++
Atests/cc-parse/41-array-2d.expected-exit | 1+
4 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/cc/parse.scm b/cc/parse.scm @@ -263,6 +263,11 @@ (cons #f (lambda (b k) (k #f (s b)))))))) (define (parse-decl-suf-cont ps) + ;; C declarator suffixes apply RIGHT-TO-LEFT (innermost first): + ;; int a[2][3] ⇒ arr (arr int 3) 2 (outer dim 2) + ;; not arr (arr int 2) 3 (which would treat the leftmost suffix as + ;; outermost). The recursive structure builds the inner suffix's + ;; result first, then this level wraps. (cond ((at-punct? ps 'lbrack) (advance ps) @@ -270,14 +275,14 @@ (else (parse-const-int ps)))) (_ (expect-punct ps 'rbrack)) (r (parse-decl-suf-cont ps))) - (lambda (b) (r (%mk-arr b ln))))) + (lambda (b) (%mk-arr (r b) ln)))) ((at-punct? ps 'lparen) (advance ps) (let* ((res (parse-fn-params ps)) (p (car res)) (v (cdr res))) (expect-punct ps 'rparen) (let ((r (parse-decl-suf-cont ps))) - (lambda (b) (r (%mk-fn b p v)))))) + (lambda (b) (%mk-fn (r b) p v))))) (else (lambda (b) b)))) (define (paren-is-group? ps) diff --git a/docs/CC-PUNCHLIST.md b/docs/CC-PUNCHLIST.md @@ -186,9 +186,13 @@ broken. Pick one fix and document it in lval. cg-take-addr on an arr lval was also adjusted to yield T* (not (T[N])*) so `&a[0]` stays consistent. -- [ ] **Multi-dim arrays** - - parse: `cc-parse/NN-array-2d.c` - - Needs: derived `arr (arr T N) M`; verify size/align/decay. +- [x] **Multi-dim arrays** + - parse: `cc-parse/41-array-2d.c` + - Done: fixed `parse-decl-suf-cont` to apply suffixes + right-to-left (innermost first) so `int a[2][3]` produces + `arr (arr int 3) 2`, not `arr (arr int 2) 3`. Same fix in the + fn-suffix arm so `T (...)(...)` chains compose correctly. Decay + + ptr arithmetic from §D.5 then handles the rest. - [ ] **Struct passed by pointer to a function** - parse: `cc-parse/NN-struct-fn-arg.c` — passes `&s`. diff --git a/tests/cc-parse/41-array-2d.c b/tests/cc-parse/41-array-2d.c @@ -0,0 +1,17 @@ +// tests/cc-parse/41-array-2d.c — multi-dim array indexing (§D.6 of +// docs/CC-PUNCHLIST.md). int a[2][3]; row-major, so &a[1][2] is at +// byte offset (1*3 + 2)*4 = 20 from a's base. We write distinct +// values into a[0][0]..a[1][2] and read them back via a known sum. +// +// Sum is 0 + 1 + 2 + 10 + 11 + 12 = 36. + +int main() { + int a[2][3]; + a[0][0] = 0; + a[0][1] = 1; + a[0][2] = 2; + a[1][0] = 10; + a[1][1] = 11; + a[1][2] = 12; + return a[0][0] + a[0][1] + a[0][2] + a[1][0] + a[1][1] + a[1][2]; +} diff --git a/tests/cc-parse/41-array-2d.expected-exit b/tests/cc-parse/41-array-2d.expected-exit @@ -0,0 +1 @@ +36