Skip to content

Commit

Permalink
Hacky proof of concept implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed Jun 28, 2012
1 parent 5a9bddb commit 442f0a2
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 12 deletions.
7 changes: 7 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -6640,6 +6640,13 @@ void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_t
}
/* }}} */

void zend_do_inherit_parent_symtable(TSRMLS_D) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INHERIT_PARENT_SYMTABLE;
}
/* }}} */

void zend_do_extended_info(TSRMLS_D) /* {{{ */
{
zend_op *opline;
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,8 @@ void zend_do_goto(const znode *label TSRMLS_DC);
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC);
void zend_release_labels(TSRMLS_D);

void zend_do_inherit_parent_symtable(TSRMLS_D);

ZEND_API void function_add_ref(zend_function *function);

#define INITIAL_OP_ARRAY_SIZE 64
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_ini_scanner.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Generated by re2c 0.13.5 on Sat Feb 25 22:04:14 2012 */
/* Generated by re2c 0.13.5 on Wed Jun 27 22:28:45 2012 */
#line 1 "Zend/zend_ini_scanner.l"
/*
+----------------------------------------------------------------------+
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_ini_scanner_defs.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Generated by re2c 0.13.5 on Sat Feb 25 22:04:14 2012 */
/* Generated by re2c 0.13.5 on Wed Jun 27 22:28:45 2012 */
#line 3 "Zend/zend_ini_scanner_defs.h"

enum YYCONDTYPE {
Expand Down
66 changes: 66 additions & 0 deletions Zend/zend_language_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,72 @@ expr_without_variable:
| T_STATIC function is_generator is_reference { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, $4.op_type, 1 TSRMLS_CC); }
'(' parameter_list ')' lexical_vars { zend_do_suspend_if_generator(TSRMLS_C); }
'{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $5; }
| '(' {
zend_do_begin_lambda_function_declaration(&$$, &$1, 1, 0, 0 TSRMLS_CC);
zend_do_inherit_parent_symtable(TSRMLS_C);
zend_do_suspend_if_generator(TSRMLS_C);
}
generator_expression_foreach
')' {
zend_do_end_function_declaration(&$1 TSRMLS_CC);

zend_do_begin_dynamic_function_call(&$2, 0 TSRMLS_CC);
{
znode param_count_node;
Z_LVAL(param_count_node.u.constant) = 0;
zend_do_end_function_call(&$2, &$$, &param_count_node, 0, 1 TSRMLS_CC);
}
zend_do_extended_fcall_end(TSRMLS_C);
}
| '[' {
zend_do_begin_lambda_function_declaration(&$$, &$1, 1, 0, 0 TSRMLS_CC);
zend_do_inherit_parent_symtable(TSRMLS_C);
zend_do_suspend_if_generator(TSRMLS_C);
}
generator_expression_foreach
']' {
znode generator_instance_node;

zend_do_end_function_declaration(&$1 TSRMLS_CC);

zend_do_begin_dynamic_function_call(&$2, 0 TSRMLS_CC);
{
znode param_count_node;
Z_LVAL(param_count_node.u.constant) = 0;
zend_do_end_function_call(&$2, &generator_instance_node, &param_count_node, 0, 1 TSRMLS_CC);
}
zend_do_extended_fcall_end(TSRMLS_C);

{
znode function_node, param_count_node;

function_node.op_type = IS_CONST;
ZVAL_STRING(&function_node.u.constant, "iterator_to_array", 1);

Z_LVAL(param_count_node.u.constant) = 1;

zend_do_begin_function_call(&function_node, 0 TSRMLS_CC);
zend_do_pass_param(&generator_instance_node, ZEND_SEND_VAL, 1 TSRMLS_CC);
zend_do_end_function_call(&function_node, &$$, &param_count_node, 0, 0 TSRMLS_CC);
zend_do_extended_fcall_end(TSRMLS_C);
}
}
;

generator_expression_foreach:
T_FOREACH '(' variable T_AS { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
generator_expression_content { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
| T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
generator_expression_content { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
;

generator_expression_content:
generator_expression_foreach
| T_IF '(' expr ')' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } generator_expression_content { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); zend_do_if_end(TSRMLS_C); }
| T_YIELD expr { zend_do_yield(&$$, &$2, NULL TSRMLS_CC); }
| T_YIELD expr T_DOUBLE_ARROW expr { zend_do_yield(&$$, &$4, &$2 TSRMLS_CC); }
;

combined_scalar_offset:
Expand Down
28 changes: 26 additions & 2 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -2395,14 +2395,14 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
EX(object) = NULL;
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR &&
} else if (OP2_TYPE != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
Z_ADDREF_P(EX(object));
}
if (OP2_TYPE == IS_VAR && OP2_FREE &&
if (OP2_TYPE != IS_CV && OP2_FREE &&
EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
EX(fbc)->common.prototype = (zend_function*)function_name;
Expand Down Expand Up @@ -5237,6 +5237,7 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY)

EX(current_scope) = EG(scope);
EX(current_called_scope) = EG(called_scope);
EX(symbol_table) = EG(active_symbol_table);

if (EG(This)) {
Z_ADDREF_P(EG(This));
Expand Down Expand Up @@ -5421,4 +5422,27 @@ ZEND_VM_HANDLER(161, ZEND_DELEGATE_YIELD, CONST|TMP|VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}

ZEND_VM_HANDLER(162, ZEND_INHERIT_PARENT_SYMTABLE, ANY, ANY)
{
HashTable *symbol_table;

/* Make sure that the parent scope has a symbol table. As
* zend_rebuild_symbol_table() acts upon EG(current_execute_data) we
* have to temporarily set it to the parent scope and then set it back. */
EG(current_execute_data) = EX(prev_execute_data);
zend_rebuild_symbol_table(TSRMLS_C);
EG(current_execute_data) = execute_data;

/* Create a new symbol table into which the parent symbol table is copied.
* The parent symbol table was put into EG(active_symbol_table) by
* zend_rebuild_symbol_table(). Then set EG(active_symbol_table) to the
* newly created copy of the parent table. */
ALLOC_HASHTABLE(symbol_table);
zend_hash_init(symbol_table, zend_hash_num_elements(EG(active_symbol_table)), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(symbol_table, EG(active_symbol_table), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
EG(active_symbol_table) = symbol_table;

ZEND_VM_NEXT_OPCODE();
}

ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
65 changes: 57 additions & 8 deletions Zend/zend_vm_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,7 @@ static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP

EX(current_scope) = EG(scope);
EX(current_called_scope) = EG(called_scope);
EX(symbol_table) = EG(active_symbol_table);

if (EG(This)) {
Z_ADDREF_P(EG(This));
Expand Down Expand Up @@ -1296,6 +1297,29 @@ static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP
ZEND_VM_LEAVE();
}

static int ZEND_FASTCALL ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
HashTable *symbol_table;

/* Make sure that the parent scope has a symbol table. As
* zend_rebuild_symbol_table() acts upon EG(current_execute_data) we
* have to temporarily set it to the parent scope and then set it back. */
EG(current_execute_data) = EX(prev_execute_data);
zend_rebuild_symbol_table(TSRMLS_C);
EG(current_execute_data) = execute_data;

/* Create a new symbol table into which the parent symbol table is copied.
* The parent symbol table was put into EG(active_symbol_table) by
* zend_rebuild_symbol_table(). Then set EG(active_symbol_table) to the
* newly created copy of the parent table. */
ALLOC_HASHTABLE(symbol_table);
zend_hash_init(symbol_table, zend_hash_num_elements(EG(active_symbol_table)), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(symbol_table, EG(active_symbol_table), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
EG(active_symbol_table) = symbol_table;

ZEND_VM_NEXT_OPCODE();
}

static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
Expand Down Expand Up @@ -1374,14 +1398,14 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
EX(object) = NULL;
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR &&
} else if (IS_CONST != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
Z_ADDREF_P(EX(object));
}
if (IS_CONST == IS_VAR && 0 &&
if (IS_CONST != IS_CV && 0 &&
EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
EX(fbc)->common.prototype = (zend_function*)function_name;
Expand Down Expand Up @@ -1676,14 +1700,14 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
EX(object) = NULL;
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR &&
} else if (IS_TMP_VAR != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
Z_ADDREF_P(EX(object));
}
if (IS_TMP_VAR == IS_VAR && 1 &&
if (IS_TMP_VAR != IS_CV && 1 &&
EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
EX(fbc)->common.prototype = (zend_function*)function_name;
Expand Down Expand Up @@ -1840,14 +1864,14 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
EX(object) = NULL;
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR &&
} else if (IS_VAR != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
Z_ADDREF_P(EX(object));
}
if (IS_VAR == IS_VAR && (free_op2.var != NULL) &&
if (IS_VAR != IS_CV && (free_op2.var != NULL) &&
EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
EX(fbc)->common.prototype = (zend_function*)function_name;
Expand Down Expand Up @@ -2037,14 +2061,14 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
EX(object) = NULL;
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR &&
} else if (IS_CV != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
Z_ADDREF_P(EX(object));
}
if (IS_CV == IS_VAR && 0 &&
if (IS_CV != IS_CV && 0 &&
EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
EX(fbc)->common.prototype = (zend_function*)function_name;
Expand Down Expand Up @@ -43600,6 +43624,31 @@ void zend_init_opcodes_handlers(void)
ZEND_DELEGATE_YIELD_SPEC_CV_HANDLER,
ZEND_DELEGATE_YIELD_SPEC_CV_HANDLER,
ZEND_DELEGATE_YIELD_SPEC_CV_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_INHERIT_PARENT_SYMTABLE_SPEC_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_vm_opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,4 @@
#define ZEND_SUSPEND_AND_RETURN_GENERATOR 159
#define ZEND_YIELD 160
#define ZEND_DELEGATE_YIELD 161
#define ZEND_INHERIT_PARENT_SYMTABLE 162

0 comments on commit 442f0a2

Please sign in to comment.