Skip to content

Commit

Permalink
Merge branch 'generators'
Browse files Browse the repository at this point in the history
* generators: (70 commits)
  Fix typos
  Fix segfault when traversing a by-ref generator twice
  Make sure that exception is thrown on rewind() after closing too
  Remove implementation stubs for yield delegation
  Fix several issues and allow rewind only at/before first yield
  Run finally if generator is closed before finishing
  Finally with return now works in generators too
  Add dedicated opcode for returns from a generator
  Disallow serialization and unserialization
  Fix zts build (typo)
  Drop Generator::close() method
  Forgot to add test
  Support trivial finally in generators (no yield, no return)
  Fix implementation of Iterator interface
  Add T_YIELD in tokenizer_data.c
  Throw error also for return occuring before yield
  Fix throwing of exceptions within a generator
  Remove reference restrictions from foreach
  Require parenthesis around yield expressions
  Add some more tests
  ...
  • Loading branch information
cataphract committed Sep 1, 2012
2 parents 7b5960b + dbc7809 commit 53351d0
Show file tree
Hide file tree
Showing 85 changed files with 9,338 additions and 2,820 deletions.
3 changes: 2 additions & 1 deletion Zend/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ libZend_la_SOURCES=\
zend_objects_API.c zend_ts_hash.c zend_stream.c \
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
zend_generators.c

libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
Expand Down
4 changes: 4 additions & 0 deletions Zend/Zend.dsp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Zend/ZendTS.dsp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 0 additions & 12 deletions Zend/tests/errmsg_043.phpt

This file was deleted.

18 changes: 18 additions & 0 deletions Zend/tests/foreach_temp_array_expr_with_refs.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Temporary array expressions can be iterated by reference
--FILE--
<?php

$a = 'a';
$b = 'b';

foreach ([&$a, &$b] as &$value) {
$value .= '-foo';
}

var_dump($a, $b);

?>
--EXPECT--
string(5) "a-foo"
string(5) "b-foo"
22 changes: 22 additions & 0 deletions Zend/tests/generators/auto_incrementing_keys.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
Generator keys are auto-incrementing by default
--FILE--
<?php

function gen() {
yield 'foo';
yield 'bar';
yield 5 => 'rab';
yield 'oof';
}

foreach (gen() as $k => $v) {
echo $k, ' => ', $v, "\n";
}

?>
--EXPECT--
0 => foo
1 => bar
5 => rab
6 => oof
27 changes: 27 additions & 0 deletions Zend/tests/generators/backtrace.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
Printing the stack trace in a generator
--FILE--
<?php

function f1() {
debug_print_backtrace();
}

function f2($arg1, $arg2) {
f1();
yield; // force generator
}

function f3($gen) {
$gen->rewind(); // trigger run
}

$gen = f2('foo', 'bar');
f3($gen);

?>
--EXPECTF--
#0 f1() called at [%s:%d]
#1 f2(foo, bar)
#2 Generator->rewind() called at [%s:%d]
#3 f3(Generator Object ()) called at [%s:%d]
32 changes: 32 additions & 0 deletions Zend/tests/generators/clone.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
Generators can be cloned
--FILE--
<?php

function firstN($end) {
for ($i = 0; $i < $end; ++$i) {
yield $i;
}
}

$g1 = firstN(5);
var_dump($g1->current());
$g1->next();

$g2 = clone $g1;
var_dump($g2->current());
$g2->next();

var_dump($g2->current());
var_dump($g1->current());

$g1->next();
var_dump($g1->current());

?>
--EXPECT--
int(0)
int(1)
int(2)
int(1)
int(2)
33 changes: 33 additions & 0 deletions Zend/tests/generators/clone_with_foreach.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--TEST--
Cloning a generator with a foreach loop properly adds a ref for the loop var
--FILE--
<?php

function gen() {
foreach ([1, 2, 3] as $i) {
yield $i;
}
}

$g1 = gen();
var_dump($g1->current());

$g2 = clone $g1;
var_dump($g2->current());

$g1->next();
$g2->next();
var_dump($g1->current());
var_dump($g2->current());

unset($g1);
$g2->next();
var_dump($g2->current());

?>
--EXPECT--
int(1)
int(1)
int(2)
int(2)
int(3)
18 changes: 18 additions & 0 deletions Zend/tests/generators/clone_with_stack.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
A generator with an active stack can be cloned
--FILE--
<?php

function gen() {
var_dump(str_repeat("x", yield));
}

$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->send(10);

?>
--EXPECT--
string(10) "xxxxxxxxxx"
27 changes: 27 additions & 0 deletions Zend/tests/generators/clone_with_symbol_table.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
A generator using a symbol table can be cloned
--FILE--
<?php

function gen() {
// force compiled variable for $foo
$foo = 'foo';

// force symbol table
extract(['foo' => 'bar']);

// interrupt
yield;

var_dump($foo);
}

$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->next();

?>
--EXPECT--
string(3) "bar"
24 changes: 24 additions & 0 deletions Zend/tests/generators/clone_with_this.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
Cloning a generator method (with $this)
--FILE--
<?php

class Test {
protected $foo;

public function gen() {
$this->foo = 'bar';
yield; // interrupt
var_dump($this->foo);
}
}

$g1 = (new Test)->gen();
$g1->rewind(); // goto yield
$g2 = clone $g1;
unset($g1);
$g2->next();

?>
--EXPECT--
string(3) "bar"
19 changes: 19 additions & 0 deletions Zend/tests/generators/dynamic_call.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
It's possible to invoke a generator dynamically
--FILE--
<?php

function gen($foo, $bar) {
yield $foo;
yield $bar;
}

$gen = call_user_func('gen', 'bar', 'foo');
foreach ($gen as $value) {
var_dump($value);
}

?>
--EXPECT--
string(3) "bar"
string(3) "foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Generators cannot return values (even before yield)
--FILE--
<?php

function gen() {
return $foo;
yield;
}

?>
--EXPECTF--
Fatal error: Generators cannot return values using "return" in %s on line 4
13 changes: 13 additions & 0 deletions Zend/tests/generators/errors/generator_cannot_return_error.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Generators cannot return values
--FILE--
<?php

function gen() {
yield;
return $abc;
}

?>
--EXPECTF--
Fatal error: Generators cannot return values using "return" in %s on line 5
10 changes: 10 additions & 0 deletions Zend/tests/generators/errors/generator_extend_error.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
The Generator class cannot be extended
--FILE--
<?php

class ExtendedGenerator extends Generator { }

?>
--EXPECTF--
Fatal error: Class ExtendedGenerator may not inherit from final class (Generator) in %s on line %d
10 changes: 10 additions & 0 deletions Zend/tests/generators/errors/generator_instantiate_error.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--TEST--
It's not possible to directly instantiate the Generator class
--FILE--
<?php

new Generator;

?>
--EXPECTF--
Catchable fatal error: The "Generator" class is reserved for internal use and cannot be manually instantiated in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Non-ref generators cannot be iterated by-ref
--FILE--
<?php

function gen() { yield; }

$gen = gen();
foreach ($gen as &$value) { }

?>
--EXPECTF--
Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d
Stack trace:
#0 %s(%d): unknown()
#1 {main}
thrown in %s on line %d

17 changes: 17 additions & 0 deletions Zend/tests/generators/errors/resume_running_generator_error.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
It is not possible to resume an already running generator
--FILE--
<?php

function gen() {
$gen = yield;
$gen->next();
}

$gen = gen();
$gen->send($gen);
$gen->next();

?>
--EXPECTF--
Fatal error: Cannot resume an already running generator in %s on line %d
Loading

0 comments on commit 53351d0

Please sign in to comment.