Skip to content

Commit 2d069f6

Browse files
Merge branch 'coalesce_operator'
* coalesce_operator: Extended coalesce operator test case for ordering/short-circuiting Ensure not evaluated twice Added test Initial coalesce operator implementation
2 parents f13da5b + ec39802 commit 2d069f6

File tree

12 files changed

+3352
-3026
lines changed

12 files changed

+3352
-3026
lines changed

Zend/zend_ast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ enum _zend_ast_kind {
115115
ZEND_AST_NEW,
116116
ZEND_AST_INSTANCEOF,
117117
ZEND_AST_YIELD,
118+
ZEND_AST_COALESCE,
118119

119120
ZEND_AST_STATIC,
120121
ZEND_AST_WHILE,

Zend/zend_compile.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5324,6 +5324,30 @@ void zend_compile_conditional(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
53245324
}
53255325
/* }}} */
53265326

5327+
void zend_compile_coalesce(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
5328+
{
5329+
zend_ast *expr_ast = ast->child[0];
5330+
zend_ast *default_ast = ast->child[1];
5331+
5332+
znode expr_node, default_node;
5333+
zend_op *opline;
5334+
uint32_t opnum;
5335+
5336+
zend_compile_var(&expr_node, expr_ast, BP_VAR_IS TSRMLS_CC);
5337+
5338+
opnum = get_next_op_number(CG(active_op_array));
5339+
zend_emit_op(result, ZEND_COALESCE, &expr_node, NULL TSRMLS_CC);
5340+
5341+
zend_compile_expr(&default_node, default_ast TSRMLS_CC);
5342+
5343+
opline = zend_emit_op(NULL, ZEND_QM_ASSIGN, &default_node, NULL TSRMLS_CC);
5344+
SET_NODE(opline->result, result);
5345+
5346+
opline = &CG(active_op_array)->opcodes[opnum];
5347+
opline->op2.opline_num = get_next_op_number(CG(active_op_array));
5348+
}
5349+
/* }}} */
5350+
53275351
void zend_compile_print(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
53285352
{
53295353
zend_ast *expr_ast = ast->child[0];
@@ -6158,6 +6182,9 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
61586182
case ZEND_AST_CONDITIONAL:
61596183
zend_compile_conditional(result, ast TSRMLS_CC);
61606184
return;
6185+
case ZEND_AST_COALESCE:
6186+
zend_compile_coalesce(result, ast TSRMLS_CC);
6187+
return;
61616188
case ZEND_AST_PRINT:
61626189
zend_compile_print(result, ast TSRMLS_CC);
61636190
return;

Zend/zend_language_parser.y

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
6767
%right T_YIELD
6868
%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL
6969
%left '?' ':'
70+
%right T_COALESCE
7071
%left T_BOOLEAN_OR
7172
%left T_BOOLEAN_AND
7273
%left '|'
@@ -221,6 +222,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
221222
%token T_NS_C "__NAMESPACE__ (T_NS_C)"
222223
%token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)"
223224
%token T_ELLIPSIS "... (T_ELLIPSIS)"
225+
%token T_COALESCE "?? (T_COALESCE)"
224226
%token T_POW "** (T_POW)"
225227
%token T_POW_EQUAL "**= (T_POW_EQUAL)"
226228

@@ -827,6 +829,8 @@ expr_without_variable:
827829
{ $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); }
828830
| expr '?' ':' expr
829831
{ $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }
832+
| expr T_COALESCE expr
833+
{ $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); }
830834
| internal_functions_in_yacc { $$ = $1; }
831835
| T_INT_CAST expr { $$ = zend_ast_create_cast(IS_LONG, $2); }
832836
| T_DOUBLE_CAST expr { $$ = zend_ast_create_cast(IS_DOUBLE, $2); }

0 commit comments

Comments
 (0)