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
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