feat: implement PHP clone — parser, checker, EIR shallow object copy#472
Open
chadmandoo wants to merge 1 commit into
Open
feat: implement PHP clone — parser, checker, EIR shallow object copy#472chadmandoo wants to merge 1 commit into
chadmandoo wants to merge 1 commit into
Conversation
`clone $expr` was rejected at parse ("Expected ';'"). Implement it
end-to-end:
- PARSER: contextual recognition — an identifier spelled `clone` in
prefix position followed by an operand-start token (variable/$this/
name/new/self/static/parent/paren) parses as a unary operator at the
other prefix operators' binding power. `clone` stays fully usable as
a method name; `clone($x)` lands on the operator like PHP.
- AST: ExprKind::Clone(Box<Expr>) + arms across every expression walker
(resolver, optimizer fold/prune/propagate/effects, preludes, usage
collectors, magic-constants, parser dependency walks). Effects mirror
NewObject (allocation, may-throw).
- CHECKER: operand must be a statically-typed object; the result is the
same class. Classes declaring __clone() are rejected ("__clone()
hooks are not supported yet") rather than silently skipping the hook.
- EIR: Op::ObjectCloneShallow (operand: source object, immediate: class
name) → backend allocates a same-class payload (heap kind 4, class-id
word) and copies every 8-byte word of the statically-sized payload.
Reference-property slots copy their CELL POINTER — PHP semantics (a
reference property stays shared). Dynamic-properties classes are
rejected (a payload copy would share the dynamic-prop hash).
The frozen legacy backend marks Clone unreachable (EIR-only).
Byte-parity vs PHP 8.5: the PSR-7 withX() round-trip (original
untouched, clone mutated, object slot shared) and the contextual-keyword
probes. Full suite 6184 passed / 1 env-only failure. AIC EC-7 (illegalstudio#490):
ward-http Message/Request/Response/ServerRequest/Uri/RequestBehavior all
parse past clone (next gaps: interface covariant returns, EC-10).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 8485e9e)
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>
chadmandoo
added a commit
to chadmandoo/elephc
that referenced
this pull request
Jul 10, 2026
…opy (R9/#599, illegalstudio#472) v0.26.1's parser rejected `clone $x` ("Expected ';'"), gapping every PSR-7 immutability wither (Message/Uri/RequestBehavior `$new = clone $this`). Re-ports illegalstudio#472 (8485e9e) onto the post-EIR-refactor tree: - PARSER: contextual `clone <expr>` prefix operator (clone is not a reserved token — `clone_operand_follows` guards it so a bare identifier spelled "clone" in a non-operator position still parses as a name). New ExprKind::Clone(Box<Expr>). - CHECKER: `clone $x` infers as the type of `$x`. - EIR: shallow object/array copy lowering (array_clone_shallow, x86 frame-safe). - The new AST variant is threaded through every ExprKind match (name resolver, optimizer passes, magic-constant walker, usage/invalidation analysis, warnings). The legacy backend is gone in v0.26.1, so no legacy emit arm is needed. clone codegen tests pass (round-trip + contextual-keyword). Survey 90% → 91% (277 → 278/307); the "Expected ';'" gaps (Message ×4, Uri, RequestBehavior) clear. Also completes R6's deferred illegalstudio#472. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements
clone $exprend-to-end:clonein prefix position followed by an operand-start token parses as a unary operator;clonestays fully usable as a method name andclone($x)lands on the operator like PHP.ExprKind::Clonewith arms across every expression walker (resolver, optimizer passes, preludes, usage collectors, parser dependency walks); effects mirrorObjectNew.__clone()are rejected explicitly ("__clone() hooks are not supported yet") rather than silently skipping the hook.Op::ObjectCloneShallow— the backend allocates a same-class payload (heap-kind stamp + class-id word) and copies the statically-sized payload wordwise. Reference-property slots copy their CELL POINTER, matching PHP (a reference property stays shared with the original); dynamic-properties classes are rejected (a payload copy would share the dynamic-prop hash).Byte-parity vs PHP 8.5: the PSR-7
withX()immutability round-trip (original untouched, clone mutated, object slot shared) and contextual-keyword probes. 2 regression tests.