Commit Graph

128 Commits

Author SHA1 Message Date
Nikita Popov
6233408a2a Fix thread safe build 2012-06-20 21:31:23 +02:00
Nikita Popov
d939d2dee5 Add sceleton for yield* expression
This does not yet actually implement any delegation.
2012-06-19 00:37:31 +02:00
Nikita Popov
f169b26dd7 Fix backtraces and func_get_args()
To make the generator function show up in backtraces one has to insert an
additional execute_data into the chain, as prev_execute_data->function_state
is used to determine the called function.

Adding the additional stack frame is also required for func_get_args(), as
the arguments are fetched from there too. The arguments have to be copied
in order to keep them around. Due to the way they are saved doing so is
quite ugly, so I added another function zend_copy_arguments to zend_execute.c
which handles this.
2012-06-09 00:40:47 +02:00
Nikita Popov
40760ecb90 Fix cloning of generator methods
Forgot to add a reference to the this variable
2012-06-05 14:00:31 +02:00
Nikita Popov
bf82f46ea9 Properly handle yield during method calls 2012-06-03 02:16:29 +02:00
Nikita Popov
7b3bfa5784 Improve backtraces from generators
The current situation is still not perfect, as the generator function itself
does not appear in the stack trace. This makes sense in some way, but it
would probably be more helpful if it would show up (with the bound arguments)
after the $generator->xyz() call. This could be misleading too though as the
function is not *really* called there.
2012-06-03 02:00:11 +02:00
Nikita Popov
6117f4c7c0 Add cloning support for generators
Generators can now be cloned. I'm pretty sure that my current code does not
yet cover all the edge cases of cloning the execution context, so there are
probably a few bugs in there :)
2012-06-02 20:40:58 +02:00
Nikita Popov
1477be9aa8 Make $generator->send() return the current value
This makes the API easier to use (and is consistent with Python and JS).
2012-05-31 20:03:18 +02:00
Nikita Popov
ee89e228f6 Allow yielding during function calls
During function calls arguments are pushed onto the stack. Now these are
backed up on yield and restored on resume. This requires memcpy'ing them,
but there doesn't seem to be any better way to do it.

Also this fixes the issue with exceptions thrown during function calls.
2012-05-31 00:00:30 +02:00
Nikita Popov
8790160235 Add auto-increment keys
When no key is explicitely yielded PHP will used auto-incrementing keys
as a fallback. They behave the same as with arrays, i.e. the key is the
successor of the largest previously used integer key.
2012-05-30 05:05:49 +02:00
Nikita Popov
bc08c2cf94 Add support for yielding keys
Keys are yielded using the

    yield $key => $value

syntax. Currently this is implemented as a statement only and not as an
expression, because conflicts arise considering nesting and use in arrays:

    yield yield $a => $b;
    // could be either
    yield (yield $a) => $b;
    // or
    yield (yield $a => $b);

Once I find some way to resolve these conflicts this should be available
as an expression too.

Also the key yielding code is rather copy-and-past-y for the value yielding
code, so that should be factored out.
2012-05-30 02:44:06 +02:00
Nikita Popov
72a91d08e7 Add $generator->close() method
Calling $generator->close() is equivalent to executing a return statement
at the current position in the generator.
2012-05-29 18:11:18 +02:00
Nikita Popov
12e928314f Fix segfault when send()ing to a closed generator 2012-05-29 18:01:08 +02:00
Nikita Popov
3600914ced Add support for $generator->send()
Yield now is an expression and the return value is the value passed to
$generator->send(). By default (i.e. if ->next() is called) the value is
NULL.

Unlike in Python ->send() can be run without priming the generator with a
->next() call first.
2012-05-29 17:34:33 +02:00
Nikita Popov
4aab08b64c Properly free resources when generator return value not used
To keep things clean two new functions are introduced:

zend_clean_and_cache_symbol_table(HashTable *symbol_table)
zend_free_compiled_variables(zval ***CVs, int num)
2012-05-28 06:43:18 +02:00
Nikita Popov
bcc7d976f3 Set EG(current_execute_data)
This fixes several issues. In particular it makes method generators work
properly and also allows generators using a symbol table.
2012-05-28 06:06:30 +02:00
Nikita Popov
64a643a4e3 Free loop variables
If the generator is closed before it has finished running, it may happen
that some FREE or SWITCH_FREE opcodes haven't been executed and memory is
leaked.

This fixes it by walking the brk_cont_array and manually freeing the
variables.
2012-05-27 17:14:20 +02:00
Nikita Popov
247bb737d5 Add support for generator methods 2012-05-27 03:50:31 +02:00
Nikita Popov
cbfa96cad5 Remove wrong dtor call 2012-05-27 00:25:12 +02:00
Nikita Popov
d49d3971e6 Close generator on return 2012-05-26 23:59:22 +02:00
Nikita Popov
5bb3a995c2 Implement return for generators
For generators ZEND_RETURN directly calls ZEND_VM_RETURN(), thus passing
execution back to the caller (zend_generator_resume).

This commit also adds a check that only return; is used in generators and
not return $value;.
2012-05-26 23:07:40 +02:00
Nikita Popov
fafce58683 Add YIELD opcode implementation 2012-05-26 22:44:53 +02:00
Nikita Popov
1a99d1c887 Add way to pass generator object to opcode handlers
The generator zval is put into the return_value_ptr_ptr.
2012-05-26 19:40:29 +02:00
Nikita Popov
f627be5254 Add support for executing a zend_execute_data
This adds another function execute_ex(), which accepts a zend_execute_data
struct to run (contrary to execute(), which accepts a zend_op_array from
which it initialized the execute_data).

This needs a bit more cleanup.
2012-05-26 17:53:13 +02:00
Nikita Popov
2c5ecb4fea Add dummy Iterator implementation
This simply adds dummy rewind/valid/current/key/next methods to Generator.
2012-05-23 16:44:58 +02:00
Nikita Popov
9ce9a7e639 Add initial code for suspending execution
This is just some initial code, which is still quite broken (and needs to be
moved so it can be reused.)
2012-05-23 14:20:25 +02:00
Nikita Popov
40b7533576 Add some boilerplate code for Generator class
The Generator class now uses a zend_generator struct, so it'll be able to
store additional info.

This commit also ensures that Generator cannot be directly instantiated
and extended. The error tests are now in a separate folder from the
(yet-to-come) functional tests.
2012-05-20 14:19:16 +02:00
Nikita Popov
ca59e5464d Add empty Generator class 2012-05-20 00:03:27 +02:00