Skip to content

Commit fd7ac5f

Browse files
committed
Added default as an expression in argument lists.
1 parent 8853cf3 commit fd7ac5f

File tree

9 files changed

+663
-558
lines changed

9 files changed

+663
-558
lines changed

Zend/zend_ast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ enum _zend_ast_kind {
7474
ZEND_AST_TYPE,
7575
ZEND_AST_CONSTANT_CLASS,
7676
ZEND_AST_CALLABLE_CONVERT,
77+
ZEND_AST_DEFAULT,
7778

7879
/* 1 child node */
7980
ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT,

Zend/zend_compile.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3778,6 +3778,8 @@ static uint32_t zend_compile_args(
37783778
arg_count++;
37793779
}
37803780

3781+
CG(arg_num) = arg_num;
3782+
37813783
/* Treat passing of $GLOBALS the same as passing a call.
37823784
* This will error at runtime if the argument is by-ref. */
37833785
if (zend_is_call(arg) || is_globals_fetch(arg)) {
@@ -3896,6 +3898,12 @@ static uint32_t zend_compile_args(
38963898
}
38973899
/* }}} */
38983900

3901+
static void zend_compile_default(znode *result, zend_ast *ast)
3902+
{
3903+
zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_DEFAULT_ARG, NULL, NULL);
3904+
opline->op1.num = CG(arg_num);
3905+
}
3906+
38993907
ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc) /* {{{ */
39003908
{
39013909
if (fbc) {
@@ -11497,6 +11505,9 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
1149711505
case ZEND_AST_MATCH:
1149811506
zend_compile_match(result, ast);
1149911507
return;
11508+
case ZEND_AST_DEFAULT:
11509+
zend_compile_default(result, ast);
11510+
return;
1150011511
default:
1150111512
ZEND_ASSERT(0 /* not supported */);
1150211513
}

Zend/zend_globals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ struct _zend_compiler_globals {
154154
uint32_t rtd_key_counter;
155155

156156
zend_stack short_circuiting_opnums;
157+
158+
uint32_t arg_num;
157159
#ifdef ZTS
158160
uint32_t copied_functions_count;
159161
#endif

Zend/zend_language_parser.y

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
251251
%type <ast> group_use_declaration inline_use_declarations inline_use_declaration
252252
%type <ast> mixed_group_use_declaration use_declaration unprefixed_use_declaration
253253
%type <ast> unprefixed_use_declarations const_decl inner_statement
254-
%type <ast> expr optional_expr while_statement for_statement foreach_variable
254+
%type <ast> expr expr_with_default optional_expr while_statement for_statement foreach_variable
255255
%type <ast> foreach_statement declare_statement finally_statement unset_variable variable
256256
%type <ast> extends_from parameter optional_type_without_static argument global_var
257257
%type <ast> static_var class_statement trait_adaptation trait_precedence trait_alias
@@ -904,7 +904,7 @@ non_empty_argument_list:
904904
;
905905

906906
argument:
907-
expr { $$ = $1; }
907+
expr_with_default { $$ = $1; }
908908
| identifier ':' expr
909909
{ $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, $3); }
910910
| T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); }
@@ -1326,6 +1326,10 @@ expr:
13261326
| match { $$ = $1; }
13271327
;
13281328

1329+
expr_with_default:
1330+
expr { $$ = $1; }
1331+
| T_DEFAULT { $$ = zend_ast_create(ZEND_AST_DEFAULT); }
1332+
;
13291333

13301334
inline_function:
13311335
function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type

Zend/zend_vm_def.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9808,6 +9808,44 @@ ZEND_VM_HANDLER(209, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL, CONST, UNUSED|NUM, NUM
98089808
ZEND_VM_NEXT_OPCODE();
98099809
}
98109810

9811+
ZEND_VM_HANDLER(210, ZEND_FETCH_DEFAULT_ARG, UNUSED, UNUSED)
9812+
{
9813+
USE_OPLINE
9814+
SAVE_OPLINE();
9815+
9816+
zend_function *called_func = EX(call)->func;
9817+
9818+
zend_string *reflection_class_name = ZSTR_INIT_LITERAL("ReflectionParameter", 0);
9819+
zend_class_entry *reflection_class = zend_fetch_class(reflection_class_name, ZEND_FETCH_CLASS_DEFAULT);
9820+
zend_string_release(reflection_class_name);
9821+
9822+
/*
9823+
* [0]: The function (string) or class method (array) to reflect parameters from.
9824+
* [1]: A zero-based integer specifying the parameter position.
9825+
*/
9826+
zval constructor_params[2];
9827+
ZVAL_LONG(&constructor_params[1], opline->op1.num - 1);
9828+
if (called_func->common.scope == NULL) {
9829+
ZVAL_STR_COPY(&constructor_params[0], called_func->common.function_name);
9830+
} else {
9831+
zval arr;
9832+
array_init_size(&arr, 2);
9833+
add_next_index_string(&arr, called_func->common.scope->name->val);
9834+
add_next_index_string(&arr, called_func->common.function_name->val);
9835+
ZVAL_ARR(&constructor_params[0], Z_ARR(arr));
9836+
}
9837+
9838+
zval reflection_obj;
9839+
// TODO: Check result.
9840+
/*zend_result res =*/ object_init_with_constructor(&reflection_obj, reflection_class, 2, constructor_params, NULL);
9841+
9842+
zval default_value;
9843+
zend_call_method_with_0_params(Z_OBJ(reflection_obj), reflection_class, NULL, "getDefaultValue", &default_value);
9844+
9845+
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &default_value);
9846+
ZEND_VM_NEXT_OPCODE();
9847+
}
9848+
98119849
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_JMP, (OP_JMP_ADDR(op, op->op1) > op), ZEND_JMP_FORWARD, JMP_ADDR, ANY)
98129850
{
98139851
USE_OPLINE

0 commit comments

Comments
 (0)