Summary
The parser (php-zephir-parser) now supports destructuring assignment syntax:
let [a, b, c] = arr;
let [a, , c] = arr; // skip slots
See: zephir-lang/php-zephir-parser#186 (closes zephir-lang/php-zephir-parser#18)
The compiler needs a corresponding handler to translate this AST node into C code.
AST Shape
The parser emits the following AST node inside a let statement's assignments array:
{
"assign-type": "destructure",
"operator": "assign",
"variables": [
{ "type": "variable", "value": "a", "file": "...", "line": 1, "char": 1 },
{ "type": "variable", "value": "b", "file": "...", "line": 1, "char": 1 },
{ "type": "variable", "value": "c", "file": "...", "line": 1, "char": 1 }
],
"expr": { "type": "variable", "value": "arr", ... },
"file": "...",
"line": 1,
"char": 1
}
variables is a flat array of variable name objects (type "variable", with a "value" key holding the name string)
- Skipped slots (
let [a, , c] = arr;) have null entries in the variables array
expr is the right-hand side expression (any valid xx_assign_expr)
Required Compiler Changes
1. src/Statements/LetStatement.php
Add 'destructure' to the match expression (line ~45) so the symbol table lookup doesn't crash:
$symbolVariable = match ($assignment['assign-type']) {
// ...existing cases...
'destructure' => null, // handled specially below
// ...
};
The destructure case needs special handling: iterate $assignment['variables'], skip null entries, and for each variable name call $compilationContext->symbolTable->getVariableForWrite(...).
2. src/Statements/Let/AssignmentFactory.php
Add 'destructure' to the ASSIGNMENT_MAP:
private const ASSIGNMENT_MAP = [
// ...existing entries...
'destructure' => Destructure::class,
];
And add a case to the switch in process():
case 'destructure':
$handler->assign($assignment, $resolvedExpr, $compilationContext);
break;
3. New src/Statements/Let/Destructure.php
Create a new handler class that generates C code equivalent to indexed array fetches:
Should generate C equivalent to:
zephir_array_fetch_long(&a, arr, 0, PH_NOISY_CC);
zephir_array_fetch_long(&b, arr, 1, PH_NOISY_CC);
zephir_array_fetch_long(&c, arr, 2, PH_NOISY_CC);
For skipped slots (null in the variables array), simply skip that index.
The handler should:
- Compile the RHS expression once into a temp variable
- Iterate the
variables array with index
- For each non-null entry, emit a
zephir_array_fetch_long() call using the index
- Handle type coercion based on the target variable's declared type
4. src/Passes/LocalContextPass.php and src/Passes/SkipVariantInit.php
These passes inspect assign-type for optimization. Add 'destructure' handling so the passes don't skip or mishandle destructured variables.
Out of Scope
- Nested destructuring (
let [[a, b], c] = arr;) — not supported by the parser
- Keyed/object destructuring (
let {key1, key2} = obj;) — not supported by the parser
- These can be added incrementally in follow-up PRs
Related
Summary
The parser (
php-zephir-parser) now supports destructuring assignment syntax:See: zephir-lang/php-zephir-parser#186 (closes zephir-lang/php-zephir-parser#18)
The compiler needs a corresponding handler to translate this AST node into C code.
AST Shape
The parser emits the following AST node inside a
letstatement'sassignmentsarray:{ "assign-type": "destructure", "operator": "assign", "variables": [ { "type": "variable", "value": "a", "file": "...", "line": 1, "char": 1 }, { "type": "variable", "value": "b", "file": "...", "line": 1, "char": 1 }, { "type": "variable", "value": "c", "file": "...", "line": 1, "char": 1 } ], "expr": { "type": "variable", "value": "arr", ... }, "file": "...", "line": 1, "char": 1 }variablesis a flat array of variable name objects (type"variable", with a"value"key holding the name string)let [a, , c] = arr;) havenullentries in thevariablesarrayexpris the right-hand side expression (any validxx_assign_expr)Required Compiler Changes
1.
src/Statements/LetStatement.phpAdd
'destructure'to thematchexpression (line ~45) so the symbol table lookup doesn't crash:The destructure case needs special handling: iterate
$assignment['variables'], skip null entries, and for each variable name call$compilationContext->symbolTable->getVariableForWrite(...).2.
src/Statements/Let/AssignmentFactory.phpAdd
'destructure'to theASSIGNMENT_MAP:And add a case to the
switchinprocess():3. New
src/Statements/Let/Destructure.phpCreate a new handler class that generates C code equivalent to indexed array fetches:
Should generate C equivalent to:
For skipped slots (
nullin the variables array), simply skip that index.The handler should:
variablesarray with indexzephir_array_fetch_long()call using the index4.
src/Passes/LocalContextPass.phpandsrc/Passes/SkipVariantInit.phpThese passes inspect
assign-typefor optimization. Add'destructure'handling so the passes don't skip or mishandle destructured variables.Out of Scope
let [[a, b], c] = arr;) — not supported by the parserlet {key1, key2} = obj;) — not supported by the parserRelated
let [a, b, c] = expr) php-zephir-parser#186