return opline;
}
+static zend_op *emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, znode *op2 TSRMLS_DC) {
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = opcode;
+
+ SET_NODE(opline->op1, op1);
+
+ if (op2 == NULL) {
+ SET_UNUSED(opline->op2);
+ } else {
+ SET_NODE(opline->op2, op2);
+ }
+
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
+
+ return opline;
+}
+
static zend_bool zend_is_variable(zend_ast *ast) {
return ast->kind == ZEND_AST_VAR || ast->kind == ZEND_AST_DIM || ast->kind == ZEND_AST_PROP
|| ast->kind == ZEND_AST_CALL || ast->kind == ZEND_AST_METHOD_CALL
|| ast->kind == ZEND_AST_STATIC_CALL;
}
+static zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) {
+ zval *name;
+ int fetch_type;
+ if (name_ast->kind != ZEND_CONST) {
+ return 0;
+ }
+
+ name = zend_ast_get_zval(name_ast);
+ fetch_type = zend_get_class_fetch_type(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ return fetch_type == ZEND_FETCH_CLASS_DEFAULT;
+}
+
+static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast TSRMLS_DC) {
+ znode name_node;
+ zend_op *opline;
+
+ zend_compile_expr(&name_node, name_ast TSRMLS_CC);
+
+ if (name_node.op_type == IS_CONST) {
+ zval *name = &name_node.u.constant;
+ int fetch_type = zend_get_class_fetch_type(Z_STRVAL_P(name), Z_STRLEN_P(name));
+
+ opline = emit_op(result, ZEND_FETCH_CLASS, NULL, NULL TSRMLS_CC);
+ opline->extended_value = fetch_type;
+
+ switch (fetch_type) {
+ case ZEND_FETCH_CLASS_SELF:
+ case ZEND_FETCH_CLASS_PARENT:
+ case ZEND_FETCH_CLASS_STATIC:
+ zval_ptr_dtor(name);
+ break;
+ default:
+ zend_resolve_class_name(&name_node TSRMLS_CC);
+ opline->op2_type = IS_CONST;
+ opline->op2.constant =
+ zend_add_class_name_literal(CG(active_op_array), name TSRMLS_CC);
+ break;
+ }
+ } else {
+ opline = emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node TSRMLS_CC);
+ opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
+ }
+
+ return opline;
+}
+
static int zend_try_compile_cv(znode *result, zend_ast *ast TSRMLS_DC) {
zend_ast *name_ast = ast->child[0];
if (name_ast->kind == ZEND_CONST) {
zend_ast *class_ast = ast->child[0];
zend_ast *prop_ast = ast->child[1];
- znode class_name_node, class_node, prop_node;
+ znode class_node, prop_node;
zend_op *opline;
- zend_compile_expr(&class_name_node, class_ast TSRMLS_CC);
- if (class_name_node.op_type == IS_CONST &&
- ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(
- Z_STRVAL(class_name_node.u.constant), Z_STRLEN(class_name_node.u.constant))
- ) {
- zend_resolve_class_name(&class_name_node TSRMLS_CC);
- class_node = class_name_node;
+ if (zend_is_const_default_class_ref(class_ast)) {
+ zend_compile_expr(&class_node, class_ast TSRMLS_CC);
+ zend_resolve_class_name(&class_node TSRMLS_CC);
} else {
- zend_do_fetch_class(&class_node, &class_name_node TSRMLS_CC);
+ zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
}
zend_compile_expr(&prop_node, prop_ast TSRMLS_CC);
}
}
-/* Detected $a[b]... = $a pattern */
-zend_bool zend_is_dim_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast TSRMLS_DC) {
+/* Detects $a... = $a pattern */
+zend_bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast TSRMLS_DC) {
if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_CONST) {
return 0;
}
- while (zend_is_variable(var_ast) && !var_ast->kind == ZEND_AST_VAR) {
+ while (zend_is_variable(var_ast) && var_ast->kind != ZEND_AST_VAR) {
var_ast = var_ast->child[0];
}
zend_ensure_writable_variable(var_ast);
- // TODO.AST handle $a[b] = $a
- //if (zend_is_dim_assign_to_self(var_ast, expr_ast TSRMLS_CC)) {
- //zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R TSRMLS_CC);
- //} else {
+ if (zend_is_assign_to_self(var_ast, expr_ast TSRMLS_CC)) {
+ zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R TSRMLS_CC);
+ } else {
zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
- //}
+ }
switch (var_ast->kind) {
case ZEND_AST_VAR:
if (zend_is_call(source_ast)) {
opline->extended_value = ZEND_RETURNS_FUNCTION;
- }
- // TODO.AST
- /*if (rvar->EA & ZEND_PARSED_NEW) {
+ } else if (source_ast->kind == ZEND_NEW) {
opline->extended_value = ZEND_RETURNS_NEW;
- }*/
+ }
}
void zend_compile_compound_assign(znode *result, zend_ast *ast TSRMLS_DC) {
zend_ast *method_ast = ast->child[1];
zend_ast *params_ast = ast->child[2];
- znode class_name_node, class_node, method_node;
+ znode class_node, method_node;
zend_op *opline;
zend_ulong extended_value = 0;
- zend_compile_expr(&class_name_node, class_ast TSRMLS_CC);
- if (class_name_node.op_type == IS_CONST &&
- ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(
- Z_STRVAL(class_name_node.u.constant), Z_STRLEN(class_name_node.u.constant))
- ) {
- zend_resolve_class_name(&class_name_node TSRMLS_CC);
- class_node = class_name_node;
+ if (zend_is_const_default_class_ref(class_ast)) {
+ zend_compile_expr(&class_node, class_ast TSRMLS_CC);
+ zend_resolve_class_name(&class_node TSRMLS_CC);
} else {
- zend_do_fetch_class(&class_node, &class_name_node TSRMLS_CC);
- extended_value = class_node.EA;
+ opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+ extended_value = opline->extended_value;
}
zend_compile_expr(&method_node, method_ast TSRMLS_CC);
zend_compile_call_common(result, params_ast, NULL TSRMLS_CC);
}
+void zend_compile_new(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *params_ast = ast->child[1];
+
+ znode class_node, ctor_result;
+ zend_op *opline;
+ zend_uint opnum;
+
+ zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+
+ opnum = get_next_op_number(CG(active_op_array));
+ opline = emit_op(result, ZEND_NEW, &class_node, NULL TSRMLS_CC);
+ opline->extended_value = CG(context).nested_calls;
+
+ zend_compile_call_common(&ctor_result, params_ast, NULL TSRMLS_CC);
+ zend_do_free(&ctor_result TSRMLS_CC);
+
+ /* New jumps over ctor call if ctor does not exist */
+ opline = &CG(active_op_array)->opcodes[opnum];
+ opline->op2.opline_num = get_next_op_number(CG(active_op_array));
+}
+
+void zend_compile_clone(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *obj_ast = ast->child[0];
+
+ znode obj_node;
+ zend_compile_expr(&obj_node, obj_ast TSRMLS_CC);
+
+ emit_op(result, ZEND_CLONE, &obj_node, NULL TSRMLS_CC);
+}
+
void zend_compile_global_var(zend_ast *ast TSRMLS_DC) {
zend_ast *var_ast = ast->child[0];
}
}
+void zend_compile_binary_op(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *left_ast = ast->child[0];
+ zend_ast *right_ast = ast->child[1];
+
+ znode left_node, right_node;
+ zend_compile_expr(&left_node, left_ast TSRMLS_CC);
+ zend_compile_expr(&right_node, right_ast TSRMLS_CC);
+
+ emit_op_tmp(result, ast->kind, &left_node, &right_node TSRMLS_CC);
+}
+
+/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
+ * evaluation order. */
+void zend_compile_greater(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *left_ast = ast->child[0];
+ zend_ast *right_ast = ast->child[1];
+ znode left_node, right_node;
+
+ ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
+
+ zend_compile_expr(&left_node, left_ast TSRMLS_CC);
+ zend_compile_expr(&right_node, right_ast TSRMLS_CC);
+
+ emit_op_tmp(result, ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
+ &right_node, &left_node TSRMLS_CC);
+}
+
+void zend_compile_unary_op(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *expr_ast = ast->child[0];
+
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ emit_op_tmp(result, ast->kind, &expr_node, NULL TSRMLS_CC);
+}
+
+void zend_compile_unary_pm(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *expr_ast = ast->child[0];
+ znode zero_node, expr_node;
+
+ ZEND_ASSERT(ast->kind == ZEND_UNARY_PLUS || ast->kind == ZEND_UNARY_MINUS);
+
+ zero_node.op_type = IS_CONST;
+ ZVAL_LONG(&zero_node.u.constant, 0);
+
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ emit_op_tmp(result, ast->kind == ZEND_UNARY_PLUS ? ZEND_ADD : ZEND_SUB,
+ &zero_node, &expr_node TSRMLS_CC);
+}
+
+void zend_compile_short_circuiting(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *left_ast = ast->child[0];
+ zend_ast *right_ast = ast->child[1];
+
+ znode left_node, right_node;
+ zend_op *opline_jmpz, *opline_bool;
+ zend_uint opnum_jmpz;
+
+ ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
+
+ zend_compile_expr(&left_node, left_ast TSRMLS_CC);
+
+ opnum_jmpz = get_next_op_number(CG(active_op_array));
+ opline_jmpz = emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
+ &left_node, NULL TSRMLS_CC);
+
+ if (left_node.op_type == IS_TMP_VAR) {
+ SET_NODE(opline_jmpz->result, &left_node);
+ } else {
+ opline_jmpz->result.var = get_temporary_variable(CG(active_op_array));
+ opline_jmpz->result_type = IS_TMP_VAR;
+ }
+ GET_NODE(result, opline_jmpz->result);
+
+ zend_compile_expr(&right_node, right_ast TSRMLS_CC);
+
+ opline_bool = emit_op(NULL, ZEND_BOOL, &right_node, NULL TSRMLS_CC);
+ SET_NODE(opline_bool->result, result);
+
+ opline_jmpz = &CG(active_op_array)->opcodes[opnum_jmpz];
+ opline_jmpz->op2.opline_num = get_next_op_number(CG(active_op_array));
+}
+
+void zend_compile_post_incdec(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *var_ast = ast->child[0];
+
+ znode var_node;
+ zend_op *opline;
+
+ ZEND_ASSERT(ast->kind == ZEND_POST_INC || ast->kind == ZEND_POST_DEC);
+
+ if (var_ast->kind == ZEND_AST_PROP) {
+ opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_RW TSRMLS_CC);
+ opline->opcode = ast->kind == ZEND_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
+ } else {
+ zend_compile_var(&var_node, var_ast, BP_VAR_RW TSRMLS_CC);
+ emit_op_tmp(result, ast->kind, &var_node, NULL TSRMLS_CC);
+ }
+}
+
+void zend_compile_pre_incdec(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *var_ast = ast->child[0];
+
+ znode var_node;
+ zend_op *opline;
+
+ ZEND_ASSERT(ast->kind == ZEND_PRE_INC || ast->kind == ZEND_PRE_DEC);
+
+ if (var_ast->kind == ZEND_AST_PROP) {
+ opline = zend_compile_prop_common(result, var_ast, BP_VAR_RW TSRMLS_CC);
+ opline->opcode = ast->kind == ZEND_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
+ } else {
+ zend_compile_var(&var_node, var_ast, BP_VAR_RW TSRMLS_CC);
+ emit_op(result, ast->kind, &var_node, NULL TSRMLS_CC);
+ }
+}
+
+void zend_compile_cast(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *expr_ast = ast->child[0];
+ znode expr_node;
+ zend_op *opline;
+
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ opline = emit_op(result, ZEND_CAST, &expr_node, NULL TSRMLS_CC);
+ switch (ast->kind) {
+ case ZEND_AST_CAST_NULL: opline->extended_value = IS_NULL; break;
+ case ZEND_AST_CAST_BOOL: opline->extended_value = _IS_BOOL; break;
+ case ZEND_AST_CAST_INT: opline->extended_value = IS_LONG; break;
+ case ZEND_AST_CAST_DOUBLE: opline->extended_value = IS_DOUBLE; break;
+ case ZEND_AST_CAST_STRING: opline->extended_value = IS_STRING; break;
+ case ZEND_AST_CAST_ARRAY: opline->extended_value = IS_ARRAY; break;
+ case ZEND_AST_CAST_OBJECT: opline->extended_value = IS_OBJECT; break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+
+static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *cond_ast = ast->child[0];
+ zend_ast *false_ast = ast->child[2];
+
+ znode cond_node, false_node;
+ zend_op *opline_jmp_set, *opline_qm_assign;
+ zend_uint opnum_jmp_set;
+
+ ZEND_ASSERT(ast->child[1] == NULL);
+
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
+
+ opnum_jmp_set = get_next_op_number(CG(active_op_array));
+ emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL TSRMLS_CC);
+
+ zend_compile_expr(&false_node, false_ast TSRMLS_CC);
+
+ opline_jmp_set = &CG(active_op_array)->opcodes[opnum_jmp_set];
+ opline_jmp_set->op2.opline_num = get_next_op_number(CG(active_op_array)) + 1;
+ if (cond_node.op_type == IS_VAR || cond_node.op_type == IS_CV
+ || false_node.op_type == IS_VAR || false_node.op_type == IS_CV
+ ) {
+ opline_jmp_set->opcode = ZEND_JMP_SET_VAR;
+ opline_jmp_set->result_type = IS_VAR;
+ GET_NODE(result, opline_jmp_set->result);
+
+ opline_qm_assign = emit_op(NULL, ZEND_QM_ASSIGN_VAR, &false_node, NULL TSRMLS_CC);
+ } else {
+ opline_qm_assign = emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL TSRMLS_CC);
+ }
+ SET_NODE(opline_qm_assign->result, result);
+}
+
+void zend_compile_conditional(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *cond_ast = ast->child[0];
+ zend_ast *true_ast = ast->child[1];
+ zend_ast *false_ast = ast->child[2];
+
+ znode cond_node, true_node, false_node;
+ zend_op *opline_jmpz, *opline_jmp, *opline_qm_assign1, *opline_qm_assign2;
+ zend_uint opnum_jmpz, opnum_jmp, opnum_qm_assign1;
+
+ if (!true_ast) {
+ zend_compile_shorthand_conditional(result, ast TSRMLS_CC);
+ return;
+ }
+
+ zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
+
+ opnum_jmpz = get_next_op_number(CG(active_op_array));
+ emit_op(NULL, ZEND_JMPZ, &cond_node, NULL TSRMLS_CC);
+
+ zend_compile_expr(&true_node, true_ast TSRMLS_CC);
+
+ opnum_qm_assign1 = get_next_op_number(CG(active_op_array));
+ emit_op(result, ZEND_QM_ASSIGN, &true_node, NULL TSRMLS_CC);
+
+ opnum_jmp = get_next_op_number(CG(active_op_array));
+ emit_op(NULL, ZEND_JMP, NULL, NULL TSRMLS_CC);
+
+ opline_jmpz = &CG(active_op_array)->opcodes[opnum_jmpz];
+ opline_jmpz->op2.opline_num = get_next_op_number(CG(active_op_array));
+
+ zend_compile_expr(&false_node, false_ast TSRMLS_CC);
+
+ opline_qm_assign1 = &CG(active_op_array)->opcodes[opnum_qm_assign1];
+ if (true_node.op_type == IS_VAR || true_node.op_type == IS_CV
+ || false_node.op_type == IS_VAR || false_node.op_type == IS_CV
+ ) {
+ opline_qm_assign1->opcode = ZEND_QM_ASSIGN_VAR;
+ opline_qm_assign1->result_type = IS_VAR;
+ GET_NODE(result, opline_qm_assign1->result);
+ }
+
+ opline_qm_assign2 = emit_op(NULL, opline_qm_assign1->opcode, &false_node, NULL TSRMLS_CC);
+ SET_NODE(opline_qm_assign2->result, result);
+
+ opline_jmp = &CG(active_op_array)->opcodes[opnum_jmp];
+ opline_jmp->op1.opline_num = get_next_op_number(CG(active_op_array));
+}
+
+void zend_compile_print(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *expr_ast = ast->child[0];
+
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+
+ emit_op_tmp(result, ZEND_PRINT, &expr_node, NULL TSRMLS_CC);
+}
+
+void zend_compile_exit(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *expr_ast = ast->child[0];
+
+ if (expr_ast) {
+ znode expr_node;
+ zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
+ emit_op(NULL, ZEND_EXIT, &expr_node, NULL TSRMLS_CC);
+ } else {
+ emit_op(NULL, ZEND_EXIT, NULL, NULL TSRMLS_CC);
+ }
+
+ result->op_type = IS_CONST;
+ ZVAL_BOOL(&result->u.constant, 1);
+}
+
+void zend_compile_yield(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *value_ast = ast->child[0];
+ zend_ast *key_ast = ast->child[1];
+
+ znode value_node, key_node;
+ znode *value_node_ptr = NULL, *key_node_ptr = NULL;
+ zend_op *opline;
+ zend_bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+
+ if (!CG(active_op_array)->function_name) {
+ zend_error_noreturn(E_COMPILE_ERROR, "The \"yield\" expression can only be used inside a function");
+ }
+
+ CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
+
+ if (key_ast) {
+ zend_compile_expr(&key_node, key_ast TSRMLS_CC);
+ key_node_ptr = &key_node;
+ }
+
+ if (value_ast) {
+ if (returns_by_ref && zend_is_variable(value_ast) && !zend_is_call(value_ast)) {
+ zend_compile_var(&value_node, value_ast, BP_VAR_REF TSRMLS_CC);
+ } else {
+ zend_compile_expr(&value_node, value_ast TSRMLS_CC);
+ }
+ value_node_ptr = &value_node;
+ }
+
+ opline = emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr TSRMLS_CC);
+
+ if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
+ opline->extended_value = ZEND_RETURNS_FUNCTION;
+ }
+}
+
+void zend_compile_instanceof(znode *result, zend_ast *ast TSRMLS_DC) {
+ zend_ast *obj_ast = ast->child[0];
+ zend_ast *class_ast = ast->child[1];
+
+ znode obj_node, class_node;
+ zend_op *opline;
+
+ zend_compile_expr(&obj_node, obj_ast TSRMLS_CC);
+ if (obj_node.op_type == IS_CONST) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "instanceof expects an object instance, constant given");
+ }
+
+ opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+ opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
+
+ emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, &class_node TSRMLS_CC);
+}
+
void zend_compile_stmt(zend_ast *ast TSRMLS_DC) {
switch (ast->kind) {
case ZEND_AST_GLOBAL:
case ZEND_AST_ASSIGN_REF:
zend_compile_assign_ref(result, ast TSRMLS_CC);
return;
+ case ZEND_NEW:
+ zend_compile_new(result, ast TSRMLS_CC);
+ return;
+ case ZEND_CLONE:
+ zend_compile_clone(result, ast TSRMLS_CC);
+ return;
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
case ZEND_ASSIGN_MUL:
case ZEND_ASSIGN_SR:
zend_compile_compound_assign(result, ast TSRMLS_CC);
return;
+ case ZEND_BOOL_XOR:
+ case ZEND_BW_OR:
+ case ZEND_BW_AND:
+ case ZEND_BW_XOR:
+ case ZEND_CONCAT:
+ case ZEND_ADD:
+ case ZEND_SUB:
+ case ZEND_MUL:
+ case ZEND_POW:
+ case ZEND_DIV:
+ case ZEND_MOD:
+ case ZEND_SL:
+ case ZEND_SR:
+ case ZEND_IS_IDENTICAL:
+ case ZEND_IS_NOT_IDENTICAL:
+ case ZEND_IS_EQUAL:
+ case ZEND_IS_NOT_EQUAL:
+ case ZEND_IS_SMALLER:
+ case ZEND_IS_SMALLER_OR_EQUAL:
+ zend_compile_binary_op(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_GREATER:
+ case ZEND_AST_GREATER_EQUAL:
+ zend_compile_greater(result, ast TSRMLS_CC);
+ return;
+ case ZEND_BOOL_NOT:
+ case ZEND_BW_NOT:
+ zend_compile_unary_op(result, ast TSRMLS_CC);
+ return;
+ case ZEND_UNARY_PLUS:
+ case ZEND_UNARY_MINUS:
+ zend_compile_unary_pm(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_AND:
+ case ZEND_AST_OR:
+ zend_compile_short_circuiting(result, ast TSRMLS_CC);
+ return;
+ case ZEND_POST_INC:
+ case ZEND_POST_DEC:
+ zend_compile_post_incdec(result, ast TSRMLS_CC);
+ return;
+ case ZEND_PRE_INC:
+ case ZEND_PRE_DEC:
+ zend_compile_pre_incdec(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CAST_NULL:
+ case ZEND_AST_CAST_BOOL:
+ case ZEND_AST_CAST_INT:
+ case ZEND_AST_CAST_DOUBLE:
+ case ZEND_AST_CAST_STRING:
+ case ZEND_AST_CAST_ARRAY:
+ case ZEND_AST_CAST_OBJECT:
+ zend_compile_cast(result, ast TSRMLS_CC);
+ return;
+ case ZEND_AST_CONDITIONAL:
+ zend_compile_conditional(result, ast TSRMLS_CC);
+ return;
+ case ZEND_PRINT:
+ zend_compile_print(result, ast TSRMLS_CC);
+ return;
+ case ZEND_EXIT:
+ zend_compile_exit(result, ast TSRMLS_CC);
+ return;
+ case ZEND_YIELD:
+ zend_compile_yield(result, ast TSRMLS_CC);
+ return;
+ case ZEND_INSTANCEOF:
+ zend_compile_instanceof(result, ast TSRMLS_CC);
+ return;
default:
ZEND_ASSERT(0 /* not supported */);
}
for_statement { zend_do_for_end(&$7 TSRMLS_CC); }
| T_SWITCH parenthesis_expr { zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); }
| T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); }
- | T_BREAK expr ';' { zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); }
+ | T_BREAK expr ';' { AC($2); zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); }
| T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); }
- | T_CONTINUE expr ';' { zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
+ | T_CONTINUE expr ';' { AC($2); zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
| T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); }
- | T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); }
+ | T_RETURN expr_without_variable ';' { AC($2); zend_do_return(&$2, 0 TSRMLS_CC); }
| T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); }
- | yield_expr ';' { zend_do_free(&$1 TSRMLS_CC); }
+ | yield_expr ';' { AC($1); zend_do_free(&$1 TSRMLS_CC); }
| T_GLOBAL global_var_list ';'
| T_STATIC static_var_list ';'
| T_ECHO echo_expr_list ';'
| T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
- | expr ';' { zend_do_free(&$1 TSRMLS_CC); }
+ | expr ';' { AC($1); zend_do_free(&$1 TSRMLS_CC); }
| T_UNSET '(' unset_variables ')' ';'
| T_FOREACH '(' variable T_AS
{ zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
| T_FOREACH '(' expr_without_variable T_AS
- { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
+ { AC($3); zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
| T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
| T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
catch_statement { zend_do_bind_catch(&$1, &$6 TSRMLS_CC); }
finally_statement { zend_do_end_finally(&$1, &$6, &$8 TSRMLS_CC); }
- | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
+ | T_THROW expr ';' { AC($2); zend_do_throw(&$2 TSRMLS_CC); }
| T_GOTO T_STRING ';' { zend_do_goto(&$2 TSRMLS_CC); }
;
case_list:
/* empty */ { $$.op_type = IS_UNUSED; }
- | case_list T_CASE expr case_separator { zend_do_extended_info(TSRMLS_C); zend_do_case_before_statement(&$1, &$2, &$3 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
+ | case_list T_CASE expr case_separator { AC($3); zend_do_extended_info(TSRMLS_C); zend_do_case_before_statement(&$1, &$2, &$3 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
| case_list T_DEFAULT case_separator { zend_do_extended_info(TSRMLS_C); zend_do_default_before_statement(&$1, &$2 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
;
| fully_qualified_class_name { $$ = $1; }
;
-
function_call_parameter_list:
- '(' ')' { Z_LVAL($$.u.constant) = 0; }
- | '(' non_empty_function_call_parameter_list ')' { $$ = $2; }
- | '(' yield_expr ')' { zend_do_pass_param(&$2, ZEND_SEND_VAL TSRMLS_CC); }
-;
-
-
-non_empty_function_call_parameter_list:
- function_call_parameter
- | non_empty_function_call_parameter_list ',' function_call_parameter
-;
-
-function_call_parameter:
- expr_without_variable { zend_do_pass_param(&$1, ZEND_SEND_VAL TSRMLS_CC); }
- | variable { zend_do_pass_param(&$1, ZEND_SEND_VAR TSRMLS_CC); }
- | '&' w_variable { zend_do_pass_param(&$2, ZEND_SEND_REF TSRMLS_CC); }
- | T_ELLIPSIS expr { zend_do_unpack_params(&$2 TSRMLS_CC); }
-;
-
-function_call_parameter_list_ast:
'(' ')' { $$.u.ast = zend_ast_create_dynamic(ZEND_AST_PARAMS); }
- | '(' non_empty_function_call_parameter_list_ast ')' { $$.u.ast = $2.u.ast; }
+ | '(' non_empty_function_call_parameter_list ')' { $$.u.ast = $2.u.ast; }
| '(' yield_expr ')'
{ $$.u.ast = zend_ast_create_dynamic(ZEND_AST_PARAMS);
- zend_ast_dynamic_add(&$$.u.ast, AST_ZNODE(&$2)); }
+ zend_ast_dynamic_add(&$$.u.ast, $2.u.ast); }
;
-non_empty_function_call_parameter_list_ast:
- function_call_parameter_ast
+non_empty_function_call_parameter_list:
+ function_call_parameter
{ $$.u.ast = zend_ast_create_dynamic(ZEND_AST_PARAMS);
zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); }
- | non_empty_function_call_parameter_list_ast ',' function_call_parameter_ast
+ | non_empty_function_call_parameter_list ',' function_call_parameter
{ zend_ast_dynamic_add(&$1.u.ast, $3.u.ast); $$.u.ast = $1.u.ast; }
;
-function_call_parameter_ast:
- expr_without_variable { $$.u.ast = AST_ZNODE(&$1); }
+function_call_parameter:
+ expr_without_variable { $$.u.ast = $1.u.ast; }
| variable { $$.u.ast = $1.u.ast; }
| '&' w_variable { /* ERROR */ ZEND_ASSERT(0); }
- | T_ELLIPSIS expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_UNPACK, AST_ZNODE(&$2)); }
+ | T_ELLIPSIS expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_UNPACK, $2.u.ast); }
;
global_var_list:
;
echo_expr_list:
- echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
- | expr { zend_do_echo(&$1 TSRMLS_CC); }
+ echo_expr_list ',' expr { AC($3); zend_do_echo(&$3 TSRMLS_CC); }
+ | expr { AC($1); zend_do_echo(&$1 TSRMLS_CC); }
;
;
non_empty_for_expr:
- non_empty_for_expr ',' { zend_do_free(&$1 TSRMLS_CC); } expr { $$ = $4; }
- | expr { $$ = $1; }
+ non_empty_for_expr ',' { zend_do_free(&$1 TSRMLS_CC); } expr { AC($4); $$ = $4; }
+ | expr { AC($1); $$ = $1; }
;
new_expr:
- T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ T_NEW class_name_reference ctor_arguments
+ { $$.u.ast = zend_ast_create_binary(ZEND_NEW, $2.u.ast, $3.u.ast); }
;
expr_without_variable:
T_LIST '(' assignment_list ')' '=' expr
- { $$.u.ast = zend_ast_create_binary(ZEND_AST_ASSIGN, $3.u.ast, AST_ZNODE(&$6));
- AST_COMPILE(&$$, $$.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_ASSIGN, $3.u.ast, $6.u.ast); }
| variable '=' expr
- { $$.u.ast = zend_ast_create_binary(ZEND_AST_ASSIGN, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $$.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_ASSIGN, $1.u.ast, $3.u.ast); }
| variable '=' '&' variable
- { $$.u.ast = zend_ast_create_binary(ZEND_AST_ASSIGN_REF, $1.u.ast, $4.u.ast);
- AST_COMPILE(&$$, $$.u.ast); }
- | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
- | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_ASSIGN_REF, $1.u.ast, $4.u.ast); }
+ | variable '=' '&' T_NEW class_name_reference ctor_arguments
+ { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");
+ $$.u.ast = zend_ast_create_binary(ZEND_AST_ASSIGN_REF, $1.u.ast,
+ zend_ast_create_binary(ZEND_NEW, $5.u.ast, $6.u.ast)); }
+ | T_CLONE expr { $$.u.ast = zend_ast_create_unary(ZEND_CLONE, $2.u.ast); }
| variable T_PLUS_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_ADD, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_ADD, $1.u.ast, $3.u.ast); }
| variable T_MINUS_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_SUB, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_SUB, $1.u.ast, $3.u.ast); }
| variable T_MUL_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_MUL, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_MUL, $1.u.ast, $3.u.ast); }
| variable T_POW_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_POW, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_POW, $1.u.ast, $3.u.ast); }
| variable T_DIV_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_DIV, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_DIV, $1.u.ast, $3.u.ast); }
| variable T_CONCAT_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_CONCAT, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_CONCAT, $1.u.ast, $3.u.ast); }
| variable T_MOD_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_MOD, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_MOD, $1.u.ast, $3.u.ast); }
| variable T_AND_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_BW_AND, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_BW_AND, $1.u.ast, $3.u.ast); }
| variable T_OR_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_BW_OR, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_BW_OR, $1.u.ast, $3.u.ast); }
| variable T_XOR_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_BW_XOR, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_BW_XOR, $1.u.ast, $3.u.ast); }
| variable T_SL_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_SL, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_SL, $1.u.ast, $3.u.ast); }
| variable T_SR_EQUAL expr
- { $2.u.ast = zend_ast_create_binary(ZEND_ASSIGN_SR, $1.u.ast, AST_ZNODE(&$3));
- AST_COMPILE(&$$, $2.u.ast); }
- | rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
- | T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
- | rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
- | T_DEC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_DEC TSRMLS_CC); }
- | expr T_BOOLEAN_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_BOOLEAN_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_LOGICAL_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
- | expr T_LOGICAL_XOR expr { zend_do_binary_op(ZEND_BOOL_XOR, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '|' expr { zend_do_binary_op(ZEND_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '&' expr { zend_do_binary_op(ZEND_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '^' expr { zend_do_binary_op(ZEND_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '.' expr { zend_do_binary_op(ZEND_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '+' expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '-' expr { zend_do_binary_op(ZEND_SUB, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '*' expr { zend_do_binary_op(ZEND_MUL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_POW expr { zend_do_binary_op(ZEND_POW, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '/' expr { zend_do_binary_op(ZEND_DIV, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '%' expr { zend_do_binary_op(ZEND_MOD, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_SL expr { zend_do_binary_op(ZEND_SL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_SR expr { zend_do_binary_op(ZEND_SR, &$$, &$1, &$3 TSRMLS_CC); }
- | '+' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; zend_do_binary_op(ZEND_ADD, &$$, &$1, &$2 TSRMLS_CC); } }
- | '-' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; zend_do_binary_op(ZEND_SUB, &$$, &$1, &$2 TSRMLS_CC); } }
- | '!' expr { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$2 TSRMLS_CC); }
- | '~' expr { zend_do_unary_op(ZEND_BW_NOT, &$$, &$2 TSRMLS_CC); }
- | expr T_IS_IDENTICAL expr { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_NOT_IDENTICAL expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_EQUAL expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_NOT_EQUAL expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '<' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 TSRMLS_CC); }
- | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
- | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }
- | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
- | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
- | parenthesis_expr { $$ = $1; }
- | new_expr { $$ = $1; }
- | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
- expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
- expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
- | expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
- expr { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
- | internal_functions_in_yacc { $$ = $1; }
- | T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
- | T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }
- | T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); }
- | T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
- | T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
- | T_BOOL_CAST expr { zend_do_cast(&$$, &$2, _IS_BOOL TSRMLS_CC); }
- | T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
- | T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
- | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
- | scalar { $$ = $1; }
- | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
- | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
- | T_YIELD { zend_do_yield(&$$, NULL, NULL, 0 TSRMLS_CC); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_ASSIGN_SR, $1.u.ast, $3.u.ast); }
+ | variable T_INC { $$.u.ast = zend_ast_create_unary(ZEND_POST_INC, $1.u.ast); }
+ | T_INC variable { $$.u.ast = zend_ast_create_unary(ZEND_PRE_INC, $2.u.ast); }
+ | variable T_DEC { $$.u.ast = zend_ast_create_unary(ZEND_POST_DEC, $1.u.ast); }
+ | T_DEC variable { $$.u.ast = zend_ast_create_unary(ZEND_PRE_DEC, $2.u.ast); }
+ | expr T_BOOLEAN_OR expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_OR, $1.u.ast, $3.u.ast); }
+ | expr T_BOOLEAN_AND expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_AND, $1.u.ast, $3.u.ast); }
+ | expr T_LOGICAL_OR expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_OR, $1.u.ast, $3.u.ast); }
+ | expr T_LOGICAL_AND expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_AND, $1.u.ast, $3.u.ast); }
+ | expr T_LOGICAL_XOR expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_XOR, $1.u.ast, $3.u.ast); }
+ | expr '|' expr { $$.u.ast = zend_ast_create_binary(ZEND_BW_OR, $1.u.ast, $3.u.ast); }
+ | expr '&' expr { $$.u.ast = zend_ast_create_binary(ZEND_BW_AND, $1.u.ast, $3.u.ast); }
+ | expr '^' expr { $$.u.ast = zend_ast_create_binary(ZEND_BW_XOR, $1.u.ast, $3.u.ast); }
+ | expr '.' expr { $$.u.ast = zend_ast_create_binary(ZEND_CONCAT, $1.u.ast, $3.u.ast); }
+ | expr '+' expr { $$.u.ast = zend_ast_create_binary(ZEND_ADD, $1.u.ast, $3.u.ast); }
+ | expr '-' expr { $$.u.ast = zend_ast_create_binary(ZEND_SUB, $1.u.ast, $3.u.ast); }
+ | expr '*' expr { $$.u.ast = zend_ast_create_binary(ZEND_MUL, $1.u.ast, $3.u.ast); }
+ | expr T_POW expr { $$.u.ast = zend_ast_create_binary(ZEND_POW, $1.u.ast, $3.u.ast); }
+ | expr '/' expr { $$.u.ast = zend_ast_create_binary(ZEND_DIV, $1.u.ast, $3.u.ast); }
+ | expr '%' expr { $$.u.ast = zend_ast_create_binary(ZEND_MOD, $1.u.ast, $3.u.ast); }
+ | expr T_SL expr { $$.u.ast = zend_ast_create_binary(ZEND_SL, $1.u.ast, $3.u.ast); }
+ | expr T_SR expr { $$.u.ast = zend_ast_create_binary(ZEND_SR, $1.u.ast, $3.u.ast); }
+ | '+' expr %prec T_INC { $$.u.ast = zend_ast_create_unary(ZEND_UNARY_PLUS, $2.u.ast); }
+ | '-' expr %prec T_INC { $$.u.ast = zend_ast_create_unary(ZEND_UNARY_MINUS, $2.u.ast); }
+ | '!' expr { $$.u.ast = zend_ast_create_unary(ZEND_BOOL_NOT, $2.u.ast); }
+ | '~' expr { $$.u.ast = zend_ast_create_unary(ZEND_BW_NOT, $2.u.ast); }
+ | expr T_IS_IDENTICAL expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_IS_IDENTICAL, $1.u.ast, $3.u.ast); }
+ | expr T_IS_NOT_IDENTICAL expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_IS_NOT_IDENTICAL, $1.u.ast, $3.u.ast); }
+ | expr T_IS_EQUAL expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_IS_EQUAL, $1.u.ast, $3.u.ast); }
+ | expr T_IS_NOT_EQUAL expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_IS_NOT_EQUAL, $1.u.ast, $3.u.ast); }
+ | expr '<' expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER, $1.u.ast, $3.u.ast); }
+ | expr T_IS_SMALLER_OR_EQUAL expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER_OR_EQUAL, $1.u.ast, $3.u.ast); }
+ | expr '>' expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_GREATER, $1.u.ast, $3.u.ast); }
+ | expr T_IS_GREATER_OR_EQUAL expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_GREATER_EQUAL, $1.u.ast, $3.u.ast); }
+ | expr T_INSTANCEOF class_name_reference
+ { $$.u.ast = zend_ast_create_binary(ZEND_INSTANCEOF, $1.u.ast, $3.u.ast); }
+ | parenthesis_expr { $$.u.ast = AST_ZNODE(&$1); }
+ | new_expr { $$.u.ast = $1.u.ast; }
+ | expr '?' expr ':' expr
+ { $$.u.ast = zend_ast_create_ternary(
+ ZEND_AST_CONDITIONAL, $1.u.ast, $3.u.ast, $5.u.ast); }
+ | expr '?' ':' expr
+ { $$.u.ast = zend_ast_create_ternary(ZEND_AST_CONDITIONAL, $1.u.ast, NULL, $4.u.ast); }
+ | internal_functions_in_yacc { $$.u.ast = AST_ZNODE(&$1); }
+ | T_INT_CAST expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_CAST_INT, $2.u.ast); }
+ | T_DOUBLE_CAST expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_CAST_DOUBLE, $2.u.ast); }
+ | T_STRING_CAST expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_CAST_STRING, $2.u.ast); }
+ | T_ARRAY_CAST expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_CAST_ARRAY, $2.u.ast); }
+ | T_OBJECT_CAST expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_CAST_OBJECT, $2.u.ast); }
+ | T_BOOL_CAST expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_CAST_BOOL, $2.u.ast); }
+ | T_UNSET_CAST expr { $$.u.ast = zend_ast_create_unary(ZEND_AST_CAST_NULL, $2.u.ast); }
+ | T_EXIT exit_expr { $$.u.ast = zend_ast_create_unary(ZEND_EXIT, $2.u.ast); }
+ | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { AC($3); zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; AZ($$); }
+ | scalar { $$.u.ast = AST_ZNODE(&$1); }
+ | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); AZ($$); }
+ | T_PRINT expr { $$.u.ast = zend_ast_create_unary(ZEND_PRINT, $2.u.ast); }
+ | T_YIELD { $$.u.ast = zend_ast_create_binary(ZEND_YIELD, NULL, NULL); }
| function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); }
'(' parameter_list ')' lexical_vars
- '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $3; }
+ '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $3; AZ($$); }
| T_STATIC function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); }
'(' parameter_list ')' lexical_vars
- '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $4; }
+ '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $4; AZ($$); }
;
yield_expr:
- T_YIELD expr_without_variable { zend_do_yield(&$$, &$2, NULL, 0 TSRMLS_CC); }
- | T_YIELD variable { zend_do_yield(&$$, &$2, NULL, 1 TSRMLS_CC); }
- | T_YIELD expr T_DOUBLE_ARROW expr_without_variable { zend_do_yield(&$$, &$4, &$2, 0 TSRMLS_CC); }
- | T_YIELD expr T_DOUBLE_ARROW variable { zend_do_yield(&$$, &$4, &$2, 1 TSRMLS_CC); }
+ T_YIELD expr { $$.u.ast = zend_ast_create_binary(ZEND_YIELD, $2.u.ast, NULL); }
+ | T_YIELD expr T_DOUBLE_ARROW expr
+ { $$.u.ast = zend_ast_create_binary(ZEND_YIELD, $4.u.ast, $2.u.ast); }
;
function:
;
function_call:
- namespace_name function_call_parameter_list_ast
+ namespace_name function_call_parameter_list
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_CALL,
zend_ast_create_unary(ZEND_AST_NAME, AST_ZVAL(&$1)), $2.u.ast); }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name function_call_parameter_list_ast
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name function_call_parameter_list
{ ZVAL_EMPTY_STRING(&$1.u.constant);
zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC);
$$.u.ast = zend_ast_create_binary(ZEND_AST_CALL,
zend_ast_create_unary(ZEND_AST_NAME_FQ, AST_ZVAL(&$1)), $4.u.ast); }
- | T_NS_SEPARATOR namespace_name function_call_parameter_list_ast
+ | T_NS_SEPARATOR namespace_name function_call_parameter_list
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_CALL,
zend_ast_create_unary(ZEND_AST_NAME_FQ, AST_ZVAL(&$2)), $3.u.ast); }
- | class_name T_PAAMAYIM_NEKUDOTAYIM member_name function_call_parameter_list_ast
+ | class_name T_PAAMAYIM_NEKUDOTAYIM member_name function_call_parameter_list
{ $$.u.ast = zend_ast_create_ternary(ZEND_AST_STATIC_CALL,
AST_ZVAL(&$1), $3.u.ast, $4.u.ast); }
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name function_call_parameter_list_ast
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name function_call_parameter_list
{ $$.u.ast = zend_ast_create_ternary(ZEND_AST_STATIC_CALL,
AST_ZNODE(&$1), $3.u.ast, $4.u.ast); }
- | callable_expr function_call_parameter_list_ast
+ | callable_expr function_call_parameter_list
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_CALL, $1.u.ast, $2.u.ast); }
;
class_name_reference:
- class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
- | new_variable { AST_COMPILE_VAR(&$1, $1.u.ast, BP_VAR_R); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+ class_name { $$.u.ast = AST_ZVAL(&$1); }
+ | new_variable { $$.u.ast = $1.u.ast; }
;
exit_expr:
- /* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
- | '(' ')' { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
- | parenthesis_expr { $$ = $1; }
+ /* empty */ { $$.u.ast = NULL; }
+ | '(' ')' { $$.u.ast = NULL; }
+ | parenthesis_expr { $$.u.ast = AST_ZNODE(&$1); }
;
backticks_expr:
ctor_arguments:
- /* empty */ { Z_LVAL($$.u.constant) = 0; }
- | function_call_parameter_list { $$ = $1; }
+ /* empty */ { $$.u.ast = zend_ast_create_dynamic(ZEND_AST_PARAMS); }
+ | function_call_parameter_list { $$.u.ast = $1.u.ast; }
;
;
expr:
- r_variable { $$ = $1; }
- | expr_without_variable { $$ = $1; }
+ variable { $$.u.ast = $1.u.ast; }
+ | expr_without_variable { $$.u.ast = $1.u.ast; }
;
parenthesis_expr:
- '(' expr ')' { $$ = $2; }
- | '(' yield_expr ')' { $$ = $2; }
-;
-
-
-r_variable:
- variable { zend_compile_var(&$$, $1.u.ast, BP_VAR_R TSRMLS_CC); zend_ast_destroy($1.u.ast); }
+ '(' expr ')' { AST_COMPILE(&$$, $2.u.ast); }
+ | '(' yield_expr ')' { AST_COMPILE(&$$, $2.u.ast); }
;
w_variable:
- variable { zend_compile_var(&$$, $1.u.ast, BP_VAR_W TSRMLS_CC); zend_ast_destroy($1.u.ast);
- zend_check_writable_variable(&$1); }
-;
-
-rw_variable:
- variable { zend_compile_var(&$$, $1.u.ast, BP_VAR_RW TSRMLS_CC); zend_ast_destroy($1.u.ast);
- zend_check_writable_variable(&$$); }
+ variable { zend_ensure_writable_variable($1.u.ast); AST_COMPILE_VAR(&$$, $1.u.ast, BP_VAR_W); }
;
variable_class_name:
dereferencable:
variable { $$.u.ast = $1.u.ast; }
- | '(' expr ')' { $$.u.ast = AST_ZNODE(&$2); }
+ | '(' expr ')' { $$.u.ast = $2.u.ast; }
| dereferencable_scalar { $$.u.ast = AST_ZNODE(&$1); }
;
callable_expr:
callable_variable { $$.u.ast = $1.u.ast; }
- | '(' expr ')' { $$.u.ast = AST_ZNODE(&$2); }
+ | '(' expr ')' { $$.u.ast = $2.u.ast; }
| dereferencable_scalar { $$.u.ast = AST_ZNODE(&$1); }
;
| dereferencable '[' dim_offset ']'
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_DIM, $1.u.ast, $3.u.ast); }
| dereferencable '{' expr '}'
- { $$.u.ast = zend_ast_create_binary(ZEND_AST_DIM, $1.u.ast, AST_ZNODE(&$3)); }
- | dereferencable T_OBJECT_OPERATOR member_name function_call_parameter_list_ast
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_DIM, $1.u.ast, $3.u.ast); }
+ | dereferencable T_OBJECT_OPERATOR member_name function_call_parameter_list
{ $$.u.ast = zend_ast_create_ternary(ZEND_AST_METHOD_CALL, $1.u.ast, $3.u.ast, $4.u.ast); }
| function_call { $$.u.ast = $1.u.ast; }
;
T_VARIABLE
{ $$.u.ast = AST_ZVAL(&$1); }
| '$' '{' expr '}'
- { $$.u.ast = zend_ast_create_znode(&$3); }
+ { $$.u.ast = $3.u.ast; }
| '$' simple_variable
{ $$.u.ast = zend_ast_create_unary(ZEND_AST_VAR, $2.u.ast); }
;
| new_variable '[' dim_offset ']'
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_DIM, $1.u.ast, $3.u.ast); }
| new_variable '{' expr '}'
- { $$.u.ast = zend_ast_create_binary(ZEND_AST_DIM, $1.u.ast, AST_ZNODE(&$3)); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_DIM, $1.u.ast, $3.u.ast); }
| new_variable T_OBJECT_OPERATOR member_name
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_PROP, $1.u.ast, $3.u.ast); }
| class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
dim_offset:
/* empty */ { $$.u.ast = NULL; }
- | expr { $$.u.ast = AST_ZNODE(&$1); }
+ | expr { $$.u.ast = $1.u.ast; }
;
member_name:
T_STRING { $$.u.ast = AST_ZVAL(&$1); }
- | '{' expr '}' { $$.u.ast = AST_ZNODE(&$2); }
+ | '{' expr '}' { $$.u.ast = $2.u.ast; }
| simple_variable { $$.u.ast = zend_ast_create_unary(ZEND_AST_VAR, $1.u.ast); }
;
;
non_empty_array_pair_list:
- non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { zend_do_add_array_element(&$$, &$5, &$3, 0 TSRMLS_CC); }
- | non_empty_array_pair_list ',' expr { zend_do_add_array_element(&$$, &$3, NULL, 0 TSRMLS_CC); }
- | expr T_DOUBLE_ARROW expr { zend_do_init_array(&$$, &$3, &$1, 0 TSRMLS_CC); }
- | expr { zend_do_init_array(&$$, &$1, NULL, 0 TSRMLS_CC); }
- | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable { zend_do_add_array_element(&$$, &$6, &$3, 1 TSRMLS_CC); }
+ non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { AC($3); AC($5); zend_do_add_array_element(&$$, &$5, &$3, 0 TSRMLS_CC); }
+ | non_empty_array_pair_list ',' expr { AC($3); zend_do_add_array_element(&$$, &$3, NULL, 0 TSRMLS_CC); }
+ | expr T_DOUBLE_ARROW expr { AC($1); AC($3); zend_do_init_array(&$$, &$3, &$1, 0 TSRMLS_CC); }
+ | expr { AC($1); zend_do_init_array(&$$, &$1, NULL, 0 TSRMLS_CC); }
+ | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable { AC($3); zend_do_add_array_element(&$$, &$6, &$3, 1 TSRMLS_CC); }
| non_empty_array_pair_list ',' '&' w_variable { zend_do_add_array_element(&$$, &$4, NULL, 1 TSRMLS_CC); }
- | expr T_DOUBLE_ARROW '&' w_variable { zend_do_init_array(&$$, &$4, &$1, 1 TSRMLS_CC); }
+ | expr T_DOUBLE_ARROW '&' w_variable { AC($1); zend_do_init_array(&$$, &$4, &$1, 1 TSRMLS_CC); }
| '&' w_variable { zend_do_init_array(&$$, &$2, NULL, 1 TSRMLS_CC); }
;
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_PROP,
zend_ast_create_var(&$1.u.constant), AST_ZNODE(&$3)); }
| T_DOLLAR_OPEN_CURLY_BRACES expr '}'
- { $$.u.ast = zend_ast_create_unary(ZEND_AST_VAR, AST_ZNODE(&$2)); }
+ { $$.u.ast = zend_ast_create_unary(ZEND_AST_VAR, $2.u.ast); }
| T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_DIM,
- zend_ast_create_var(&$2.u.constant), AST_ZNODE(&$4)); }
+ zend_ast_create_var(&$2.u.constant), $4.u.ast); }
| T_CURLY_OPEN variable '}' { $$.u.ast = $2.u.ast; }
;
internal_functions_in_yacc:
T_ISSET '(' isset_variables ')' { $$ = $3; }
| T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
- | T_EMPTY '(' expr_without_variable ')' { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$3 TSRMLS_CC); }
- | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
- | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
- | T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
- | T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
- | T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
+ | T_EMPTY '(' expr_without_variable ')' { AC($3); zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$3 TSRMLS_CC); }
+ | T_INCLUDE expr { AC($2); zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
+ | T_INCLUDE_ONCE expr { AC($2); zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
+ | T_EVAL '(' expr ')' { AC($3); zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
+ | T_REQUIRE expr { AC($2); zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
+ | T_REQUIRE_ONCE expr { AC($2); zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
;
isset_variables: