Skip to content

fix: keyword-spelled member names — declarations and case-insensitive access#469

Open
chadmandoo wants to merge 1 commit into
illegalstudio:mainfrom
chadmandoo:upstream-pr/keyword-member-names
Open

fix: keyword-spelled member names — declarations and case-insensitive access#469
chadmandoo wants to merge 1 commit into
illegalstudio:mainfrom
chadmandoo:upstream-pr/keyword-member-names

Conversation

@chadmandoo

Copy link
Copy Markdown
Contributor

Three commits making keyword-spelled members work end-to-end. The lexer folds keywords case-insensitively, so a member named like a keyword loses its source lexeme: (1) semi-reserved keywords are accepted as enum-case NAMES (case Match;, case Default;); (2) the two ::-member parse sites stop guessing spellings (a hardcoded Token::Match => "MATCH" disagreed with the lowercase bareword mapping) and the checker's scoped-constant lookup retries case-insensitively after an exact miss, accepting a UNIQUE fold-match (ambiguity keeps the miss; genuinely undefined cases still error); (3) the LOWERING's scoped_constant_value/interface_constant_value mirror the same retry (builtin tables declare e.g. RegexIterator::MATCH uppercase — pinned by the existing spl regex tests).

Byte-parity vs PHP 8.5 (case values + identifier-named-case ->name). Known documented limit: ->name of a KEYWORD-named case reports the folded spelling — recovering the source lexeme needs spelling-preserving keyword tokens.

chadmandoo added a commit to chadmandoo/elephc that referenced this pull request Jul 10, 2026
….1 (R6/#595)

Three v0.26.0 enum/parser fixes, survey-driven (79% → 85%, 241 → 262/307):

- ENUM-CASE PARAM DEFAULT (illegalstudio#468, declarations.rs): `E $x = E::Case` — an
  enum-case default has the enum object type, but syntactic inference types
  every `::` access as Str. When the declared type is Object(E) and the
  default is a scoped access naming E, accept it (the semantic pass validates
  the case exists). Clears the Badge/Button `$variant expects Object, got Str`
  family (9).
- KEYWORD ENUM-CASE NAMES (body.rs): PHP 8 allows semi-reserved keywords as
  enum-case names (`case Default;`, `case String;`, `case Float;`) — every one
  but `class` (reserved for `Foo::class`). Clears CardVariant/LogicalType/
  HeadAssetMode `Expected case name after 'case'` (10).
- USE CONST/FUNCTION IMPORTS (illegalstudio#473/EC-10/illegalstudio#493, namespace_use.rs): the lexer
  eagerly tokenizes `PHP_INT_MAX` etc., so the use-declaration parser must
  accept those dedicated tokens as import names (`use const PHP_INT_MAX;`).
  Clears RegionEntry `Expected imported name after 'use'` (2).

Deferred (not survey-visible on v0.26.1): illegalstudio#469 keyword-case access, illegalstudio#472 clone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… access

PHP 8 permits reserved keywords as enum-case names (`case Default;`,
`case Print;`, `case List;`) and semi-reserved keywords as class-constant
and enum-case member names, under the same rule that already applies to
method names and `->` member access. Three fixes:

- Enum-case name parsing accepts barewords via the shared
  `bareword_name_from_token` helper (as class-constant names already do),
  and rejects `class` (reserved for the `Foo::class` fetch) with a
  dedicated diagnostic.
- Keyword-named member ACCESS resolves case-insensitively: the lexer folds
  keyword spellings, so `case Match` is declared as "match" while a builtin
  table may declare "MATCH". Drop the `Token::Match => "MATCH"` special
  cases and make the scoped-constant lookup retry case-insensitively after
  an exact miss, accepting a UNIQUE fold-match. PHP is case-sensitive here;
  the retry only fires for spellings the lexer already erased, and an
  ambiguous fold keeps the miss.
- The same unique fold fallback is mirrored in the lowering's own
  scoped-constant resolution (`scoped_constant_value` /
  `interface_constant_value`) so `RegexIterator::MATCH` resolves.

Byte-parity vs PHP 8.5 (values + identifier-named `->name`). Known limit:
`->name` of a KEYWORD-named case reports the folded spelling — recovering
the source lexeme needs spelling-preserving keyword tokens (follow-up).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chadmandoo
chadmandoo force-pushed the upstream-pr/keyword-member-names branch from bb154fb to 5601607 Compare July 11, 2026 14:10
@github-actions github-actions Bot added area:eir Touches EIR definitions, lowering, validation, or passes. area:parser Touches parsing or AST construction. area:types Touches type checking, inference, or compatibility. size:s Small pull request. type:fix Corrects broken or incompatible behavior. labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:eir Touches EIR definitions, lowering, validation, or passes. area:parser Touches parsing or AST construction. area:types Touches type checking, inference, or compatibility. size:s Small pull request. type:fix Corrects broken or incompatible behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant