Skip to content

Evaluate range pattern conditions lazily - #540

Merged
bertysentry merged 2 commits into
mainfrom
fix/115-lazy-range-pattern-conditions
Jul 31, 2026
Merged

Evaluate range pattern conditions lazily#540
bertysentry merged 2 commits into
mainfrom
fix/115-lazy-range-pattern-conditions

Conversation

@bertysentry

Copy link
Copy Markdown
Contributor

Fixes #115

Problem

Range patterns (begpat, endpat) evaluated both conditions on every record, which produces wrong results when the conditions have side effects:

a++ == 2, a++ == 5

on input 1..10 printed 2 3 instead of 3 4 5.

Fix

ConditionPairAst now compiles to conditional jumps so that:

  • the start condition is evaluated only while outside the range;
  • the end condition is evaluated only once the range has started — including on the very record that starts it, so a range can still begin and end on the same record (/b/, /b/ behavior is unchanged).

This is implemented with three new opcodes — CONDITION_PAIR_IN_RANGE, CONDITION_PAIR_ENTER, CONDITION_PAIR_LEAVE — carrying a per-pattern identifier, appended at the end of the Opcode enum to preserve serialized numeric identifiers. The legacy CONDITION_PAIR opcode is kept in the AVM for precompiled tuple streams, and AwkTuples.conditionPair() is deprecated.

Tests

  • The issue's exact reproduction (a++ == 2, a++ == 53 4 5), an end-condition side-effect case, and two independent ranges in one script, all verified against gawk 5.0.
  • Unit tests for the new ConditionPair.isWithin()/enter()/leave() accessors.
  • mvn verify passes: surefire green, checkstyle/PMD/SpotBugs clean.

🤖 Generated with Claude Code

Range patterns (begpat, endpat) used to evaluate both conditions on
every record, which is wrong when the conditions have side effects
(e.g. "a++ == 2, a++ == 5"). Per POSIX, the start condition must be
evaluated only while outside the range, and the end condition only once
the range has started (including on the record that starts it, so a
range can begin and end on the same record).

ConditionPairAst now compiles to conditional jumps around the two
condition expressions, using the new CONDITION_PAIR_IN_RANGE,
CONDITION_PAIR_ENTER and CONDITION_PAIR_LEAVE opcodes, appended at the
end of the Opcode enum to preserve serialized numeric identifiers. The
legacy CONDITION_PAIR opcode remains supported for precompiled tuple
streams.

Fixes #115

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1d1f74a83

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +5327 to +5329
// The start condition is evaluated only while outside the range, and the
// end condition only once the range has started (including on the very
// record that starts it, so a range can begin and end on the same record)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Document lazy range evaluation for users

Because this changes observable AWK output whenever range conditions have side effects, it is an end-user-facing behavior change, but the commit updates neither README.md nor any src/site documentation. Document the corrected range-pattern semantics in both required locations.

AGENTS.md reference: AGENTS.md:L32-L34

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documented in the compatibility page's Detailed Behavior Notes (new "Range patterns" section). README already delegates to that page for detailed behavior notes — it links to https://jawk.io/compatibility.html for exactly this — and its POSIX support claim now simply holds, so no README change is needed.

Comment on lines +52 to +53
@Test
public void testEnterLeave() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route the new test through AwkTestSupport

This newly added test constructs ConditionPair and uses direct JUnit assertions, bypassing the project-required AwkTestSupport setup and assertion flow. Rewrite the coverage using the helper, or rely on the new helper-based integration cases instead.

AGENTS.md reference: AGENTS.md:L23-L26

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the direct-JUnit test; the new AwkTestSupport-based cases in AwkTest#testRanges exercise isWithin()/enter()/leave() through the interpreter.

Add the corrected range-pattern semantics to the compatibility page's
detailed behavior notes (README already links there for behavior
notes), and remove the ConditionPair accessor unit test in favor of the
AwkTestSupport-based integration coverage in AwkTest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bertysentry

Copy link
Copy Markdown
Contributor Author

@codex please review again

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 99ea772c51

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@bertysentry
bertysentry merged commit 1a52aff into main Jul 31, 2026
5 checks passed
@bertysentry
bertysentry deleted the fix/115-lazy-range-pattern-conditions branch July 31, 2026 13:34
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.

Range patterns must not evaluate endpat until the range starts matching

1 participant