Permalink
Please sign in to comment.
Browse files
Allow specifying keys on list() elements
Squashed commit of the following: commit 0361dbe Author: Andrea Faulds <[email protected]> Date: Fri Mar 25 16:59:20 2016 +0000 UPGRADING and NEWS commit dca9d4a Author: Andrea Faulds <[email protected]> Date: Fri Mar 25 16:45:18 2016 +0000 Add tests contributed by @jesseschalken commit e557f77 Author: Andrea Faulds <[email protected]> Date: Fri Mar 25 16:44:51 2016 +0000 Rebuild VM commit 70942e4 Author: Andrea Faulds <[email protected]> Date: Wed Feb 24 13:12:26 2016 +0000 Add test for evaluation order of nested list() keys commit ed3592e Author: Andrea Faulds <[email protected]> Date: Wed Feb 24 12:42:04 2016 +0000 Add test for evaluation order commit 589756c Author: Andrea Faulds <[email protected]> Date: Tue Jan 19 17:29:34 2016 +0000 Allow arbitrary expressions for key commit 3f62207 Author: Andrea Faulds <[email protected]> Date: Tue Jan 19 17:45:10 2016 +0000 Remove compile-time HANDLE_NUMERIC (see bug #63217) commit bab7581 Author: Andrea Faulds <[email protected]> Date: Sun Jan 17 01:20:26 2016 +0000 Handle numeric strings commit 14bfe93 Author: Andrea Faulds <[email protected]> Date: Sun Jan 17 01:09:36 2016 +0000 Allow trailing comma commit f4c8b2c Author: Andrea Faulds <[email protected]> Date: Sat Jan 16 23:47:11 2016 +0000 Add tests commit 0085884 Author: Andrea Faulds <[email protected]> Date: Sat Jan 16 22:24:23 2016 +0000 Handle non-integer/string opcodes commit e572d2d Author: Andrea Faulds <[email protected]> Date: Sat Jan 16 21:10:33 2016 +0000 Disallow mixing keyed and unkeyed list() elements commit cede13c Author: Andrea Faulds <[email protected]> Date: Sun Jan 10 20:46:44 2016 +0000 list() with keys (no foreach or tests)
- Loading branch information...
Showing
with
1,484 additions
and 45 deletions.
- +1 −0 NEWS
- +2 −0 UPGRADING
- +36 −0 Zend/tests/foreach_list_keyed.phpt
- +71 −0 Zend/tests/list_keyed.phpt
- +54 −0 Zend/tests/list_keyed_ArrayAccess.phpt
- +32 −0 Zend/tests/list_keyed_conversions.phpt
- +60 −0 Zend/tests/list_keyed_evaluation_order.inc
- +35 −0 Zend/tests/list_keyed_evaluation_order.phpt
- +77 −0 Zend/tests/list_keyed_evaluation_order_2.phpt
- +24 −0 Zend/tests/list_keyed_evaluation_order_3.phpt
- +77 −0 Zend/tests/list_keyed_evaluation_order_nested.phpt
- +30 −0 Zend/tests/list_keyed_non_literals.phpt
- +38 −0 Zend/tests/list_keyed_trailing_comma.phpt
- +22 −0 Zend/tests/list_keyed_undefined.phpt
- +16 −0 Zend/tests/list_mixed_keyed_unkeyed.phpt
- +34 −0 Zend/tests/list_mixed_nested_keyed_unkeyed.phpt
- +35 −2 Zend/zend_compile.c
- +28 −5 Zend/zend_language_parser.y
- +58 −7 Zend/zend_vm_def.h
- +753 −30 Zend/zend_vm_execute.h
- +1 −1 Zend/zend_vm_opcodes.c
| @@ -0,0 +1,36 @@ | ||
| +--TEST-- | ||
| +foreach with list syntax, keyed | ||
| +--FILE-- | ||
| +<?php | ||
| + | ||
| +$points = [ | ||
| + ["x" => 1, "y" => 2], | ||
| + ["x" => 2, "y" => 1] | ||
| +]; | ||
| + | ||
| +foreach ($points as list("x" => $x, "y" => $y)) { | ||
| + var_dump($x, $y); | ||
| +} | ||
| + | ||
| +echo PHP_EOL; | ||
| + | ||
| +$invertedPoints = [ | ||
| + "x" => [1, 2], | ||
| + "y" => [2, 1] | ||
| +]; | ||
| + | ||
| +foreach ($invertedPoints as list(0 => $row1, 1 => $row2)) { | ||
| + var_dump($row1, $row2); | ||
| +} | ||
| + | ||
| +?> | ||
| +--EXPECT-- | ||
| +int(1) | ||
| +int(2) | ||
| +int(2) | ||
| +int(1) | ||
| + | ||
| +int(1) | ||
| +int(2) | ||
| +int(2) | ||
| +int(1) |
| @@ -0,0 +1,71 @@ | ||
| +--TEST-- | ||
| +list() with keys | ||
| +--FILE-- | ||
| +<?php | ||
| + | ||
| +$antonyms = [ | ||
| + "good" => "bad", | ||
| + "happy" => "sad", | ||
| +]; | ||
| + | ||
| +list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms; | ||
| +var_dump($good_antonym, $happy_antonym); | ||
| + | ||
| +echo PHP_EOL; | ||
| + | ||
| +$powersOfTwo = [ | ||
| + 1 => 2, | ||
| + 2 => 4, | ||
| + 3 => 8 | ||
| +]; | ||
| + | ||
| +list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo; | ||
| +var_dump($two_1, $two_2, $two_3); | ||
| + | ||
| +echo PHP_EOL; | ||
| + | ||
| +$contrivedMixedKeyTypesExample = [ | ||
| + 7 => "the best PHP version", | ||
| + "elePHPant" => "the cutest mascot" | ||
| +]; | ||
| + | ||
| +list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample; | ||
| +var_dump($seven, $elePHPant); | ||
| + | ||
| +echo PHP_EOL; | ||
| + | ||
| +$allTogetherNow = [ | ||
| + "antonyms" => $antonyms, | ||
| + "powersOfTwo" => $powersOfTwo, | ||
| + "contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample | ||
| +]; | ||
| + | ||
| +list( | ||
| + "antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym), | ||
| + "powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3), | ||
| + "contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant) | ||
| +) = $allTogetherNow; | ||
| + | ||
| +var_dump($good_antonym, $happy_antonym); | ||
| +var_dump($two_1, $two_2, $two_3); | ||
| +var_dump($seven, $elePHPant); | ||
| + | ||
| +?> | ||
| +--EXPECT-- | ||
| +string(3) "bad" | ||
| +string(3) "sad" | ||
| + | ||
| +int(2) | ||
| +int(4) | ||
| +int(8) | ||
| + | ||
| +string(20) "the best PHP version" | ||
| +string(17) "the cutest mascot" | ||
| + | ||
| +string(3) "bad" | ||
| +string(3) "sad" | ||
| +int(2) | ||
| +int(4) | ||
| +int(8) | ||
| +string(20) "the best PHP version" | ||
| +string(17) "the cutest mascot" |
| @@ -0,0 +1,54 @@ | ||
| +--TEST-- | ||
| +list() with keys and ArrayAccess | ||
| +--FILE-- | ||
| +<?php | ||
| + | ||
| +$antonymObject = new ArrayObject; | ||
| +$antonymObject["good"] = "bad"; | ||
| +$antonymObject["happy"] = "sad"; | ||
| + | ||
| +list("good" => $good, "happy" => $happy) = $antonymObject; | ||
| +var_dump($good, $happy); | ||
| + | ||
| +echo PHP_EOL; | ||
| + | ||
| +$stdClassCollection = new SplObjectStorage; | ||
| +$foo = new StdClass; | ||
| +$stdClassCollection[$foo] = "foo"; | ||
| +$bar = new StdClass; | ||
| +$stdClassCollection[$bar] = "bar"; | ||
| + | ||
| +list($foo => $fooStr, $bar => $barStr) = $stdClassCollection; | ||
| +var_dump($fooStr, $barStr); | ||
| + | ||
| +echo PHP_EOL; | ||
| + | ||
| +class IndexPrinter implements ArrayAccess | ||
| +{ | ||
| + public function offsetGet($offset) { | ||
| + echo "GET "; | ||
| + var_dump($offset); | ||
| + } | ||
| + public function offsetSet($offset, $value) { | ||
| + } | ||
| + public function offsetExists($offset) { | ||
| + } | ||
| + public function offsetUnset($offset) { | ||
| + } | ||
| +} | ||
| + | ||
| +$op = new IndexPrinter; | ||
| +list(123 => $x) = $op; | ||
| +// PHP shouldn't convert this to an integer offset, because it's ArrayAccess | ||
| +list("123" => $x) = $op; | ||
| + | ||
| +?> | ||
| +--EXPECT-- | ||
| +string(3) "bad" | ||
| +string(3) "sad" | ||
| + | ||
| +string(3) "foo" | ||
| +string(3) "bar" | ||
| + | ||
| +GET int(123) | ||
| +GET string(3) "123" |
| @@ -0,0 +1,32 @@ | ||
| +--TEST-- | ||
| +list() with non-integer-or-string keys | ||
| +--FILE-- | ||
| +<?php | ||
| + | ||
| +$results = [ | ||
| + 0 => 0, | ||
| + 1 => 1, | ||
| + "" => "" | ||
| +]; | ||
| + | ||
| +list(NULL => $NULL, 1.5 => $float, FALSE => $FALSE, TRUE => $TRUE) = $results; | ||
| +var_dump($NULL, $float, $FALSE, $TRUE); | ||
| + | ||
| +echo PHP_EOL; | ||
| + | ||
| +list("0" => $zeroString, "1" => $oneString) = $results; | ||
| +var_dump($zeroString, $oneString); | ||
| + | ||
| +list(STDIN => $resource) = []; | ||
| + | ||
| +?> | ||
| +--EXPECTF-- | ||
| +string(0) "" | ||
| +int(1) | ||
| +int(0) | ||
| +int(1) | ||
| + | ||
| +int(0) | ||
| +int(1) | ||
| + | ||
| +Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d |
| @@ -0,0 +1,60 @@ | ||
| +<?php declare(strict_types=1); | ||
| + | ||
| +// Observer objects for the Zend/tests/list_keyed_evaluation_order.* tests | ||
| + | ||
| +class Stringable | ||
| +{ | ||
| + private $name; | ||
| + public function __construct(string $name) { | ||
| + $this->name = $name; | ||
| + } | ||
| + | ||
| + public function __toString(): string { | ||
| + echo "$this->name evaluated.", PHP_EOL; | ||
| + return $this->name; | ||
| + } | ||
| +} | ||
| + | ||
| +class Indexable implements ArrayAccess | ||
| +{ | ||
| + private $array; | ||
| + public function __construct(array $array) { | ||
| + $this->array = $array; | ||
| + } | ||
| + | ||
| + public function offsetExists($offset): bool { | ||
| + echo "Existence of offset $offset checked for.", PHP_EOL; | ||
| + return isset($this->array[$offset]); | ||
| + } | ||
| + | ||
| + public function offsetUnset($offset): void { | ||
| + unset($this->array[$offset]); | ||
| + echo "Offset $offset removed.", PHP_EOL; | ||
| + } | ||
| + | ||
| + public function offsetGet($offset) { | ||
| + echo "Offset $offset retrieved.", PHP_EOL; | ||
| + return $this->array[$offset]; | ||
| + } | ||
| + | ||
| + public function offsetSet($offset, $value): void { | ||
| + $this->array[$offset] = $value; | ||
| + echo "Offset $offset set to $value.", PHP_EOL; | ||
| + } | ||
| +} | ||
| + | ||
| +class IndexableRetrievable | ||
| +{ | ||
| + private $label; | ||
| + private $indexable; | ||
| + | ||
| + public function __construct(string $label, Indexable $indexable) { | ||
| + $this->label = $label; | ||
| + $this->indexable = $indexable; | ||
| + } | ||
| + | ||
| + public function getIndexable(): Indexable { | ||
| + echo "Indexable $this->label retrieved.", PHP_EOL; | ||
| + return $this->indexable; | ||
| + } | ||
| +} |
| @@ -0,0 +1,35 @@ | ||
| +--TEST-- | ||
| +list() with keys, evaluation order | ||
| +--FILE-- | ||
| +<?php | ||
| + | ||
| +require_once "list_keyed_evaluation_order.inc"; | ||
| + | ||
| +$a = new Stringable("A"); | ||
| +$c = new Stringable("C"); | ||
| + | ||
| +$e = new IndexableRetrievable("E", new Indexable(["A" => "value for offset A", "C" => "value for offset C"])); | ||
| + | ||
| +$store = new Indexable([]); | ||
| + | ||
| +// list($a => $b, $c => $d) = $e; | ||
| +// Should be evaluated in the order: | ||
| +// 1. Evaluate $e | ||
| +// 2. Evaluate $a | ||
| +// 3. Evaluate $e[$a] | ||
| +// 4. Assign $b from $e[$a] | ||
| +// 5. Evaluate $c | ||
| +// 6. Evaluate $e[$c] | ||
| +// 7. Assign $c from $e[$a] | ||
| + | ||
| +list((string)$a => $store["B"], (string)$c => $store["D"]) = $e->getIndexable(); | ||
| + | ||
| +?> | ||
| +--EXPECT-- | ||
| +Indexable E retrieved. | ||
| +A evaluated. | ||
| +Offset A retrieved. | ||
| +Offset B set to value for offset A. | ||
| +C evaluated. | ||
| +Offset C retrieved. | ||
| +Offset D set to value for offset C. |
| @@ -0,0 +1,77 @@ | ||
| +--TEST-- | ||
| +list() with keys, evaluation order #2 | ||
| +--FILE-- | ||
| +<?php | ||
| + | ||
| +// All the following should print 'a' then 'b' | ||
| + | ||
| +list($a, $b) = ['a', 'b']; | ||
| +var_dump($a); | ||
| +var_dump($b); | ||
| + | ||
| +list(0 => $a, 1 => $b) = ['a', 'b']; | ||
| +var_dump($a); | ||
| +var_dump($b); | ||
| + | ||
| +list(1 => $b, 0 => $a) = ['a', 'b']; | ||
| +var_dump($a); | ||
| +var_dump($b); | ||
| + | ||
| +$arr = []; | ||
| +list($arr[], $arr[]) = ['a', 'b']; | ||
| +var_dump($arr[0]); | ||
| +var_dump($arr[1]); | ||
| + | ||
| +$arr = []; | ||
| +list(0 => $arr[], 1 => $arr[]) = ['a', 'b']; | ||
| +var_dump($arr[0]); | ||
| +var_dump($arr[1]); | ||
| + | ||
| +$arr = []; | ||
| +list(1 => $arr[], 0 => $arr[]) = ['b', 'a']; | ||
| +var_dump($arr[0]); | ||
| +var_dump($arr[1]); | ||
| + | ||
| +$arr = []; | ||
| +list(list(1 => $arr[], 0 => $arr[])) = [['b', 'a']]; | ||
| +var_dump($arr[0]); | ||
| +var_dump($arr[1]); | ||
| + | ||
| +$arr = []; | ||
| +list('key1' => $arr[], 'key2' => $arr[]) = ['key2' => 'b', 'key1' => 'a']; | ||
| +var_dump($arr[0]); | ||
| +var_dump($arr[1]); | ||
| + | ||
| +// This should print 'foo' | ||
| +$a = 0; | ||
| +list($a => $a) = ['foo', 'bar']; | ||
| +var_dump($a); | ||
| + | ||
| +// This should print 'bar' then 'foo' | ||
| +$a = 0; | ||
| +$b = 1; | ||
| +list($b => $a, $a => $c) = ['bar' => 'foo', 1 => 'bar']; | ||
| +var_dump($a); | ||
| +var_dump($c); | ||
| + | ||
| +?> | ||
| +--EXPECT-- | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(1) "a" | ||
| +string(1) "b" | ||
| +string(3) "foo" | ||
| +string(3) "bar" | ||
| +string(3) "foo" |
Oops, something went wrong.
0 comments on commit
37c8bb5