diff --git a/Zend/tests/pipe_operator/ast.phpt b/Zend/tests/pipe_operator/ast.phpt new file mode 100644 index 000000000000..e8c088dabfdb --- /dev/null +++ b/Zend/tests/pipe_operator/ast.phpt @@ -0,0 +1,109 @@ +--TEST-- +A pipe operator displays as a pipe operator when outputting syntax, with correct parens. +--FILE-- + baz() . quux()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && (foo() . bar()) |> baz() . quux()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && foo() . (bar() |> baz()) . quux()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && foo() . bar() |> (baz() . quux())); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && (foo() . bar() |> baz()) . quux()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && foo() . (bar() |> baz() . quux())); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +print "<, which binds lower\n"; + +try { + assert(false && foo() < bar() |> baz()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && (foo() < bar()) |> baz()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && foo() < (bar() |> baz())); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && foo() |> bar() < baz()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && (foo() |> bar()) < baz()); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && foo() |> (bar() < baz())); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + + + +print "misc examples\n"; + +try { + assert(false && foo() |> (bar() |> baz(...))); +} catch (AssertionError $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Concat, which binds higher +assert(false && foo() . bar() |> baz() . quux()) +assert(false && foo() . bar() |> baz() . quux()) +assert(false && foo() . (bar() |> baz()) . quux()) +assert(false && foo() . bar() |> baz() . quux()) +assert(false && (foo() . bar() |> baz()) . quux()) +assert(false && foo() . (bar() |> baz() . quux())) +<, which binds lower +assert(false && foo() < bar() |> baz()) +assert(false && (foo() < bar()) |> baz()) +assert(false && foo() < bar() |> baz()) +assert(false && foo() |> bar() < baz()) +assert(false && foo() |> bar() < baz()) +assert(false && foo() |> (bar() < baz())) +misc examples +assert(false && foo() |> (bar() |> baz(...))) diff --git a/Zend/tests/pipe_operator/call_by_ref.phpt b/Zend/tests/pipe_operator/call_by_ref.phpt new file mode 100644 index 000000000000..026089b0a654 --- /dev/null +++ b/Zend/tests/pipe_operator/call_by_ref.phpt @@ -0,0 +1,37 @@ +--TEST-- +Pipe operator rejects by-reference functions. +--FILE-- + _modify(...); + var_dump($res1); +} catch (\Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +// Complex variables. +try { + $a = ['foo' => 'beep']; + $res2 = $a |> _append(...); + var_dump($res2); +} catch (\Error $e) { + echo $e->getMessage(), PHP_EOL; +} + + +?> +--EXPECTF-- +_modify(): Argument #1 ($a) could not be passed by reference +_append(): Argument #1 ($a) could not be passed by reference diff --git a/Zend/tests/pipe_operator/call_prefer_by_ref.phpt b/Zend/tests/pipe_operator/call_prefer_by_ref.phpt new file mode 100644 index 000000000000..31750ac280d7 --- /dev/null +++ b/Zend/tests/pipe_operator/call_prefer_by_ref.phpt @@ -0,0 +1,17 @@ +--TEST-- +Pipe operator accepts prefer-by-reference functions. +--FILE-- + array_multisort(...); + var_dump($r); +} catch (\Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +bool(true) diff --git a/Zend/tests/pipe_operator/complex_ordering.phpt b/Zend/tests/pipe_operator/complex_ordering.phpt new file mode 100644 index 000000000000..49f3d47ade4b --- /dev/null +++ b/Zend/tests/pipe_operator/complex_ordering.phpt @@ -0,0 +1,20 @@ +--TEST-- +Functions are executed in the expected order +--FILE-- + (bar() ? baz(...) : quux(...)) + |> var_dump(...); + +?> +--EXPECT-- +foo +bar +quux +int(1) diff --git a/Zend/tests/pipe_operator/compound_userland_calls.phpt b/Zend/tests/pipe_operator/compound_userland_calls.phpt new file mode 100644 index 000000000000..922c3c5ac23d --- /dev/null +++ b/Zend/tests/pipe_operator/compound_userland_calls.phpt @@ -0,0 +1,19 @@ +--TEST-- +Pipe operator chains +--FILE-- + '_test1' |> '_test2'; + +var_dump($res1); +?> +--EXPECT-- +int(12) diff --git a/Zend/tests/pipe_operator/exception_interruption.phpt b/Zend/tests/pipe_operator/exception_interruption.phpt new file mode 100644 index 000000000000..6711b652e7c6 --- /dev/null +++ b/Zend/tests/pipe_operator/exception_interruption.phpt @@ -0,0 +1,37 @@ +--TEST-- +A pipe interrupted by an exception, to demonstrate correct order of execution. +--FILE-- + (bar() ? baz(...) : quux(...)) + |> var_dump(...); +} +catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + $result = foo() + |> (throw new Exception('Break')) + |> (bar() ? baz(...) : quux(...)) + |> var_dump(...); +} +catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +foo +bar +quux +Exception: Oops +foo +Exception: Break diff --git a/Zend/tests/pipe_operator/function_not_found.phpt b/Zend/tests/pipe_operator/function_not_found.phpt new file mode 100644 index 000000000000..747f53ce3e3d --- /dev/null +++ b/Zend/tests/pipe_operator/function_not_found.phpt @@ -0,0 +1,15 @@ +--TEST-- +Pipe operator throws normally on missing function +--FILE-- + '_test'; +} +catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Error: Call to undefined function _test() diff --git a/Zend/tests/pipe_operator/generators.phpt b/Zend/tests/pipe_operator/generators.phpt new file mode 100644 index 000000000000..9607af581fcd --- /dev/null +++ b/Zend/tests/pipe_operator/generators.phpt @@ -0,0 +1,30 @@ +--TEST-- +Generators +--FILE-- + map_incr(...) |> iterator_to_array(...); + +var_dump($result); +?> +--EXPECT-- +array(3) { + [0]=> + int(2) + [1]=> + int(3) + [2]=> + int(4) +} diff --git a/Zend/tests/pipe_operator/mixed_callable_call.phpt b/Zend/tests/pipe_operator/mixed_callable_call.phpt new file mode 100644 index 000000000000..13bef986defb --- /dev/null +++ b/Zend/tests/pipe_operator/mixed_callable_call.phpt @@ -0,0 +1,74 @@ +--TEST-- +Pipe operator handles all callable styles +--FILE-- + _add($x, 3); + +$res1 = 1 + |> times3(...) + |> 'times5' + |> $test->times7(...) + |> [$test, 'times11'] + |> StaticTest::times13(...) + |> [StaticTest::class, 'times17'] + |> fn($x) => times23($x) + |> new Times27() +; + +var_dump($res1); +?> +--EXPECT-- +int(158513355) diff --git a/Zend/tests/pipe_operator/namespaced_functions.phpt b/Zend/tests/pipe_operator/namespaced_functions.phpt new file mode 100644 index 000000000000..0c2b1ab52db7 --- /dev/null +++ b/Zend/tests/pipe_operator/namespaced_functions.phpt @@ -0,0 +1,22 @@ +--TEST-- +Pipe operator handles all callable styles +--FILE-- + test(...); + + 5 |> \Beep\test(...); +} +?> +--EXPECT-- +5 +5 diff --git a/Zend/tests/pipe_operator/optimizations.phpt b/Zend/tests/pipe_operator/optimizations.phpt new file mode 100644 index 000000000000..afdc528337c1 --- /dev/null +++ b/Zend/tests/pipe_operator/optimizations.phpt @@ -0,0 +1,89 @@ +--TEST-- +Pipe operator optimizes away most callables +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.opt_debug_level=0x20000 +--EXTENSIONS-- +opcache +--FILE-- + _test1(...) + |> $o->foo(...) + |> Other::bar(...) +; + +var_dump($res1); +?> +--EXPECTF-- +$_main: + ; (lines=18, args=0, vars=2, tmps=2) + ; (after optimizer) + ; %s:1-27 +0000 V2 = NEW 0 string("Other") +0001 DO_FCALL +0002 ASSIGN CV0($o) V2 +0003 INIT_FCALL 1 %d string("_test1") +0004 SEND_VAL int(5) 1 +0005 T2 = DO_UCALL +0006 INIT_METHOD_CALL 1 CV0($o) string("foo") +0007 SEND_VAL_EX T2 1 +0008 V3 = DO_FCALL +0009 T2 = QM_ASSIGN V3 +0010 INIT_STATIC_METHOD_CALL 1 string("Other") string("bar") +0011 SEND_VAL T2 1 +0012 V2 = DO_UCALL +0013 ASSIGN CV1($res1) V2 +0014 INIT_FCALL 1 %d string("var_dump") +0015 SEND_VAR CV1($res1) 1 +0016 DO_ICALL +0017 RETURN int(1) +LIVE RANGES: + 2: 0001 - 0002 (new) + 2: 0010 - 0011 (tmp/var) + +_test1: + ; (lines=4, args=1, vars=1, tmps=1) + ; (after optimizer) + ; %s:3-5 +0000 CV0($a) = RECV 1 +0001 T1 = ADD CV0($a) int(1) +0002 VERIFY_RETURN_TYPE T1 +0003 RETURN T1 + +Other::foo: + ; (lines=4, args=1, vars=1, tmps=1) + ; (after optimizer) + ; %s:8-10 +0000 CV0($a) = RECV 1 +0001 T1 = ADD CV0($a) CV0($a) +0002 VERIFY_RETURN_TYPE T1 +0003 RETURN T1 + +Other::bar: + ; (lines=4, args=1, vars=1, tmps=1) + ; (after optimizer) + ; %s:12-14 +0000 CV0($a) = RECV 1 +0001 T1 = SUB CV0($a) int(1) +0002 VERIFY_RETURN_TYPE T1 +0003 RETURN T1 +int(11) diff --git a/Zend/tests/pipe_operator/optional_parameters.phpt b/Zend/tests/pipe_operator/optional_parameters.phpt new file mode 100644 index 000000000000..53cce2e9972e --- /dev/null +++ b/Zend/tests/pipe_operator/optional_parameters.phpt @@ -0,0 +1,15 @@ +--TEST-- +Pipe operator accepts optional-parameter functions +--FILE-- + '_test'; + +var_dump($res1); +?> +--EXPECT-- +int(8) diff --git a/Zend/tests/pipe_operator/precedence_addition.phpt b/Zend/tests/pipe_operator/precedence_addition.phpt new file mode 100644 index 000000000000..4fd64639b451 --- /dev/null +++ b/Zend/tests/pipe_operator/precedence_addition.phpt @@ -0,0 +1,16 @@ +--TEST-- +Pipe binds lower than addition +--FILE-- + '_test1'; + +var_dump($res1); +?> +--EXPECT-- +int(14) diff --git a/Zend/tests/pipe_operator/precedence_coalesce.phpt b/Zend/tests/pipe_operator/precedence_coalesce.phpt new file mode 100644 index 000000000000..daf699d9fe85 --- /dev/null +++ b/Zend/tests/pipe_operator/precedence_coalesce.phpt @@ -0,0 +1,17 @@ +--TEST-- +Pipe binds higher than coalesce +--FILE-- + get_username(...) + ?? 'default'; + +var_dump($user); +?> +--EXPECT-- +string(1) "5" diff --git a/Zend/tests/pipe_operator/precedence_comparison.phpt b/Zend/tests/pipe_operator/precedence_comparison.phpt new file mode 100644 index 000000000000..84f71b74058a --- /dev/null +++ b/Zend/tests/pipe_operator/precedence_comparison.phpt @@ -0,0 +1,16 @@ +--TEST-- +Pipe binds higher than comparison +--FILE-- + _test1(...) == 10 ; +var_dump($res1); + +?> +--EXPECTF-- +bool(true) diff --git a/Zend/tests/pipe_operator/precedence_ternary.phpt b/Zend/tests/pipe_operator/precedence_ternary.phpt new file mode 100644 index 000000000000..207d15dab9d6 --- /dev/null +++ b/Zend/tests/pipe_operator/precedence_ternary.phpt @@ -0,0 +1,36 @@ +--TEST-- +Pipe binds higher than ternary +--FILE-- + is_odd(...) ? 'odd' : 'even'; +var_dump($res1); + +// The pipe binds first, resulting in bool ? int : string, which is well-understood. +$x = true; +$y = 'beep'; +$z = 'default'; +$ret3 = $x ? $y |> strlen(...) : $z; +var_dump($ret3); + + +?> +--EXPECT-- +string(3) "odd" +int(4) diff --git a/Zend/tests/pipe_operator/simple_builtin_call.phpt b/Zend/tests/pipe_operator/simple_builtin_call.phpt new file mode 100644 index 000000000000..72f5968dd0b6 --- /dev/null +++ b/Zend/tests/pipe_operator/simple_builtin_call.phpt @@ -0,0 +1,11 @@ +--TEST-- +Pipe operator supports built-in functions +--FILE-- + 'strlen'; + +var_dump($res1); +?> +--EXPECT-- +int(5) diff --git a/Zend/tests/pipe_operator/simple_userland_call.phpt b/Zend/tests/pipe_operator/simple_userland_call.phpt new file mode 100644 index 000000000000..7f311f9a1047 --- /dev/null +++ b/Zend/tests/pipe_operator/simple_userland_call.phpt @@ -0,0 +1,15 @@ +--TEST-- +Pipe operator supports user-defined functions +--FILE-- + '_test'; + +var_dump($res1); +?> +--EXPECT-- +int(6) diff --git a/Zend/tests/pipe_operator/too_many_parameters.phpt b/Zend/tests/pipe_operator/too_many_parameters.phpt new file mode 100644 index 000000000000..b36046bde05c --- /dev/null +++ b/Zend/tests/pipe_operator/too_many_parameters.phpt @@ -0,0 +1,21 @@ +--TEST-- +Pipe operator fails on multi-parameter functions +--FILE-- + '_test'; +} +catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + + +?> +--EXPECTF-- +ArgumentCountError: Too few arguments to function %s, 1 passed in %s on line %s and exactly 2 expected diff --git a/Zend/tests/pipe_operator/type_mismatch.phpt b/Zend/tests/pipe_operator/type_mismatch.phpt new file mode 100644 index 000000000000..2cee15bb47a0 --- /dev/null +++ b/Zend/tests/pipe_operator/type_mismatch.phpt @@ -0,0 +1,20 @@ +--TEST-- +Pipe operator respects types +--FILE-- + '_test'; + var_dump($res1); +} +catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +TypeError: _test(): Argument #1 ($a) must be of type int, string given, called in %s on line %d diff --git a/Zend/tests/pipe_operator/void_return.phpt b/Zend/tests/pipe_operator/void_return.phpt new file mode 100644 index 000000000000..0dbba519297c --- /dev/null +++ b/Zend/tests/pipe_operator/void_return.phpt @@ -0,0 +1,21 @@ +--TEST-- +Pipe operator fails void return chaining in strict mode +--FILE-- + 'nonReturnFunction' + |> 'strlen'; + var_dump($result); +} +catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: strlen(): Argument #1 ($string) must be of type string, null given diff --git a/Zend/tests/pipe_operator/wrapped_chains.phpt b/Zend/tests/pipe_operator/wrapped_chains.phpt new file mode 100644 index 000000000000..e2b6f39f7f34 --- /dev/null +++ b/Zend/tests/pipe_operator/wrapped_chains.phpt @@ -0,0 +1,21 @@ +--TEST-- +Pipe operator chains saved as a closure +--FILE-- + $x |> '_test1' |> '_test2'; + +$res1 = $func(5); + +var_dump($res1); +?> +--EXPECT-- +int(12) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 8bdd29c5512c..ec861b3ff6bf 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -2510,6 +2510,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case ZEND_AST_GREATER_EQUAL: BINARY_OP(" >= ", 180, 181, 181); case ZEND_AST_AND: BINARY_OP(" && ", 130, 130, 131); case ZEND_AST_OR: BINARY_OP(" || ", 120, 120, 121); + case ZEND_AST_PIPE: BINARY_OP(" |> ", 183, 183, 184); case ZEND_AST_ARRAY_ELEM: if (ast->child[1]) { zend_ast_export_ex(str, ast->child[1], 80, indent); diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 9348c35f6cc0..c82ca66c9f57 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -154,6 +154,7 @@ enum _zend_ast_kind { ZEND_AST_MATCH_ARM, ZEND_AST_NAMED_ARG, ZEND_AST_PARENT_PROPERTY_HOOK_CALL, + ZEND_AST_PIPE, /* 3 child nodes */ ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT, diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0669d106f15e..1deb81ca2a4c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6427,6 +6427,52 @@ static bool can_match_use_jumptable(zend_ast_list *arms) { return 1; } +static void zend_compile_pipe(znode *result, zend_ast *ast) +{ + zend_ast *operand_ast = ast->child[0]; + zend_ast *callable_ast = ast->child[1]; + + /* Compile the left hand side down to a value first. */ + znode operand_result; + zend_compile_expr(&operand_result, operand_ast); + + /* Wrap the value in a ZEND_QM_ASSIGN opcode to ensure references + * always fail. Otherwise, they'd only fail in complex cases like arrays. */ + znode wrapped_operand_result; + zend_emit_op_tmp(&wrapped_operand_result, ZEND_QM_ASSIGN, &operand_result, NULL); + + /* Turn the operand into a function parameter list. */ + zend_ast *arg_list_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, zend_ast_create_znode(&wrapped_operand_result)); + + zend_ast *fcall_ast; + znode callable_result; + + /* Turn $foo |> bar(...) into bar($foo). */ + if (callable_ast->kind == ZEND_AST_CALL + && callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) { + fcall_ast = zend_ast_create(ZEND_AST_CALL, + callable_ast->child[0], arg_list_ast); + /* Turn $foo |> bar::baz(...) into bar::baz($foo). */ + } else if (callable_ast->kind == ZEND_AST_STATIC_CALL + && callable_ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT) { + fcall_ast = zend_ast_create(ZEND_AST_STATIC_CALL, + callable_ast->child[0], callable_ast->child[1], arg_list_ast); + /* Turn $foo |> $bar->baz(...) into $bar->baz($foo). */ + } else if (callable_ast->kind == ZEND_AST_METHOD_CALL + && callable_ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT) { + fcall_ast = zend_ast_create(ZEND_AST_METHOD_CALL, + callable_ast->child[0], callable_ast->child[1], arg_list_ast); + /* Turn $foo |> $expr into ($expr)($foo) */ + } else { + zend_compile_expr(&callable_result, callable_ast); + callable_ast = zend_ast_create_znode(&callable_result); + fcall_ast = zend_ast_create(ZEND_AST_CALL, + callable_ast, arg_list_ast); + } + + zend_compile_expr(result, fcall_ast); +} + static void zend_compile_match(znode *result, zend_ast *ast) { zend_ast *expr_ast = ast->child[0]; @@ -11769,6 +11815,9 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */ case ZEND_AST_MATCH: zend_compile_match(result, ast); return; + case ZEND_AST_PIPE: + zend_compile_pipe(result, ast); + return; default: ZEND_ASSERT(0 /* not supported */); } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 08b2ac6b3f39..816b8126cbf2 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -71,6 +71,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL +%left T_PIPE %left '.' %left T_SL T_SR %left '+' '-' @@ -237,6 +238,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_COALESCE "'??'" %token T_POW "'**'" %token T_POW_EQUAL "'**='" +%token T_PIPE "'|>'" /* We need to split the & token in two to avoid a shift/reduce conflict. For T1&$v and T1&T2, * with only one token lookahead, bison does not know whether to reduce T1 as a complete type, * or shift to continue parsing an intersection type. */ @@ -1292,6 +1294,8 @@ expr: { $$ = zend_ast_create_binary_op(ZEND_IS_EQUAL, $1, $3); } | expr T_IS_NOT_EQUAL expr { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_EQUAL, $1, $3); } + | expr T_PIPE expr + { $$ = zend_ast_create(ZEND_AST_PIPE, $1, $3); } | expr '<' expr { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER, $1, $3); } | expr T_IS_SMALLER_OR_EQUAL expr diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 4c883b81c5f7..5e377249422a 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -1861,6 +1861,10 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN(T_COALESCE_EQUAL); } +"|>" { + RETURN_TOKEN(T_PIPE); +} + "||" { RETURN_TOKEN(T_BOOLEAN_OR); } diff --git a/ext/tokenizer/tokenizer_data.c b/ext/tokenizer/tokenizer_data.c index a1e131032bcf..0900c51d3d95 100644 --- a/ext/tokenizer/tokenizer_data.c +++ b/ext/tokenizer/tokenizer_data.c @@ -173,6 +173,7 @@ char *get_token_type_name(int token_type) case T_COALESCE: return "T_COALESCE"; case T_POW: return "T_POW"; case T_POW_EQUAL: return "T_POW_EQUAL"; + case T_PIPE: return "T_PIPE"; case T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG: return "T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG"; case T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG: return "T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG"; case T_BAD_CHARACTER: return "T_BAD_CHARACTER"; diff --git a/ext/tokenizer/tokenizer_data.stub.php b/ext/tokenizer/tokenizer_data.stub.php index c1e1fd254dfa..57c8edad8acb 100644 --- a/ext/tokenizer/tokenizer_data.stub.php +++ b/ext/tokenizer/tokenizer_data.stub.php @@ -742,6 +742,11 @@ * @cvalue T_POW_EQUAL */ const T_POW_EQUAL = UNKNOWN; +/** + * @var int + * @cvalue T_PIPE + */ +const T_PIPE = UNKNOWN; /** * @var int * @cvalue T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG diff --git a/ext/tokenizer/tokenizer_data_arginfo.h b/ext/tokenizer/tokenizer_data_arginfo.h index 9c488d19f189..3a3cdaa46813 100644 --- a/ext/tokenizer/tokenizer_data_arginfo.h +++ b/ext/tokenizer/tokenizer_data_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 19d25d22098f46283b517352cbb302db962b50fd */ + * Stub hash: c5235344b7c651d27c2c33c90696a418a9c96837 */ static void register_tokenizer_data_symbols(int module_number) { @@ -151,6 +151,7 @@ static void register_tokenizer_data_symbols(int module_number) REGISTER_LONG_CONSTANT("T_COALESCE", T_COALESCE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_POW", T_POW, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_POW_EQUAL", T_POW_EQUAL, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("T_PIPE", T_PIPE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG", T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG", T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("T_BAD_CHARACTER", T_BAD_CHARACTER, CONST_PERSISTENT);