Skip to content

Commit 508d55d

Browse files
committed
Refactoring
1 parent 1e3cdf4 commit 508d55d

File tree

4 files changed

+55
-124
lines changed

4 files changed

+55
-124
lines changed

Zend/tests/pattern_matching/is/range.phpt

Lines changed: 0 additions & 42 deletions
This file was deleted.

Zend/zend_ast.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ enum _zend_ast_kind {
166166
ZEND_AST_PIPE,
167167
ZEND_AST_IS,
168168
ZEND_AST_OBJECT_PATTERN_ELEMENT,
169-
ZEND_AST_RANGE_PATTERN,
170169
ZEND_AST_ARRAY_PATTERN_ELEMENT,
171170
ZEND_AST_CLASS_CONST_PATTERN,
172171

Zend/zend_compile.c

Lines changed: 54 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6644,7 +6644,7 @@ static void zend_compile_pipe(znode *result, zend_ast *ast)
66446644
typedef struct {
66456645
bool inside_or_pattern;
66466646
uint32_t num_bindings;
6647-
uint32_t first_tmp;
6647+
uint32_t first_binding_tmp;
66486648
zend_stack labels;
66496649
} zend_pm_context;
66506650

@@ -6673,21 +6673,16 @@ static uint32_t zend_pm_label_create(zend_pm_context *context)
66736673
static void zend_pm_label_set_next(zend_pm_context *context, uint32_t label_offset)
66746674
{
66756675
uint32_t *labels = zend_stack_base(&context->labels);
6676-
uint32_t *label = &labels[-label_offset];
6677-
*label = get_next_op_number();
6676+
labels[-label_offset] = get_next_op_number();
66786677
}
66796678

66806679
static void zend_pm_labels_replace(zend_pm_context *context, uint32_t start_opnum)
66816680
{
66826681
uint32_t *labels = zend_stack_base(&context->labels);
6683-
if (!labels) {
6684-
return;
6685-
}
6686-
6682+
uint32_t label_lower_bound = -zend_stack_count(&context->labels);
66876683
zend_op_array *op_array = CG(active_op_array);
66886684
zend_op *opline = &op_array->opcodes[start_opnum];
66896685
zend_op *end_opline = &op_array->opcodes[op_array->last];
6690-
uint32_t label_lower_bound = -zend_stack_count(&context->labels);
66916686

66926687
while (opline < end_opline) {
66936688
switch (opline->opcode) {
@@ -6706,15 +6701,15 @@ static void zend_pm_labels_replace(zend_pm_context *context, uint32_t start_opnu
67066701
}
67076702
}
67086703

6709-
static void zend_compile_expr_like_pattern(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum)
6704+
static void zend_pm_compile_expr_like(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum)
67106705
{
67116706
znode result, value;
67126707
zend_compile_expr(&value, ast->child[0]);
67136708
zend_emit_op_tmp(&result, expr_node->op_type == IS_CV || consume_expr ? ZEND_IS_IDENTICAL : ZEND_CASE_STRICT, expr_node, &value);
67146709
zend_emit_cond_jump(ZEND_JMPZ, &result, false_opnum);
67156710
}
67166711

6717-
static void verify_parenthesized_compound_pattern(zend_ast *ast, zend_ast_kind kind)
6712+
static void zend_pm_verify_parenthesized_compound_pattern(zend_ast *ast, zend_ast_kind kind)
67186713
{
67196714
zend_ast_list *ast_list = zend_ast_get_list(ast);
67206715

@@ -6726,14 +6721,15 @@ static void verify_parenthesized_compound_pattern(zend_ast *ast, zend_ast_kind k
67266721
}
67276722
}
67286723

6729-
static void zend_compile_or_pattern(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
6724+
static void zend_pm_compile_or(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
67306725
{
6731-
verify_parenthesized_compound_pattern(ast, ZEND_AST_AND_PATTERN);
6726+
zend_pm_verify_parenthesized_compound_pattern(ast, ZEND_AST_AND_PATTERN);
67326727

67336728
context->inside_or_pattern = true;
67346729

67356730
zend_ast_list *ast_list = zend_ast_get_list(ast);
67366731
uint32_t true_label = zend_pm_label_create(context);
6732+
uint32_t false_label = consume_expr ? zend_pm_label_create(context) : false_opnum;
67376733
uint32_t next_label = 0;
67386734

67396735
for (uint32_t i = 0; i < ast_list->children - 1; i++) {
@@ -6746,13 +6742,9 @@ static void zend_compile_or_pattern(zend_ast *ast, znode *expr_node, bool consum
67466742
}
67476743
zend_pm_label_set_next(context, next_label);
67486744

6749-
if (!consume_expr) {
6750-
zend_compile_pattern(ast_list->child[ast_list->children - 1], expr_node, false, false_opnum, context);
6751-
zend_pm_label_set_next(context, true_label);
6752-
} else {
6753-
uint32_t false_label = zend_pm_label_create(context);
6754-
zend_compile_pattern(ast_list->child[ast_list->children - 1], expr_node, false, false_label, context);
6745+
zend_compile_pattern(ast_list->child[ast_list->children - 1], expr_node, false, false_label, context);
67556746

6747+
if (consume_expr) {
67566748
zend_pm_label_set_next(context, true_label);
67576749
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
67586750
uint32_t end_label = zend_emit_jump(0);
@@ -6767,9 +6759,9 @@ static void zend_compile_or_pattern(zend_ast *ast, znode *expr_node, bool consum
67676759
context->inside_or_pattern = false;
67686760
}
67696761

6770-
static void zend_compile_and_pattern(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
6762+
static void zend_pm_compile_and(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
67716763
{
6772-
verify_parenthesized_compound_pattern(ast, ZEND_AST_OR_PATTERN);
6764+
zend_pm_verify_parenthesized_compound_pattern(ast, ZEND_AST_OR_PATTERN);
67736765

67746766
zend_ast_list *ast_list = zend_ast_get_list(ast);
67756767
uint32_t false_label = consume_expr ? zend_pm_label_create(context) : false_opnum;
@@ -6787,12 +6779,10 @@ static void zend_compile_and_pattern(zend_ast *ast, znode *expr_node, bool consu
67876779
zend_emit_jump(false_opnum);
67886780

67896781
zend_update_jump_target_to_next(jmp_end);
6790-
} else {
6791-
zend_pm_label_set_next(context, false_label);
67926782
}
67936783
}
67946784

6795-
static void zend_compile_type_pattern(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum)
6785+
static void zend_pm_compile_type(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum)
67966786
{
67976787
zend_ast *type_ast = ast->child[0];
67986788
bool nullable = type_ast->attr & ZEND_TYPE_NULLABLE;
@@ -6812,66 +6802,61 @@ static void zend_compile_type_pattern(zend_ast *ast, znode *expr_node, bool cons
68126802

68136803
znode result;
68146804
zend_emit_op(&result, ZEND_HAS_TYPE, expr_node, &type_node);
6815-
if (consume_expr && (expr_node->op_type & (IS_VAR|IS_TMP_VAR))) {
6805+
if (consume_expr) {
68166806
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
68176807
}
68186808
zend_emit_cond_jump(ZEND_JMPZ, &result, false_opnum);
68196809
}
68206810

6821-
static void zend_compile_binding_pattern(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
6811+
static void zend_pm_copy_tmp(znode *dest, znode *src, bool consume)
6812+
{
6813+
if (!consume && (src->op_type & (IS_VAR|IS_TMP_VAR))) {
6814+
zend_emit_op(dest, ZEND_COPY_TMP, src, NULL);
6815+
} else {
6816+
*dest = *src;
6817+
}
6818+
}
6819+
6820+
static void zend_pm_compile_binding(zend_ast *ast, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
68226821
{
68236822
if (context->inside_or_pattern) {
68246823
zend_error_noreturn(E_COMPILE_ERROR, "Must not bind to variables inside | pattern");
68256824
}
68266825

68276826
znode var_node;
68286827
var_node.op_type = IS_TMP_VAR;
6829-
var_node.u.op.var = context->first_tmp + context->num_bindings++;
6828+
var_node.u.op.var = context->first_binding_tmp + context->num_bindings++;
68306829

68316830
znode expr_copy_node;
6832-
if (!consume_expr && (expr_node->op_type & (IS_VAR|IS_TMP_VAR))) {
6833-
zend_emit_op(&expr_copy_node, ZEND_COPY_TMP, expr_node, NULL);
6834-
} else {
6835-
expr_copy_node = *expr_node;
6836-
}
6831+
zend_pm_copy_tmp(&expr_copy_node, expr_node, consume_expr);
68376832

68386833
zend_op *op = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &expr_copy_node, NULL);
68396834
SET_NODE(op->result, &var_node);
68406835
}
68416836

6842-
static void zend_pm_copy_tmp(znode *dest, znode *src)
6843-
{
6844-
if (src->op_type & (IS_VAR|IS_TMP_VAR)) {
6845-
zend_emit_op(dest, ZEND_COPY_TMP, src, NULL);
6846-
} else {
6847-
*dest = *src;
6848-
}
6849-
}
6850-
6851-
static void zend_compile_container_pattern(
6837+
static void zend_pm_compile_container(
68526838
zend_ast *ast,
68536839
znode *expr_node,
68546840
bool consume_expr,
68556841
uint32_t false_opnum,
68566842
zend_pm_context *context,
68576843
bool is_array
68586844
) {
6859-
// FIXME: These copies are annoying...
68606845
znode expr_copy_node;
68616846

68626847
uint32_t false_label = consume_expr ? zend_pm_label_create(context) : false_opnum;
68636848
zend_ast_list *element_list = zend_ast_get_list(ast->child[0]);
68646849

6865-
/* Make sure the value is actually an array. */
6866-
zend_pm_copy_tmp(&expr_copy_node, expr_node);
6850+
/* Make sure the value is actually of the right type. */
6851+
zend_pm_copy_tmp(&expr_copy_node, expr_node, false);
68676852
znode is_array_node;
68686853
zend_op *is_array_op = zend_emit_op(&is_array_node, ZEND_TYPE_CHECK, &expr_copy_node, NULL);
68696854
is_array_op->extended_value = is_array ? MAY_BE_ARRAY : MAY_BE_OBJECT;
68706855
zend_emit_cond_jump(ZEND_JMPZ, &is_array_node, false_label);
68716856

6872-
/* Make sure the array has the right size. */
68736857
if (is_array) {
6874-
zend_pm_copy_tmp(&expr_copy_node, expr_node);
6858+
/* Make sure the array has the right size. */
6859+
zend_pm_copy_tmp(&expr_copy_node, expr_node, false);
68756860
znode count_node;
68766861
zend_emit_op(&count_node, ZEND_COUNT, &expr_copy_node, NULL);
68776862

@@ -6894,7 +6879,7 @@ static void zend_compile_container_pattern(
68946879
zend_ast *element_value_ast = element_ast->child[1];
68956880

68966881
/* Fetch element. */
6897-
zend_pm_copy_tmp(&expr_copy_node, expr_node);
6882+
zend_pm_copy_tmp(&expr_copy_node, expr_node, false);
68986883
znode element_value_node, element_key_node;
68996884
element_key_node.op_type = IS_CONST;
69006885
if (element_key_ast) {
@@ -6908,9 +6893,6 @@ static void zend_compile_container_pattern(
69086893
zend_emit_op_tmp(&element_value_node, ZEND_FETCH_DIM_IS, &expr_copy_node, &element_key_node);
69096894
} else {
69106895
zend_op *fetch_prop_op = zend_emit_op_tmp(&element_value_node, ZEND_FETCH_OBJ_R, &expr_copy_node, &element_key_node);
6911-
// FIXME: Are those necessary?
6912-
convert_to_string(CT_CONSTANT(fetch_prop_op->op2));
6913-
zend_string_hash_val(Z_STR_P(CT_CONSTANT(fetch_prop_op->op2)));
69146896
fetch_prop_op->extended_value = zend_alloc_cache_slots(3);
69156897
}
69166898

@@ -6943,32 +6925,31 @@ static void zend_compile_pattern(zend_ast *ast, znode *expr_node, bool consume_e
69436925
}
69446926
break;
69456927
case ZEND_AST_EXPR_LIKE_PATTERN:
6946-
zend_compile_expr_like_pattern(ast, expr_node, consume_expr, false_opnum);
6928+
zend_pm_compile_expr_like(ast, expr_node, consume_expr, false_opnum);
69476929
break;
69486930
case ZEND_AST_OR_PATTERN:
6949-
zend_compile_or_pattern(ast, expr_node, consume_expr, false_opnum, context);
6931+
zend_pm_compile_or(ast, expr_node, consume_expr, false_opnum, context);
69506932
break;
69516933
case ZEND_AST_AND_PATTERN:
6952-
zend_compile_and_pattern(ast, expr_node, consume_expr, false_opnum, context);
6934+
zend_pm_compile_and(ast, expr_node, consume_expr, false_opnum, context);
69536935
break;
69546936
case ZEND_AST_TYPE_PATTERN:
6955-
zend_compile_type_pattern(ast, expr_node, consume_expr, false_opnum);
6937+
zend_pm_compile_type(ast, expr_node, consume_expr, false_opnum);
69566938
break;
69576939
case ZEND_AST_BINDING_PATTERN:
6958-
zend_compile_binding_pattern(ast, expr_node, consume_expr, false_opnum, context);
6940+
zend_pm_compile_binding(ast, expr_node, consume_expr, false_opnum, context);
69596941
break;
69606942
case ZEND_AST_ARRAY_PATTERN:
6961-
zend_compile_container_pattern(ast, expr_node, consume_expr, false_opnum, context, true);
6943+
zend_pm_compile_container(ast, expr_node, consume_expr, false_opnum, context, true);
69626944
break;
69636945
case ZEND_AST_OBJECT_PATTERN:
6964-
zend_compile_container_pattern(ast, expr_node, consume_expr, false_opnum, context, false);
6946+
zend_pm_compile_container(ast, expr_node, consume_expr, false_opnum, context, false);
69656947
break;
6966-
// ZEND_AST_RANGE_PATTERN
69676948
EMPTY_SWITCH_DEFAULT_CASE();
69686949
}
69696950
}
69706951

6971-
static void pattern_matching_count_bindings(zend_ast **ast_ptr, void *context)
6952+
static void zend_pm_count_bindings(zend_ast **ast_ptr, void *context)
69726953
{
69736954
zend_ast *ast = *ast_ptr;
69746955
if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
@@ -6980,10 +6961,10 @@ static void pattern_matching_count_bindings(zend_ast **ast_ptr, void *context)
69806961
pattern_context->num_bindings++;
69816962
}
69826963

6983-
zend_ast_apply(ast, pattern_matching_count_bindings, context);
6964+
zend_ast_apply(ast, zend_pm_count_bindings, context);
69846965
}
69856966

6986-
static void pattern_matching_emit_assigns(zend_ast **ast_ptr, void *context)
6967+
static void zend_pm_emit_assigns(zend_ast **ast_ptr, void *context)
69876968
{
69886969
zend_ast *ast = *ast_ptr;
69896970
if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
@@ -6999,20 +6980,20 @@ static void pattern_matching_emit_assigns(zend_ast **ast_ptr, void *context)
69996980

70006981
znode value_node;
70016982
value_node.op_type = IS_TMP_VAR;
7002-
value_node.u.op.var = pattern_context->first_tmp + pattern_context->num_bindings++;
6983+
value_node.u.op.var = pattern_context->first_binding_tmp + pattern_context->num_bindings++;
70036984

70046985
zend_emit_op(NULL, ZEND_ASSIGN, &var_node, &value_node);
70056986
}
70066987

7007-
zend_ast_apply(ast, pattern_matching_emit_assigns, context);
6988+
zend_ast_apply(ast, zend_pm_emit_assigns, context);
70086989
}
70096990

70106991
static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zend_ast *pattern_ast)
70116992
{
7012-
// FIXME: Do we need a copy of expr_node? We may observe side-effects, e.g.
7013-
// through hooks. Do we care?
7014-
7015-
/* When expr is a CONST, create a copy to avoid inserting multiple literals. */
6993+
/* When expr is a CONST, create a copy to avoid inserting multiple literals.
6994+
* A cleaner solution would be to remember whether a literal has already been
6995+
* inserted. This could be stored in znode.flag and handled in SET_NODE().
6996+
* However, this field is unfortunately inconsistently initialized. */
70166997
znode expr_copy_node;
70176998
if (expr_node->op_type == IS_CONST) {
70186999
zend_emit_op(&expr_copy_node, ZEND_QM_ASSIGN, expr_node, NULL);
@@ -7023,14 +7004,15 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70237004

70247005
zend_pm_context context = {0};
70257006
zend_pm_context_init(&context);
7026-
pattern_matching_count_bindings(&pattern_ast, &context);
7027-
context.first_tmp = CG(active_op_array)->T;
7007+
zend_pm_count_bindings(&pattern_ast, &context);
7008+
context.first_binding_tmp = CG(active_op_array)->T;
70287009
CG(active_op_array)->T += context.num_bindings;
70297010

7011+
/* Initialize temporaries used for assignment */
70307012
for (uint32_t i = 0; i < context.num_bindings; i++) {
70317013
znode var_node;
70327014
var_node.op_type = IS_TMP_VAR;
7033-
var_node.u.op.var = context.first_tmp + i;
7015+
var_node.u.op.var = context.first_binding_tmp + i;
70347016
znode null_node;
70357017
null_node.op_type = IS_CONST;
70367018
ZVAL_NULL(&null_node.u.constant);
@@ -7044,7 +7026,7 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70447026
zend_compile_pattern(pattern_ast, &expr_copy_node, consume_expr, false_label, &context);
70457027

70467028
context.num_bindings = 0;
7047-
pattern_matching_emit_assigns(&pattern_ast, &context);
7029+
zend_pm_emit_assigns(&pattern_ast, &context);
70487030

70497031
znode true_node;
70507032
true_node.op_type = IS_CONST;
@@ -7055,15 +7037,14 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70557037
zend_op *opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &true_node, NULL);
70567038
SET_NODE(opline_qm_assign->result, result);
70577039
}
7058-
70597040
uint32_t jmp_end = zend_emit_jump(0);
70607041

70617042
zend_pm_label_set_next(&context, false_label);
70627043

70637044
for (uint32_t i = 0; i < context.num_bindings; i++) {
70647045
znode var_node;
70657046
var_node.op_type = IS_TMP_VAR;
7066-
var_node.u.op.var = context.first_tmp + i;
7047+
var_node.u.op.var = context.first_binding_tmp + i;
70677048
zend_emit_op(NULL, ZEND_FREE, &var_node, NULL);
70687049
}
70697050

0 commit comments

Comments
 (0)