summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorIlija Tovilo <ilija.tovilo@me.com>2020-04-09 22:36:37 +0200
committerIlija Tovilo <ilija.tovilo@me.com>2020-07-09 23:52:17 +0200
commit9fa1d1330138ac424f990ff03e62721120aaaec3 (patch)
treeca3550c82b86ccf844745fbe80c77134ed5cbef4 /ext
parentc60d0dc2f41f1d4817414e37a39ae87c5677e31a (diff)
downloadphp-git-9fa1d1330138ac424f990ff03e62721120aaaec3.tar.gz
Implement match expression
RFC: https://wiki.php.net/rfc/match_expression_v2 Closes GH-5371.
Diffstat (limited to 'ext')
-rw-r--r--ext/opcache/Optimizer/block_pass.c11
-rw-r--r--ext/opcache/Optimizer/dce.c5
-rw-r--r--ext/opcache/Optimizer/dfa_pass.c46
-rw-r--r--ext/opcache/Optimizer/pass1.c2
-rw-r--r--ext/opcache/Optimizer/sccp.c41
-rw-r--r--ext/opcache/Optimizer/zend_cfg.c16
-rw-r--r--ext/opcache/Optimizer/zend_dump.c6
-rw-r--r--ext/opcache/Optimizer/zend_inference.c4
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c25
-rw-r--r--ext/opcache/jit/zend_jit.c6
-rw-r--r--ext/opcache/jit/zend_jit_trace.c3
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc7
-rw-r--r--ext/opcache/tests/match/001.phpt71
-rw-r--r--ext/opcache/tests/match/002.phpt57
-rw-r--r--ext/opcache/tests/match/003.phpt74
-rw-r--r--ext/opcache/tests/match/004.phpt93
-rw-r--r--ext/opcache/zend_file_cache.c1
-rw-r--r--ext/opcache/zend_persist.c1
-rw-r--r--ext/standard/tests/file/fnmatch_variation.phpt10
-rw-r--r--ext/tokenizer/tokenizer_data.c22
20 files changed, 424 insertions, 77 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 59429082f7..aee3931f05 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -115,6 +115,10 @@ static int get_const_switch_target(zend_cfg *cfg, zend_op_array *op_array, zend_
/* fallback to next block */
return block->successors[block->successors_count - 1];
}
+ if (opline->opcode == ZEND_MATCH && Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_STRING) {
+ /* always jump to the default arm */
+ return block->successors[block->successors_count - 1];
+ }
if (Z_TYPE_P(val) == IS_LONG) {
zv = zend_hash_index_find(jumptable, Z_LVAL_P(val));
} else {
@@ -123,7 +127,7 @@ static int get_const_switch_target(zend_cfg *cfg, zend_op_array *op_array, zend_
}
if (!zv) {
/* default */
- return block->successors[block->successors_count - 2];
+ return block->successors[block->successors_count - (opline->opcode == ZEND_MATCH ? 1 : 2)];
}
return cfg->map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv))];
}
@@ -369,6 +373,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
/* SWITCH variable will be deleted later by FREE, so we can't optimize it */
Tsource[VAR_NUM(opline->op1.var)] = NULL;
@@ -387,6 +392,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
break;
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
case ZEND_COPY_TMP:
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
/* Variable will be deleted later by FREE, so we can't optimize it */
@@ -1046,11 +1052,12 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op
break;
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
zval *zv;
uint32_t s = 0;
- ZEND_ASSERT(b->successors_count == 2 + zend_hash_num_elements(jumptable));
+ ZEND_ASSERT(b->successors_count == (opline->opcode == ZEND_MATCH ? 1 : 2) + zend_hash_num_elements(jumptable));
ZEND_HASH_FOREACH_VAL(jumptable, zv) {
Z_LVAL_P(zv) = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[s++]].start);
diff --git a/ext/opcache/Optimizer/dce.c b/ext/opcache/Optimizer/dce.c
index 43f2ef71a2..9f533ea167 100644
--- a/ext/opcache/Optimizer/dce.c
+++ b/ext/opcache/Optimizer/dce.c
@@ -106,6 +106,7 @@ static inline zend_bool may_have_side_effects(
case ZEND_IS_SMALLER:
case ZEND_IS_SMALLER_OR_EQUAL:
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
case ZEND_CAST:
case ZEND_ROPE_INIT:
case ZEND_ROPE_ADD:
@@ -146,6 +147,7 @@ static inline zend_bool may_have_side_effects(
case ZEND_ECHO:
case ZEND_INCLUDE_OR_EVAL:
case ZEND_THROW:
+ case ZEND_MATCH_ERROR:
case ZEND_EXT_STMT:
case ZEND_EXT_FCALL_BEGIN:
case ZEND_EXT_FCALL_END:
@@ -391,7 +393,8 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) {
if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) {
if (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)
- && opline->opcode != ZEND_CASE) {
+ && opline->opcode != ZEND_CASE
+ && opline->opcode != ZEND_CASE_STRICT) {
free_var = ssa_op->op1_use;
free_var_type = opline->op1_type;
}
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c
index a8bff00557..0b69323980 100644
--- a/ext/opcache/Optimizer/dfa_pass.c
+++ b/ext/opcache/Optimizer/dfa_pass.c
@@ -641,6 +641,7 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa
break;
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
zval *zv;
@@ -895,48 +896,29 @@ optimize_jmpnz:
break;
}
case ZEND_SWITCH_LONG:
- if (opline->op1_type == IS_CONST) {
- zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
- if (Z_TYPE_P(zv) != IS_LONG) {
- removed_ops++;
- MAKE_NOP(opline);
- opline->extended_value = 0;
- take_successor_ex(ssa, block_num, block, block->successors[0]);
- goto optimize_nop;
- } else {
- HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
- zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(zv));
- uint32_t target;
-
- if (jmp_zv) {
- target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
- } else {
- target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
- }
- opline->opcode = ZEND_JMP;
- opline->extended_value = 0;
- SET_UNUSED(opline->op1);
- ZEND_SET_OP_JMP_ADDR(opline, opline->op1, op_array->opcodes + target);
- SET_UNUSED(opline->op2);
- take_successor_ex(ssa, block_num, block, ssa->cfg.map[target]);
- goto optimize_jmp;
- }
- }
- break;
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
if (opline->op1_type == IS_CONST) {
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
- if (Z_TYPE_P(zv) != IS_STRING) {
+ zend_uchar type = Z_TYPE_P(zv);
+ zend_bool correct_type =
+ (opline->opcode == ZEND_SWITCH_LONG && type == IS_LONG)
+ || (opline->opcode == ZEND_SWITCH_STRING && type == IS_STRING)
+ || (opline->opcode == ZEND_MATCH && (type == IS_LONG || type == IS_STRING));
+
+ if (!correct_type) {
removed_ops++;
MAKE_NOP(opline);
opline->extended_value = 0;
- take_successor_ex(ssa, block_num, block, block->successors[0]);
+ take_successor_ex(ssa, block_num, block, block->successors[block->successors_count - 1]);
goto optimize_nop;
} else {
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
- zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(zv));
- uint32_t target;
+ zval *jmp_zv = type == IS_LONG
+ ? zend_hash_index_find(jmptable, Z_LVAL_P(zv))
+ : zend_hash_find(jmptable, Z_STR_P(zv));
+ uint32_t target;
if (jmp_zv) {
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
} else {
diff --git a/ext/opcache/Optimizer/pass1.c b/ext/opcache/Optimizer/pass1.c
index 3beb1788a3..fee0e1eac3 100644
--- a/ext/opcache/Optimizer/pass1.c
+++ b/ext/opcache/Optimizer/pass1.c
@@ -82,6 +82,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
case ZEND_BOOL_XOR:
case ZEND_SPACESHIP:
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
if (opline->op1_type == IS_CONST &&
opline->op2_type == IS_CONST) {
/* binary operation with constant operands */
@@ -663,6 +664,7 @@ constant_binary_op:
case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_THROW:
+ case ZEND_MATCH_ERROR:
case ZEND_CATCH:
case ZEND_FAST_CALL:
case ZEND_FAST_RET:
diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c
index c51b5c3ee2..ee8ccc34a7 100644
--- a/ext/opcache/Optimizer/sccp.c
+++ b/ext/opcache/Optimizer/sccp.c
@@ -300,10 +300,15 @@ static zend_bool try_replace_op1(
switch (opline->opcode) {
case ZEND_CASE:
opline->opcode = ZEND_IS_EQUAL;
- /* break missing intentionally */
+ goto replace_op1_simple;
+ case ZEND_CASE_STRICT:
+ opline->opcode = ZEND_IS_IDENTICAL;
+ goto replace_op1_simple;
case ZEND_FETCH_LIST_R:
case ZEND_SWITCH_STRING:
case ZEND_SWITCH_LONG:
+ case ZEND_MATCH:
+replace_op1_simple:
if (Z_TYPE(zv) == IS_STRING) {
zend_string_hash_val(Z_STR(zv));
}
@@ -1460,6 +1465,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
case ZEND_BW_XOR:
case ZEND_BOOL_XOR:
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
SKIP_IF_TOP(op1);
SKIP_IF_TOP(op2);
@@ -1986,11 +1992,23 @@ static void sccp_mark_feasible_successors(
s = zend_hash_num_elements(Z_ARR_P(op1)) != 0;
break;
case ZEND_SWITCH_LONG:
- if (Z_TYPE_P(op1) == IS_LONG) {
+ case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
+ {
+ zend_bool strict_comparison = opline->opcode == ZEND_MATCH;
+ zend_uchar type = Z_TYPE_P(op1);
+ zend_bool correct_type =
+ (opline->opcode == ZEND_SWITCH_LONG && type == IS_LONG)
+ || (opline->opcode == ZEND_SWITCH_STRING && type == IS_STRING)
+ || (opline->opcode == ZEND_MATCH && (type == IS_LONG || type == IS_STRING));
+
+ if (correct_type) {
zend_op_array *op_array = scdf->op_array;
zend_ssa *ssa = scdf->ssa;
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
- zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(op1));
+ zval *jmp_zv = type == IS_LONG
+ ? zend_hash_index_find(jmptable, Z_LVAL_P(op1))
+ : zend_hash_find(jmptable, Z_STR_P(op1));
int target;
if (jmp_zv) {
@@ -2000,27 +2018,16 @@ static void sccp_mark_feasible_successors(
}
scdf_mark_edge_feasible(scdf, block_num, target);
return;
- }
- s = 0;
- break;
- case ZEND_SWITCH_STRING:
- if (Z_TYPE_P(op1) == IS_STRING) {
+ } else if (strict_comparison) {
zend_op_array *op_array = scdf->op_array;
zend_ssa *ssa = scdf->ssa;
- HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
- zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(op1));
- int target;
-
- if (jmp_zv) {
- target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv))];
- } else {
- target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
- }
+ int target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
scdf_mark_edge_feasible(scdf, block_num, target);
return;
}
s = 0;
break;
+ }
default:
for (s = 0; s < block->successors_count; s++) {
scdf_mark_edge_feasible(scdf, block_num, block->successors[s]);
diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c
index 6ac5781e09..d80edda3e1 100644
--- a/ext/opcache/Optimizer/zend_cfg.c
+++ b/ext/opcache/Optimizer/zend_cfg.c
@@ -73,7 +73,11 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc
succ->flags |= ZEND_BB_FOLLOW;
}
} else {
- ZEND_ASSERT(opcode == ZEND_SWITCH_LONG || opcode == ZEND_SWITCH_STRING);
+ ZEND_ASSERT(
+ opcode == ZEND_SWITCH_LONG
+ || opcode == ZEND_SWITCH_STRING
+ || opcode == ZEND_MATCH
+ );
if (i == b->successors_count - 1) {
succ->flags |= ZEND_BB_FOLLOW | ZEND_BB_TARGET;
} else {
@@ -296,6 +300,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
case ZEND_RETURN_BY_REF:
case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
+ case ZEND_MATCH_ERROR:
if (i + 1 < op_array->last) {
BB_START(i + 1);
}
@@ -391,6 +396,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
break;
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL_P(CRT_CONSTANT(opline->op2));
zval *zv;
@@ -507,6 +513,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
case ZEND_GENERATOR_RETURN:
case ZEND_EXIT:
case ZEND_THROW:
+ case ZEND_MATCH_ERROR:
break;
case ZEND_JMP:
block->successors_count = 1;
@@ -557,12 +564,13 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
break;
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL_P(CRT_CONSTANT(opline->op2));
zval *zv;
uint32_t s = 0;
- block->successors_count = 2 + zend_hash_num_elements(jumptable);
+ block->successors_count = (opline->opcode == ZEND_MATCH ? 1 : 2) + zend_hash_num_elements(jumptable);
block->successors = zend_arena_calloc(arena, block->successors_count, sizeof(int));
ZEND_HASH_FOREACH_VAL(jumptable, zv) {
@@ -570,7 +578,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
} ZEND_HASH_FOREACH_END();
block->successors[s++] = block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
- block->successors[s++] = j + 1;
+ if (opline->opcode != ZEND_MATCH) {
+ block->successors[s++] = j + 1;
+ }
break;
}
default:
diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c
index dfd939f332..ce23c4d473 100644
--- a/ext/opcache/Optimizer/zend_dump.c
+++ b/ext/opcache/Optimizer/zend_dump.c
@@ -615,7 +615,11 @@ void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, cons
if (opline->op2_type == IS_CONST) {
zval *op = CRT_CONSTANT(opline->op2);
- if (opline->opcode == ZEND_SWITCH_LONG || opline->opcode == ZEND_SWITCH_STRING) {
+ if (
+ opline->opcode == ZEND_SWITCH_LONG
+ || opline->opcode == ZEND_SWITCH_STRING
+ || opline->opcode == ZEND_MATCH
+ ) {
HashTable *jumptable = Z_ARRVAL_P(op);
zend_string *key;
zend_ulong num_key;
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c
index c4189975d5..00708ca11b 100644
--- a/ext/opcache/Optimizer/zend_inference.c
+++ b/ext/opcache/Optimizer/zend_inference.c
@@ -2413,6 +2413,7 @@ static zend_always_inline int _zend_update_type_info(
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
case ZEND_BOOL:
case ZEND_ISSET_ISEMPTY_CV:
case ZEND_ISSET_ISEMPTY_VAR:
@@ -4312,6 +4313,7 @@ int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const ze
if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) {
switch (opline->opcode) {
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
case ZEND_FE_FETCH_R:
case ZEND_FE_FETCH_RW:
case ZEND_FETCH_LIST_R:
@@ -4380,12 +4382,14 @@ int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const ze
case ZEND_COALESCE:
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
case ZEND_ISSET_ISEMPTY_VAR:
case ZEND_ISSET_ISEMPTY_CV:
case ZEND_FUNC_NUM_ARGS:
case ZEND_FUNC_GET_ARGS:
case ZEND_COPY_TMP:
case ZEND_CHECK_FUNC_ARG:
+ case ZEND_CASE_STRICT:
return 0;
case ZEND_INIT_FCALL:
/* can't throw, because call is resolved at compile time */
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index 8456c46078..78b5893b2f 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -293,6 +293,7 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
* zend_optimizer_replace_by_const() supports this. */
return 0;
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
case ZEND_FETCH_LIST_R:
case ZEND_COPY_TMP:
case ZEND_FETCH_CLASS_NAME:
@@ -558,7 +559,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
break;
/* In most cases IS_TMP_VAR operand may be used only once.
* The operands are usually destroyed by the opcode handler.
- * ZEND_CASE and ZEND_FETCH_LIST_R are exceptions, they keeps operand
+ * ZEND_CASE[_STRICT] and ZEND_FETCH_LIST_R are exceptions, they keeps operand
* unchanged, and allows its reuse. these instructions
* usually terminated by ZEND_FREE that finally kills the value.
*/
@@ -587,17 +588,25 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
}
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
- case ZEND_CASE: {
+ case ZEND_MATCH:
+ case ZEND_CASE:
+ case ZEND_CASE_STRICT: {
zend_op *end = op_array->opcodes + op_array->last;
while (opline < end) {
if (opline->op1_type == type && opline->op1.var == var) {
- if (opline->opcode == ZEND_CASE
- || opline->opcode == ZEND_SWITCH_LONG
- || opline->opcode == ZEND_SWITCH_STRING) {
+ if (
+ opline->opcode == ZEND_CASE
+ || opline->opcode == ZEND_CASE_STRICT
+ || opline->opcode == ZEND_SWITCH_LONG
+ || opline->opcode == ZEND_SWITCH_STRING
+ || opline->opcode == ZEND_MATCH
+ ) {
zval v;
if (opline->opcode == ZEND_CASE) {
opline->opcode = ZEND_IS_EQUAL;
+ } else if (opline->opcode == ZEND_CASE_STRICT) {
+ opline->opcode = ZEND_IS_IDENTICAL;
}
ZVAL_COPY(&v, val);
if (Z_TYPE(v) == IS_STRING) {
@@ -687,6 +696,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z
break;
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
zval *zv;
@@ -731,6 +741,7 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_
break;
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
zval *zv;
@@ -1105,6 +1116,7 @@ static void zend_redo_pass_two(zend_op_array *op_array)
case ZEND_FE_FETCH_RW:
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
/* relative extended_value don't have to be changed */
break;
#endif
@@ -1115,6 +1127,7 @@ static void zend_redo_pass_two(zend_op_array *op_array)
case ZEND_IS_SMALLER:
case ZEND_IS_SMALLER_OR_EQUAL:
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
case ZEND_ISSET_ISEMPTY_CV:
case ZEND_ISSET_ISEMPTY_VAR:
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
@@ -1225,6 +1238,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
case ZEND_FE_FETCH_RW:
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
/* relative extended_value don't have to be changed */
break;
#endif
@@ -1235,6 +1249,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
case ZEND_IS_SMALLER:
case ZEND_IS_SMALLER_OR_EQUAL:
case ZEND_CASE:
+ case ZEND_CASE_STRICT:
case ZEND_ISSET_ISEMPTY_CV:
case ZEND_ISSET_ISEMPTY_VAR:
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c
index 8c46cf9676..d0c1178d69 100644
--- a/ext/opcache/jit/zend_jit.c
+++ b/ext/opcache/jit/zend_jit.c
@@ -2120,7 +2120,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
&& ssa->cfg.blocks[b].start != 0
&& (op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_NOP
|| op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_LONG
- || op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_STRING)) {
+ || op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_SWITCH_STRING
+ || op_array->opcodes[ssa->cfg.blocks[b].start - 1].opcode == ZEND_MATCH)) {
if (!zend_jit_reset_opline(&dasm_state, op_array->opcodes + ssa->cfg.blocks[b].start)
|| !zend_jit_set_valid_ip(&dasm_state, op_array->opcodes + ssa->cfg.blocks[b].start)) {
goto jit_failure;
@@ -2851,6 +2852,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
goto done;
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
if (!zend_jit_switch(&dasm_state, opline, op_array, ssa)) {
goto jit_failure;
}
@@ -2898,6 +2900,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
case ZEND_OP_DATA:
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
break;
case ZEND_JMP:
if (JIT_G(opt_level) < ZEND_JIT_LEVEL_INLINE) {
@@ -2920,6 +2923,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
case ZEND_RETURN_BY_REF:
case ZEND_RETURN:
case ZEND_EXIT:
+ case ZEND_MATCH_ERROR:
/* switch through trampoline */
case ZEND_YIELD:
case ZEND_YIELD_FROM:
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index 8bbd3debee..278b3e6151 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -279,6 +279,7 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
case ZEND_FE_FETCH_RW:
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
/* branch opcodes */
return 1;
case ZEND_NEW:
@@ -296,6 +297,7 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
case ZEND_YIELD:
case ZEND_YIELD_FROM:
case ZEND_INCLUDE_OR_EVAL:
+ case ZEND_MATCH_ERROR:
/* unsupported */
return 1;
case ZEND_DO_FCALL:
@@ -3943,6 +3945,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
#if 0
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
if (!zend_jit_switch(&dasm_state, opline, op_array, op_array_ssa)) {
goto jit_failure;
}
diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc
index cfd3b0f4cb..46145a83bb 100644
--- a/ext/opcache/jit/zend_jit_x86.dasc
+++ b/ext/opcache/jit/zend_jit_x86.dasc
@@ -11377,6 +11377,13 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o
{
HashTable *jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
+ // TODO: Implement for match instructions
+ if (opline->opcode == ZEND_MATCH) {
+ // Since the match expression doesn't have a IS_IDENTICAL/JMPNZ chain
+ // we can't skip the jumptable and thus can't JIT the function
+ return 0;
+ }
+
if (opline->op1_type == IS_CONST) {
zval *zv = RT_CONSTANT(opline, opline->op1);
zval *jump_zv;
diff --git a/ext/opcache/tests/match/001.phpt b/ext/opcache/tests/match/001.phpt
new file mode 100644
index 0000000000..0f6c4f0707
--- /dev/null
+++ b/ext/opcache/tests/match/001.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Match expression string jump table
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.opt_debug_level=0x20000
+--SKIPIF--
+<?php require_once(__DIR__ . '/../skipif.inc'); ?>
+--FILE--
+<?php
+
+function test($char) {
+ return match ($char) {
+ 'a' => 'a',
+ 'b', 'c' => 'b, c',
+ 'd' => 'd',
+ 'e', 'f' => 'e, f',
+ 'g' => 'g',
+ 'h', 'i' => 'h, i',
+ };
+}
+
+foreach (range('a', 'i') as $char) {
+ var_dump(test($char));
+}
+
+--EXPECTF--
+$_main:
+ ; (lines=15, args=0, vars=1, tmps=2)
+ ; (after optimizer)
+ ; %s
+0000 INIT_FCALL 2 %d string("range")
+0001 SEND_VAL string("a") 1
+0002 SEND_VAL string("i") 2
+0003 V2 = DO_ICALL
+0004 V1 = FE_RESET_R V2 0013
+0005 FE_FETCH_R V1 CV0($char) 0013
+0006 INIT_FCALL 1 %d string("var_dump")
+0007 INIT_FCALL 1 %d string("test")
+0008 SEND_VAR CV0($char) 1
+0009 V2 = DO_UCALL
+0010 SEND_VAR V2 1
+0011 DO_ICALL
+0012 JMP 0005
+0013 FE_FREE V1
+0014 RETURN int(1)
+LIVE RANGES:
+ 1: 0005 - 0013 (loop)
+
+test:
+ ; (lines=9, args=1, vars=1, tmps=0)
+ ; (after optimizer)
+ ; %s
+0000 CV0($char) = RECV 1
+0001 MATCH CV0($char) "a": 0002, "b": 0003, "c": 0003, "d": 0004, "e": 0005, "f": 0005, "g": 0006, "h": 0007, "i": 0007, default: 0008
+0002 RETURN string("a")
+0003 RETURN string("b, c")
+0004 RETURN string("d")
+0005 RETURN string("e, f")
+0006 RETURN string("g")
+0007 RETURN string("h, i")
+0008 MATCH_ERROR CV0($char)
+string(1) "a"
+string(4) "b, c"
+string(4) "b, c"
+string(1) "d"
+string(4) "e, f"
+string(4) "e, f"
+string(1) "g"
+string(4) "h, i"
+string(4) "h, i"
diff --git a/ext/opcache/tests/match/002.phpt b/ext/opcache/tests/match/002.phpt
new file mode 100644
index 0000000000..22f29eeb8b
--- /dev/null
+++ b/ext/opcache/tests/match/002.phpt
@@ -0,0 +1,57 @@
+--TEST--
+Test match jump table optimizer
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.opt_debug_level=0x20000
+--SKIPIF--
+<?php require_once(__DIR__ . '/../skipif.inc'); ?>
+--FILE--
+<?php
+
+function test() {
+ $x = '2';
+ echo match($x) {
+ 1, 2, 3, 4, 5 => throw new RuntimeException(),
+ default => "No match\n",
+ };
+}
+test();
+
+function test2() {
+ $x = 2;
+ echo match($x) {
+ '1', '2', '3', '4', '5' => throw new RuntimeException(),
+ default => "No match\n",
+ };
+}
+test2();
+
+--EXPECTF--
+$_main:
+ ; (lines=5, args=0, vars=0, tmps=0)
+ ; (after optimizer)
+ ; %s
+0000 INIT_FCALL 0 %d string("test")
+0001 DO_UCALL
+0002 INIT_FCALL 0 %d string("test2")
+0003 DO_UCALL
+0004 RETURN int(1)
+
+test:
+ ; (lines=2, args=0, vars=0, tmps=0)
+ ; (after optimizer)
+ ; %s
+0000 ECHO string("No match
+")
+0001 RETURN null
+
+test2:
+ ; (lines=2, args=0, vars=0, tmps=0)
+ ; (after optimizer)
+ ; %s
+0000 ECHO string("No match
+")
+0001 RETURN null
+No match
+No match
diff --git a/ext/opcache/tests/match/003.phpt b/ext/opcache/tests/match/003.phpt
new file mode 100644
index 0000000000..f7f8896073
--- /dev/null
+++ b/ext/opcache/tests/match/003.phpt
@@ -0,0 +1,74 @@
+--TEST--
+Match expression long jump table
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.opt_debug_level=0x20000
+--SKIPIF--
+<?php require_once(__DIR__ . '/../skipif.inc'); ?>
+--FILE--
+<?php
+
+function test($char) {
+ return match ($char) {
+ 1 => '1',
+ 2, 3 => '2, 3',
+ 4 => '4',
+ 5, 6 => '5, 6',
+ 7 => '7',
+ 8, 9 => '8, 9',
+ default => 'default'
+ };
+}
+
+foreach (range(0, 10) as $char) {
+ var_dump(test($char));
+}
+
+--EXPECTF--
+$_main:
+ ; (lines=15, args=0, vars=1, tmps=2)
+ ; (after optimizer)
+ ; %s
+0000 INIT_FCALL 2 %d string("range")
+0001 SEND_VAL int(0) 1
+0002 SEND_VAL int(10) 2
+0003 V2 = DO_ICALL
+0004 V1 = FE_RESET_R V2 0013
+0005 FE_FETCH_R V1 CV0($char) 0013
+0006 INIT_FCALL 1 %d string("var_dump")
+0007 INIT_FCALL 1 %d string("test")
+0008 SEND_VAR CV0($char) 1
+0009 V2 = DO_UCALL
+0010 SEND_VAR V2 1
+0011 DO_ICALL
+0012 JMP 0005
+0013 FE_FREE V1
+0014 RETURN int(1)
+LIVE RANGES:
+ 1: 0005 - 0013 (loop)
+
+test:
+ ; (lines=9, args=1, vars=1, tmps=0)
+ ; (after optimizer)
+ ; %s
+0000 CV0($char) = RECV 1
+0001 MATCH CV0($char) 1: 0002, 2: 0003, 3: 0003, 4: 0004, 5: 0005, 6: 0005, 7: 0006, 8: 0007, 9: 0007, default: 0008
+0002 RETURN string("1")
+0003 RETURN string("2, 3")
+0004 RETURN string("4")
+0005 RETURN string("5, 6")
+0006 RETURN string("7")
+0007 RETURN string("8, 9")
+0008 RETURN string("default")
+string(7) "default"
+string(1) "1"
+string(4) "2, 3"
+string(4) "2, 3"
+string(1) "4"
+string(4) "5, 6"
+string(4) "5, 6"
+string(1) "7"
+string(4) "8, 9"
+string(4) "8, 9"
+string(7) "default"
diff --git a/ext/opcache/tests/match/004.phpt b/ext/opcache/tests/match/004.phpt
new file mode 100644
index 0000000000..f84a0b832d
--- /dev/null
+++ b/ext/opcache/tests/match/004.phpt
@@ -0,0 +1,93 @@
+--TEST--
+Match expression mixed jump table
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.opt_debug_level=0x20000
+--SKIPIF--
+<?php require_once(__DIR__ . '/../skipif.inc'); ?>
+--FILE--
+<?php
+
+function test($value) {
+ return match ($value) {
+ 1 => '1 int',
+ '1' => '1 string',
+ 2 => '2 int',
+ '2' => '2 string',
+ 3 => '3 int',
+ '3' => '3 string',
+ 4 => '4 int',
+ '4' => '4 string',
+ 5 => '5 int',
+ '5' => '5 string',
+ default => 'default',
+ };
+}
+
+foreach (range(0, 6) as $number) {
+ var_dump(test($number));
+ var_dump(test((string) $number));
+}
+
+--EXPECTF--
+$_main:
+ ; (lines=22, args=0, vars=1, tmps=2)
+ ; (after optimizer)
+ ; %s.php:1-24
+0000 INIT_FCALL 2 %d string("range")
+0001 SEND_VAL int(0) 1
+0002 SEND_VAL int(6) 2
+0003 V2 = DO_ICALL
+0004 V1 = FE_RESET_R V2 0020
+0005 FE_FETCH_R V1 CV0($number) 0020
+0006 INIT_FCALL 1 %d string("var_dump")
+0007 INIT_FCALL 1 %d string("test")
+0008 SEND_VAR CV0($number) 1
+0009 V2 = DO_UCALL
+0010 SEND_VAR V2 1
+0011 DO_ICALL
+0012 INIT_FCALL 1 %d string("var_dump")
+0013 INIT_FCALL 1 %d string("test")
+0014 T2 = CAST (string) CV0($number)
+0015 SEND_VAL T2 1
+0016 V2 = DO_UCALL
+0017 SEND_VAR V2 1
+0018 DO_ICALL
+0019 JMP 0005
+0020 FE_FREE V1
+0021 RETURN int(1)
+LIVE RANGES:
+ 1: 0005 - 0020 (loop)
+
+test:
+ ; (lines=13, args=1, vars=1, tmps=0)
+ ; (after optimizer)
+ ; %s.php:3-17
+0000 CV0($value) = RECV 1
+0001 MATCH CV0($value) 1: 0002, "1": 0003, 2: 0004, "2": 0005, 3: 0006, "3": 0007, 4: 0008, "4": 0009, 5: 0010, "5": 0011, default: 0012
+0002 RETURN string("1 int")
+0003 RETURN string("1 string")
+0004 RETURN string("2 int")
+0005 RETURN string("2 string")
+0006 RETURN string("3 int")
+0007 RETURN string("3 string")
+0008 RETURN string("4 int")
+0009 RETURN string("4 string")
+0010 RETURN string("5 int")
+0011 RETURN string("5 string")
+0012 RETURN string("default")
+string(7) "default"
+string(7) "default"
+string(5) "1 int"
+string(8) "1 string"
+string(5) "2 int"
+string(8) "2 string"
+string(5) "3 int"
+string(8) "3 string"
+string(5) "4 int"
+string(8) "4 string"
+string(5) "5 int"
+string(8) "5 string"
+string(7) "default"
+string(7) "default"
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index 15ade4ce3c..379f3fa9a1 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -547,6 +547,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
case ZEND_FE_FETCH_RW:
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
/* relative extended_value don't have to be changed */
break;
}
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index ae997b9a60..e6b5194bfe 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -549,6 +549,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
case ZEND_FE_FETCH_RW:
case ZEND_SWITCH_LONG:
case ZEND_SWITCH_STRING:
+ case ZEND_MATCH:
/* relative extended_value don't have to be changed */
break;
}
diff --git a/ext/standard/tests/file/fnmatch_variation.phpt b/ext/standard/tests/file/fnmatch_variation.phpt
index e7ad222444..4ca81ed94f 100644
--- a/ext/standard/tests/file/fnmatch_variation.phpt
+++ b/ext/standard/tests/file/fnmatch_variation.phpt
@@ -74,7 +74,7 @@ unlink($file_name);
echo "\n*** Testing fnmatch() with other types other than files ***";
/* defining a common function */
-function match( $pattern, $string ) {
+function match_( $pattern, $string ) {
for( $i = 0; $i<count($pattern); $i++ ) {
echo "-- Iteration $i --\n";
for( $j = 0; $j<count($string); $j++ ) {
@@ -96,7 +96,7 @@ $int_arr = array(
0xF,
0xF0000
);
-match($int_arr, $int_arr);
+match_($int_arr, $int_arr);
echo "\n--- With Strings ---\n";
$str_arr = array(
@@ -109,7 +109,7 @@ $str_arr = array(
/* binary input */
b"string"
);
-match($str_arr, $str_arr);
+match_($str_arr, $str_arr);
echo "\n--- With booleans ---\n";
$bool_arr = array(
@@ -123,7 +123,7 @@ $bool_arr = array(
"",
"string"
);
-match($bool_arr, $bool_arr);
+match_($bool_arr, $bool_arr);
echo "\n--- With NULL ---\n";
$null_arr = array(
@@ -134,7 +134,7 @@ $null_arr = array(
"string",
0
);
-match($null_arr, $null_arr);
+match_($null_arr, $null_arr);
echo "\n*** Done ***\n";
?>
diff --git a/ext/tokenizer/tokenizer_data.c b/ext/tokenizer/tokenizer_data.c
index 9c7df93207..14630cdd40 100644
--- a/ext/tokenizer/tokenizer_data.c
+++ b/ext/tokenizer/tokenizer_data.c
@@ -84,8 +84,6 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_STRING_VARNAME", T_STRING_VARNAME, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_NUM_STRING", T_NUM_STRING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_EVAL", T_EVAL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("T_INC", T_INC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("T_DEC", T_DEC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_NEW", T_NEW, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_EXIT", T_EXIT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_IF", T_IF, CONST_CS | CONST_PERSISTENT);
@@ -105,6 +103,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_ENDSWITCH", T_ENDSWITCH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_CASE", T_CASE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_DEFAULT", T_DEFAULT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_MATCH", T_MATCH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_BREAK", T_BREAK, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_CONTINUE", T_CONTINUE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_GOTO", T_GOTO, CONST_CS | CONST_PERSISTENT);
@@ -134,7 +133,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_INTERFACE", T_INTERFACE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_EXTENDS", T_EXTENDS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_IMPLEMENTS", T_IMPLEMENTS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("T_OBJECT_OPERATOR", T_OBJECT_OPERATOR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_NAMESPACE", T_NAMESPACE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_LIST", T_LIST, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_ARRAY", T_ARRAY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_CALLABLE", T_CALLABLE, CONST_CS | CONST_PERSISTENT);
@@ -145,6 +144,10 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_TRAIT_C", T_TRAIT_C, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_METHOD_C", T_METHOD_C, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_FUNC_C", T_FUNC_C, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_NS_C", T_NS_C, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_INC", T_INC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_DEC", T_DEC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_OBJECT_OPERATOR", T_OBJECT_OPERATOR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_COMMENT", T_COMMENT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_DOC_COMMENT", T_DOC_COMMENT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_OPEN_TAG", T_OPEN_TAG, CONST_CS | CONST_PERSISTENT);
@@ -156,8 +159,6 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_DOLLAR_OPEN_CURLY_BRACES", T_DOLLAR_OPEN_CURLY_BRACES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_CURLY_OPEN", T_CURLY_OPEN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_PAAMAYIM_NEKUDOTAYIM", T_PAAMAYIM_NEKUDOTAYIM, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("T_NAMESPACE", T_NAMESPACE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("T_NS_C", T_NS_C, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_NS_SEPARATOR", T_NS_SEPARATOR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_ELLIPSIS", T_ELLIPSIS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_BAD_CHARACTER", T_BAD_CHARACTER, CONST_CS | CONST_PERSISTENT);
@@ -227,8 +228,6 @@ char *get_token_type_name(int token_type)
case T_STRING_VARNAME: return "T_STRING_VARNAME";
case T_NUM_STRING: return "T_NUM_STRING";
case T_EVAL: return "T_EVAL";
- case T_INC: return "T_INC";
- case T_DEC: return "T_DEC";
case T_NEW: return "T_NEW";
case T_EXIT: return "T_EXIT";
case T_IF: return "T_IF";
@@ -248,6 +247,7 @@ char *get_token_type_name(int token_type)
case T_ENDSWITCH: return "T_ENDSWITCH";
case T_CASE: return "T_CASE";
case T_DEFAULT: return "T_DEFAULT";
+ case T_MATCH: return "T_MATCH";
case T_BREAK: return "T_BREAK";
case T_CONTINUE: return "T_CONTINUE";
case T_GOTO: return "T_GOTO";
@@ -277,7 +277,7 @@ char *get_token_type_name(int token_type)
case T_INTERFACE: return "T_INTERFACE";
case T_EXTENDS: return "T_EXTENDS";
case T_IMPLEMENTS: return "T_IMPLEMENTS";
- case T_OBJECT_OPERATOR: return "T_OBJECT_OPERATOR";
+ case T_NAMESPACE: return "T_NAMESPACE";
case T_LIST: return "T_LIST";
case T_ARRAY: return "T_ARRAY";
case T_CALLABLE: return "T_CALLABLE";
@@ -288,6 +288,10 @@ char *get_token_type_name(int token_type)
case T_TRAIT_C: return "T_TRAIT_C";
case T_METHOD_C: return "T_METHOD_C";
case T_FUNC_C: return "T_FUNC_C";
+ case T_NS_C: return "T_NS_C";
+ case T_INC: return "T_INC";
+ case T_DEC: return "T_DEC";
+ case T_OBJECT_OPERATOR: return "T_OBJECT_OPERATOR";
case T_COMMENT: return "T_COMMENT";
case T_DOC_COMMENT: return "T_DOC_COMMENT";
case T_OPEN_TAG: return "T_OPEN_TAG";
@@ -299,8 +303,6 @@ char *get_token_type_name(int token_type)
case T_DOLLAR_OPEN_CURLY_BRACES: return "T_DOLLAR_OPEN_CURLY_BRACES";
case T_CURLY_OPEN: return "T_CURLY_OPEN";
case T_PAAMAYIM_NEKUDOTAYIM: return "T_DOUBLE_COLON";
- case T_NAMESPACE: return "T_NAMESPACE";
- case T_NS_C: return "T_NS_C";
case T_NS_SEPARATOR: return "T_NS_SEPARATOR";
case T_ELLIPSIS: return "T_ELLIPSIS";
case T_BAD_CHARACTER: return "T_BAD_CHARACTER";