Skip to content

refactor: improve hash implementations for Item, State, and Token#38

Merged
henrylee97 merged 4 commits into
masterfrom
task/t4-hash-token-semantics
May 10, 2026
Merged

refactor: improve hash implementations for Item, State, and Token#38
henrylee97 merged 4 commits into
masterfrom
task/t4-hash-token-semantics

Conversation

@henrylee97

Copy link
Copy Markdown
Member

Summary

  • Item.__hash__: sum-based → tuple-based (hash((self.left, tuple(self.right), self.loc))).
    Fixes an order-insensitivity bug where [A, B] and [B, A] in the RHS produced equal hashes.
  • State.__hash__: sum-based → frozenset-based (hash(frozenset(self.items))),
    consistent with the frozenset[Item] cache key already used by intern_state (T3).
  • Token.__hash__: now includes type(self)hash((type(self), self.lineno, self.offset)).
    The equality contract already incorporates the class via isinstance(other, self.__class__);
    the hash now matches. Added one sentence to the docstring to make this explicit.
    Existing subclass overrides (hash(self.value) + super().__hash__()) remain correct.

Tests

Added tests/test_hash_semantics.py (5 tests):

  • test_item_equal_data_hash_equal — independently constructed equal Items are == and share a hash
  • test_item_different_right_order_hash_different — validates the tuple-based fix
  • test_state_equal_items_hash_equal — equal item sets produce equal State hashes
  • test_token_hash_includes_class — different subclasses at the same position hash differently
  • test_token_same_class_same_position_equal — regression: same class + position → equal

Result

29 passed, 2 xfailed — pyright clean, black/isort unchanged.

@henrylee97 henrylee97 self-assigned this May 10, 2026
@henrylee97 henrylee97 added bug Something isn't working enhancement New feature or request labels May 10, 2026
@github-actions

Copy link
Copy Markdown

Pytest Report

Test Results

  • Tests: 31
  • Errors: 0
  • Failures: 0
  • Skipped: 2

Comment by ✨sambyeol/publish-pytest-action

@github-actions

Copy link
Copy Markdown

Pytest Report

Test Results

  • Tests: 31
  • Errors: 0
  • Failures: 0
  • Skipped: 2

Comment by ✨sambyeol/publish-pytest-action

@henrylee97
henrylee97 enabled auto-merge (squash) May 10, 2026 16:01
@github-actions

Copy link
Copy Markdown

Super-linter summary

Language Validation result
PYTHON_BLACK Pass ✅
PYTHON_ISORT Pass ✅
YAML Pass ✅

All files and directories linted successfully

For more information, see the GitHub Actions workflow run

Powered by Super-linter

@henrylee97
henrylee97 merged commit e72444e into master May 10, 2026
7 checks passed
@henrylee97
henrylee97 deleted the task/t4-hash-token-semantics branch May 10, 2026 16:02
@henrylee97 henrylee97 mentioned this pull request May 11, 2026
2 tasks
henrylee97 added a commit that referenced this pull request May 11, 2026
## Summary

- Fix hash semantics for `Item`, `State`, and `Token` to be value-based
and class-aware
- Replace recursive FIRST/FOLLOW computation with worklist fixed-point
algorithms, fixing incorrect results on mutually recursive grammars
- Make LR(0) state construction deterministic across repeated `Parser`
instantiations
- Add English docstrings and SLR(1) algorithm comments throughout the
codebase
- Expand test coverage with 4 new test modules (safety-net,
FIRST/FOLLOW, determinism, hash semantics)

## Changes

### Bug Fixes
- Correct hash implementations for `Item`, `State`, `Token` (#38)
- Fixed-point FIRST / FOLLOW computation replacing re-entry-guard
recursion (#36)

### Improvements
- Deterministic LR(0) state construction (#37)

### Documentation
- English docstrings and SLR(1) inline algorithm comments (#34)

### Tests
- Parser safety-net suite, FIRST/FOLLOW unit tests, determinism tests,
hash semantics tests (#35 #36 #37 #38)

### Maintenance
- Bumped GitHub Actions: `actions/checkout` 4→6, `actions/setup-python`
5→6, `sambyeol/publish-pytest-action` 2→4, `super-linter/super-linter`
7→8 (#28 #29 #31 #32 #33)

## Test plan

- [x] `pytest -q` passes (`29 passed, 2 xfailed`)
- [x] `python examples/calc/calc.py examples/calc/data/ex01.calc` prints
`2`

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant