Permalink
Browse files

Allow specifying keys on list() elements

Squashed commit of the following:

commit 0361dbe
Author: Andrea Faulds <ajf@ajf.me>
Date:   Fri Mar 25 16:59:20 2016 +0000

    UPGRADING and NEWS

commit dca9d4a
Author: Andrea Faulds <ajf@ajf.me>
Date:   Fri Mar 25 16:45:18 2016 +0000

    Add tests contributed by @jesseschalken

commit e557f77
Author: Andrea Faulds <ajf@ajf.me>
Date:   Fri Mar 25 16:44:51 2016 +0000

    Rebuild VM

commit 70942e4
Author: Andrea Faulds <ajf@ajf.me>
Date:   Wed Feb 24 13:12:26 2016 +0000

    Add test for evaluation order of nested list() keys

commit ed3592e
Author: Andrea Faulds <ajf@ajf.me>
Date:   Wed Feb 24 12:42:04 2016 +0000

    Add test for evaluation order

commit 589756c
Author: Andrea Faulds <ajf@ajf.me>
Date:   Tue Jan 19 17:29:34 2016 +0000

    Allow arbitrary expressions for key

commit 3f62207
Author: Andrea Faulds <ajf@ajf.me>
Date:   Tue Jan 19 17:45:10 2016 +0000

    Remove compile-time HANDLE_NUMERIC (see bug #63217)

commit bab7581
Author: Andrea Faulds <ajf@ajf.me>
Date:   Sun Jan 17 01:20:26 2016 +0000

    Handle numeric strings

commit 14bfe93
Author: Andrea Faulds <ajf@ajf.me>
Date:   Sun Jan 17 01:09:36 2016 +0000

    Allow trailing comma

commit f4c8b2c
Author: Andrea Faulds <ajf@ajf.me>
Date:   Sat Jan 16 23:47:11 2016 +0000

    Add tests

commit 0085884
Author: Andrea Faulds <ajf@ajf.me>
Date:   Sat Jan 16 22:24:23 2016 +0000

    Handle non-integer/string opcodes

commit e572d2d
Author: Andrea Faulds <ajf@ajf.me>
Date:   Sat Jan 16 21:10:33 2016 +0000

    Disallow mixing keyed and unkeyed list() elements

commit cede13c
Author: Andrea Faulds <ajf@ajf.me>
Date:   Sun Jan 10 20:46:44 2016 +0000

    list() with keys (no foreach or tests)
  • Loading branch information...
hikari-no-yume committed Mar 25, 2016
1 parent 0e5fa32 commit 37c8bb58686b2d86f145ebe4fe39854f5951dcd7
1 NEWS
@@ -12,6 +12,7 @@ PHP NEWS
. Added void return type. (Andrea)
. Added support for negative string offsets in string offset syntax and
various string functions. (Francois)
. Added a form of the list() construct where keys can be specified. (Andrea)
- FTP:
. Implemented FR #55651 (Option to ignore the returned FTP PASV address).
@@ -35,6 +35,8 @@ PHP 7.1 UPGRADE NOTES
. String offset access now supports negative references, which will be
counted from the end of the string.
(RFC: https://wiki.php.net/rfc/negative-string-offsets)
. Added a form of the list() construct where keys can be specified.
(RFC: https://wiki.php.net/rfc/list_keys)
========================================
3. Changes in SAPI modules
@@ -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

Please sign in to comment.