Skip to content

Commit

Permalink
Allow specifying keys on list() elements
Browse files Browse the repository at this point in the history
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
hikari-no-yume committed Mar 25, 2016
1 parent 0e5fa32 commit 37c8bb5
Show file tree
Hide file tree
Showing 21 changed files with 1,484 additions and 45 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions Zend/tests/foreach_list_keyed.phpt
Original file line number Diff line number Diff line change
@@ -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)
71 changes: 71 additions & 0 deletions Zend/tests/list_keyed.phpt
Original file line number Diff line number Diff line change
@@ -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"
54 changes: 54 additions & 0 deletions Zend/tests/list_keyed_ArrayAccess.phpt
Original file line number Diff line number Diff line change
@@ -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"
32 changes: 32 additions & 0 deletions Zend/tests/list_keyed_conversions.phpt
Original file line number Diff line number Diff line change
@@ -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
60 changes: 60 additions & 0 deletions Zend/tests/list_keyed_evaluation_order.inc
Original file line number Diff line number Diff line change
@@ -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;
}
}
35 changes: 35 additions & 0 deletions Zend/tests/list_keyed_evaluation_order.phpt
Original file line number Diff line number Diff line change
@@ -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.
77 changes: 77 additions & 0 deletions Zend/tests/list_keyed_evaluation_order_2.phpt
Original file line number Diff line number Diff line change
@@ -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"
Loading

0 comments on commit 37c8bb5

Please sign in to comment.