Skip to content

Add ?. and ?[ optional-access operators#22

Merged
myzie merged 1 commit into
mainfrom
optional-access
May 8, 2026
Merged

Add ?. and ?[ optional-access operators#22
myzie merged 1 commit into
mainfrom
optional-access

Conversation

@myzie
Copy link
Copy Markdown
Contributor

@myzie myzie commented May 8, 2026

What

  • Add internal/optaccess: a token-level pre-parse rewrite that turns obj?.field into __try_select__(obj, "field") and obj?[i] into __try_index__(obj, i). The walker matches balanced parens/brackets and treats earlier ? tokens as continuation links so chained a?.b?.c rewrites cleanly. Strings, runes, and comments are not touched.
  • Wire optaccess into the Compile pipeline ahead of jsonlit and preprocessSource, so ?[1] can carry the inner index expression through unmolested.
  • Register sentinel forms __try_select__ / __try_index__ in higher_order.go. Each form short-circuits on a nil receiver and treats missing-key / out-of-range as nil; wrong-kind type errors still surface as ErrEvaluate.
  • Add language-level tests in optional_access_test.go (chained selects, fallback via ||, predicates, type-error propagation, string-literal preservation) plus unit + fuzz tests in internal/optaccess.
  • Add fuzz seeds covering ?. and ?[ to FuzzCompile / FuzzEval.
  • Update spec.md, llms.txt, and the higher-order-patterns and examples guides (plus their matching test) to use find(...)?.x instead of the unsafe find(...).x.

Why

?. plus operand-returning || plus try covers the same use cases as ?? without needing precedence-aware token rewriting. The rewrite layer mirrors internal/jsonlit so the disambiguation logic stays simple and reasons about tokens, not strings.

Test plan

  • go test ./...
  • go test -race ./...
  • go test -run=^$ -fuzz=FuzzCompile -fuzztime=20s .
  • go test -run=^$ -fuzz=FuzzEval -fuzztime=20s .
  • go test -run=^$ -fuzz=FuzzRewrite -fuzztime=20s ./internal/optaccess/

What:
- Add internal/optaccess: a token-level pre-parse rewrite that
  turns `obj?.field` into `__try_select__(obj, "field")` and
  `obj?[i]` into `__try_index__(obj, i)`. The walker matches
  balanced parens/brackets and treats earlier `?` tokens as
  continuation links so chained `a?.b?.c` rewrites cleanly.
  Strings, runes, and comments are not touched.
- Wire optaccess into the Compile pipeline ahead of jsonlit and
  preprocessSource, so `?[1]` can carry the inner index expression
  through unmolested.
- Register sentinel forms `__try_select__` / `__try_index__` in
  higher_order.go alongside the other special forms. Each form
  short-circuits on a nil receiver and treats missing-key /
  out-of-range as nil; wrong-kind type errors still surface.
- Add language-level tests in optional_access_test.go (chained
  selects, fallback via ||, predicates, type-error propagation,
  string-literal preservation) and unit + fuzz tests in
  internal/optaccess.
- Add fuzz seeds covering `?.` and `?[` to FuzzCompile / FuzzEval.
- Update spec.md, llms.txt, and the higher-order-patterns and
  examples guides (plus their matching test) to use `find(...)?.x`
  instead of the unsafe `find(...).x`.

Why:
- `?.` plus operand-returning `||` plus `try` covers the same use
  cases as `??` without needing precedence-aware token rewriting.
- The rewrite layer mirrors internal/jsonlit so the disambiguation
  logic stays simple and is reasoning about tokens, not strings.
@myzie myzie force-pushed the optional-access branch from ecf1d14 to 2dfb9c8 Compare May 8, 2026 15:14
@myzie myzie merged commit 755d4db into main May 8, 2026
1 check passed
@myzie myzie deleted the optional-access branch May 8, 2026 15:15
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