Skip to content

Instantly share code, notes, and snippets.

@thekid
Last active December 28, 2025 12:12
Show Gist options
  • Select an option

  • Save thekid/773803d84b357799ffd65f855bc0181c to your computer and use it in GitHub Desktop.

Select an option

Save thekid/773803d84b357799ffd65f855bc0181c to your computer and use it in GitHub Desktop.
Is operator array structure support for ArrayAccess
diff --git a/src/main/php/lang/ast/syntax/php/IsOperator.class.php b/src/main/php/lang/ast/syntax/php/IsOperator.class.php
index 30832b5..bb1048e 100755
--- a/src/main/php/lang/ast/syntax/php/IsOperator.class.php
+++ b/src/main/php/lang/ast/syntax/php/IsOperator.class.php
@@ -250,24 +250,29 @@ class IsOperator implements Extension {
}
return $compound;
} else if ($pattern instanceof IsArrayStructure) {
- $compound= new BinaryExpression(
- new InvokeExpression(new Literal('is_array'), [$init]),
- '&&',
- new BinaryExpression(
- new InvokeExpression(new Literal('sizeof'), [$use]),
- $pattern->rest ? '>=' : '===',
- new Literal((string)sizeof($pattern->patterns))
- )
+ $size= new BinaryExpression(
+ new InvokeExpression(new Literal('sizeof'), [$use]),
+ $pattern->rest ? '>=' : '===',
+ new Literal((string)sizeof($pattern->patterns))
);
+ $arrays= new BinaryExpression(new InvokeExpression(new Literal('is_array'), [$init]), '&&', $size);
+ $objects= new BinaryExpression(new InstanceOfExpression($init, new IsValue('ArrayAccess')), '&&', $size);
+
foreach ($pattern->patterns as $key => $p) {
$offset= new Literal((string)$key);
- $compound= new BinaryExpression($compound, '&&', new BinaryExpression(
+ $apply= $match($codegen, new OffsetExpression($use, $offset), $p);
+ $arrays= new BinaryExpression($arrays, '&&', new BinaryExpression(
new InvokeExpression(new Literal('array_key_exists'), [$offset, $use]),
'&&',
- $match($codegen, new OffsetExpression($use, $offset), $p),
+ $apply,
+ ));
+ $objects= new BinaryExpression($objects, '&&', new BinaryExpression(
+ new InvokeExpression(new InstanceExpression($use, new Literal('offsetExists')), [$offset]),
+ '&&',
+ $apply,
));
}
- return $compound;
+ return new Braced(new BinaryExpression($arrays, '||', $objects));
}
// Should be unreachable
diff --git a/src/test/php/lang/ast/syntax/php/unittest/ArrayStructureTest.class.php b/src/test/php/lang/ast/syntax/php/unittest/ArrayStructureTest.class.php
index 32c1603..2454ebe 100755
--- a/src/test/php/lang/ast/syntax/php/unittest/ArrayStructureTest.class.php
+++ b/src/test/php/lang/ast/syntax/php/unittest/ArrayStructureTest.class.php
@@ -63,4 +63,24 @@ class ArrayStructureTest extends EmittingTest {
}
}'));
}
+
+ #[Test, Values(['$this', 'new ArrayObject([1, 2, 3])'])]
+ public function integrates_with_array_access($expr) {
+ Assert::equals([1, 2, 3], $this->run('class %T implements ArrayAccess, Countable {
+
+ public function count() { return 3; }
+
+ public function offsetExists($i) { return true; }
+
+ public function offsetGet($i) { return $i + 1; }
+
+ public function offsetSet($i, $value) { /* NOOP */ }
+
+ public function offsetUnset($i) { /* NOOP */ }
+
+ public function run() {
+ return '.$expr.' is [$a, $b, $c] ? [$a, $b, $c] : null;
+ }
+ }'));
+ }
}
\ No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment