mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Use separate node type for lists
This saves storing the children count for normal ast nodes.
This commit is contained in:
parent
21eb6807c9
commit
d3cb239305
4 changed files with 381 additions and 321 deletions
128
Zend/zend_ast.c
128
Zend/zend_ast.c
|
@ -79,7 +79,6 @@ static zend_ast *zend_ast_create_from_va_list(
|
|||
ast->kind = kind;
|
||||
ast->attr = attr;
|
||||
ast->lineno = UINT_MAX;
|
||||
ast->children = children;
|
||||
|
||||
for (i = 0; i < children; ++i) {
|
||||
ast->child[i] = va_arg(va, zend_ast *);
|
||||
|
@ -124,16 +123,16 @@ ZEND_API zend_ast *zend_ast_create(
|
|||
return ast;
|
||||
}
|
||||
|
||||
ZEND_API zend_ast *zend_ast_create_dynamic(zend_ast_kind kind)
|
||||
{
|
||||
ZEND_API zend_ast *zend_ast_create_dynamic(zend_ast_kind kind) {
|
||||
/* use 4 children as default */
|
||||
TSRMLS_FETCH();
|
||||
zend_ast *ast = zend_arena_alloc(&CG(ast_arena), sizeof(zend_ast) + sizeof(zend_ast *) * 3);
|
||||
ast->kind = kind;
|
||||
ast->attr = 0;
|
||||
ast->lineno = CG(zend_lineno);
|
||||
ast->children = 0;
|
||||
return ast;
|
||||
zend_ast_list *list = zend_arena_alloc(&CG(ast_arena),
|
||||
sizeof(zend_ast_list) + sizeof(zend_ast *) * 3);
|
||||
list->kind = kind;
|
||||
list->attr = 0;
|
||||
list->lineno = CG(zend_lineno);
|
||||
list->children = 0;
|
||||
return (zend_ast *) list;
|
||||
}
|
||||
|
||||
static inline zend_bool is_power_of_two(unsigned short n) {
|
||||
|
@ -142,39 +141,17 @@ static inline zend_bool is_power_of_two(unsigned short n) {
|
|||
|
||||
ZEND_API zend_ast *zend_ast_dynamic_add(zend_ast *ast, zend_ast *op)
|
||||
{
|
||||
if (ast->children >= 4 && is_power_of_two(ast->children)) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
if (list->children >= 4 && is_power_of_two(list->children)) {
|
||||
TSRMLS_FETCH();
|
||||
size_t old_size = sizeof(zend_ast) + sizeof(zend_ast *) * (ast->children - 1);
|
||||
zend_ast *new_ast = zend_arena_alloc(&CG(ast_arena),
|
||||
sizeof(zend_ast) + sizeof(zend_ast *) * (ast->children * 2 - 1));
|
||||
memcpy(new_ast, ast, old_size);
|
||||
ast = new_ast;
|
||||
}
|
||||
ast->child[ast->children++] = op;
|
||||
return ast;
|
||||
}
|
||||
|
||||
ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast)
|
||||
{
|
||||
*ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast *) * ((*ast)->children - 1));
|
||||
}
|
||||
|
||||
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ast->kind == ZEND_AST_ZVAL) {
|
||||
return !Z_CONSTANT_P(zend_ast_get_zval(ast));
|
||||
} else {
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
if (ast->child[i]) {
|
||||
if (!zend_ast_is_ct_constant(ast->child[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
size_t old_size = sizeof(zend_ast_list) + sizeof(zend_ast *) * (list->children - 1);
|
||||
zend_ast_list *new_list = zend_arena_alloc(&CG(ast_arena),
|
||||
sizeof(zend_ast_list) + sizeof(zend_ast *) * (list->children * 2 - 1));
|
||||
memcpy(new_list, list, old_size);
|
||||
list = new_list;
|
||||
}
|
||||
list->child[list->children++] = op;
|
||||
return (zend_ast *) list;
|
||||
}
|
||||
|
||||
static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TSRMLS_DC)
|
||||
|
@ -237,16 +214,14 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
|
|||
zval_dtor(&op2);
|
||||
break;
|
||||
}
|
||||
case ZEND_BW_NOT:
|
||||
case ZEND_AST_UNARY_OP:
|
||||
{
|
||||
unary_op_type op = get_unary_op(ast->attr);
|
||||
zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
|
||||
bitwise_not_function(result, &op1 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
break;
|
||||
case ZEND_BOOL_NOT:
|
||||
zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
|
||||
boolean_not_function(result, &op1 TSRMLS_CC);
|
||||
op(result, &op1 TSRMLS_CC);
|
||||
zval_dtor(&op1);
|
||||
break;
|
||||
}
|
||||
case ZEND_AST_ZVAL:
|
||||
ZVAL_DUP(result, zend_ast_get_zval(ast));
|
||||
if (Z_OPT_CONSTANT_P(result)) {
|
||||
|
@ -305,8 +280,9 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
|
|||
array_init(result);
|
||||
{
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
zend_ast *elem = ast->child[i];
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
for (i = 0; i < list->children; i++) {
|
||||
zend_ast *elem = list->child[i];
|
||||
if (elem->child[1]) {
|
||||
zend_ast_evaluate(&op1, elem->child[1], scope TSRMLS_CC);
|
||||
} else {
|
||||
|
@ -341,18 +317,29 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
|
|||
if (ast == NULL) {
|
||||
return NULL;
|
||||
} else if (ast->kind == ZEND_AST_ZVAL) {
|
||||
zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval));
|
||||
copy->kind = ZEND_AST_ZVAL;
|
||||
copy->attr = ast->attr;
|
||||
ZVAL_DUP(©->val, zend_ast_get_zval(ast));
|
||||
return (zend_ast *) copy;
|
||||
zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
|
||||
new->kind = ZEND_AST_ZVAL;
|
||||
new->attr = ast->attr;
|
||||
ZVAL_DUP(&new->val, zend_ast_get_zval(ast));
|
||||
return (zend_ast *) new;
|
||||
} else if (zend_ast_is_list(ast)) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_ast_list *new = emalloc(sizeof(zend_ast_list)
|
||||
+ sizeof(zend_ast *) * (list->children - 1));
|
||||
zend_uint i;
|
||||
new->kind = list->kind;
|
||||
new->attr = list->attr;
|
||||
new->children = list->children;
|
||||
for (i = 0; i < list->children; i++) {
|
||||
new->child[i] = zend_ast_copy(list->child[i]);
|
||||
}
|
||||
return (zend_ast *) new;
|
||||
} else {
|
||||
zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast *) * (ast->children - 1));
|
||||
int i;
|
||||
zend_uint i, children = zend_ast_get_num_children(ast);
|
||||
zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast *) * (children - 1));
|
||||
new->kind = ast->kind;
|
||||
new->attr = ast->attr;
|
||||
new->children = ast->children;
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
for (i = 0; i < children; i++) {
|
||||
new->child[i] = zend_ast_copy(ast->child[i]);
|
||||
}
|
||||
return new;
|
||||
|
@ -386,9 +373,15 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
|
|||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (zend_ast_is_list(ast)) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; i++) {
|
||||
for (i = 0; i < list->children; i++) {
|
||||
zend_ast_destroy_ex(list->child[i], free);
|
||||
}
|
||||
} else {
|
||||
zend_uint i, children = zend_ast_get_num_children(ast);
|
||||
for (i = 0; i < children; i++) {
|
||||
zend_ast_destroy_ex(ast->child[i], free);
|
||||
}
|
||||
}
|
||||
|
@ -405,3 +398,18 @@ ZEND_API void zend_ast_destroy(zend_ast *ast) {
|
|||
ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
|
||||
zend_ast_destroy_ex(ast, 1);
|
||||
}
|
||||
|
||||
ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC) {
|
||||
if (zend_ast_is_list(ast)) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
fn(&list->child[i] TSRMLS_CC);
|
||||
}
|
||||
} else {
|
||||
zend_uint i, children = zend_ast_get_num_children(ast);
|
||||
for (i = 0; i < children; ++i) {
|
||||
fn(&ast->child[i] TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
181
Zend/zend_ast.h
181
Zend/zend_ast.h
|
@ -25,31 +25,49 @@
|
|||
|
||||
#include "zend.h"
|
||||
|
||||
|
||||
#define ZEND_AST_IS_LIST_SHIFT 11
|
||||
#define ZEND_AST_NUM_CHILDREN_SHIFT 12
|
||||
|
||||
enum _zend_ast_kind {
|
||||
/* first 256 kinds are reserved for opcodes */
|
||||
ZEND_AST_ZVAL = 256,
|
||||
ZEND_AST_ZNODE,
|
||||
|
||||
ZEND_AST_VAR,
|
||||
ZEND_AST_DIM,
|
||||
ZEND_AST_PROP,
|
||||
ZEND_AST_STATIC_PROP,
|
||||
/* declaration nodes */
|
||||
ZEND_AST_FUNC_DECL,
|
||||
ZEND_AST_CLOSURE,
|
||||
ZEND_AST_METHOD,
|
||||
ZEND_AST_CLASS,
|
||||
|
||||
ZEND_AST_CALL,
|
||||
ZEND_AST_METHOD_CALL,
|
||||
ZEND_AST_STATIC_CALL,
|
||||
ZEND_AST_ARG_LIST,
|
||||
ZEND_AST_UNPACK,
|
||||
|
||||
ZEND_AST_CONST,
|
||||
ZEND_AST_CLASS_CONST,
|
||||
ZEND_AST_RESOLVE_CLASS_NAME,
|
||||
|
||||
ZEND_AST_ASSIGN,
|
||||
ZEND_AST_ASSIGN_REF,
|
||||
ZEND_AST_ASSIGN_OP,
|
||||
/* list nodes */
|
||||
ZEND_AST_ARG_LIST = 1 << ZEND_AST_IS_LIST_SHIFT,
|
||||
ZEND_AST_LIST,
|
||||
ZEND_AST_ARRAY,
|
||||
ZEND_AST_ENCAPS_LIST,
|
||||
ZEND_AST_EXPR_LIST,
|
||||
ZEND_AST_STMT_LIST,
|
||||
ZEND_AST_IF,
|
||||
ZEND_AST_SWITCH_LIST,
|
||||
ZEND_AST_CATCH_LIST,
|
||||
ZEND_AST_PARAM_LIST,
|
||||
ZEND_AST_CLOSURE_USES,
|
||||
ZEND_AST_PROP_DECL,
|
||||
ZEND_AST_CONST_DECL,
|
||||
ZEND_AST_CLASS_CONST_DECL,
|
||||
ZEND_AST_NAME_LIST,
|
||||
ZEND_AST_TRAIT_ADAPTATIONS,
|
||||
ZEND_AST_USE,
|
||||
|
||||
/* 0 child nodes */
|
||||
ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
ZEND_AST_TYPE,
|
||||
|
||||
/* 1 child node */
|
||||
ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
ZEND_AST_CONST,
|
||||
ZEND_AST_RESOLVE_CLASS_NAME,
|
||||
ZEND_AST_UNPACK,
|
||||
ZEND_AST_UNARY_PLUS,
|
||||
ZEND_AST_UNARY_MINUS,
|
||||
ZEND_AST_CAST,
|
||||
|
@ -57,75 +75,75 @@ enum _zend_ast_kind {
|
|||
ZEND_AST_ISSET,
|
||||
ZEND_AST_SILENCE,
|
||||
ZEND_AST_SHELL_EXEC,
|
||||
ZEND_AST_CLONE,
|
||||
ZEND_AST_EXIT,
|
||||
ZEND_AST_PRINT,
|
||||
ZEND_AST_INCLUDE_OR_EVAL,
|
||||
ZEND_AST_UNARY_OP,
|
||||
ZEND_AST_PRE_INC,
|
||||
ZEND_AST_PRE_DEC,
|
||||
ZEND_AST_POST_INC,
|
||||
ZEND_AST_POST_DEC,
|
||||
|
||||
ZEND_AST_GLOBAL,
|
||||
ZEND_AST_UNSET,
|
||||
ZEND_AST_RETURN,
|
||||
ZEND_AST_LABEL,
|
||||
ZEND_AST_REF,
|
||||
ZEND_AST_HALT_COMPILER,
|
||||
ZEND_AST_ECHO,
|
||||
ZEND_AST_THROW,
|
||||
ZEND_AST_GOTO,
|
||||
ZEND_AST_BREAK,
|
||||
ZEND_AST_CONTINUE,
|
||||
|
||||
/* 2 child nodes */
|
||||
ZEND_AST_DIM = 2 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
ZEND_AST_PROP,
|
||||
ZEND_AST_STATIC_PROP,
|
||||
ZEND_AST_CALL,
|
||||
ZEND_AST_CLASS_CONST,
|
||||
ZEND_AST_ASSIGN,
|
||||
ZEND_AST_ASSIGN_REF,
|
||||
ZEND_AST_ASSIGN_OP,
|
||||
ZEND_AST_BINARY_OP,
|
||||
ZEND_AST_GREATER,
|
||||
ZEND_AST_GREATER_EQUAL,
|
||||
ZEND_AST_AND,
|
||||
ZEND_AST_OR,
|
||||
|
||||
ZEND_AST_CONDITIONAL,
|
||||
|
||||
ZEND_AST_ARRAY,
|
||||
ZEND_AST_ARRAY_ELEM,
|
||||
ZEND_AST_ENCAPS_LIST,
|
||||
ZEND_AST_MAGIC_CONST,
|
||||
ZEND_AST_NEW,
|
||||
ZEND_AST_INSTANCEOF,
|
||||
ZEND_AST_YIELD,
|
||||
|
||||
ZEND_AST_EXPR_LIST,
|
||||
ZEND_AST_STMT_LIST,
|
||||
|
||||
ZEND_AST_GLOBAL,
|
||||
ZEND_AST_STATIC,
|
||||
ZEND_AST_UNSET,
|
||||
ZEND_AST_RETURN,
|
||||
ZEND_AST_LABEL,
|
||||
|
||||
ZEND_AST_WHILE,
|
||||
ZEND_AST_DO_WHILE,
|
||||
ZEND_AST_FOR,
|
||||
ZEND_AST_FOREACH,
|
||||
ZEND_AST_REF,
|
||||
ZEND_AST_IF,
|
||||
ZEND_AST_IF_ELEM,
|
||||
|
||||
ZEND_AST_SWITCH,
|
||||
ZEND_AST_SWITCH_LIST,
|
||||
ZEND_AST_SWITCH_CASE,
|
||||
ZEND_AST_DECLARE,
|
||||
ZEND_AST_PROP_ELEM,
|
||||
ZEND_AST_CONST_ELEM,
|
||||
ZEND_AST_USE_TRAIT,
|
||||
ZEND_AST_TRAIT_PRECEDENCE,
|
||||
ZEND_AST_METHOD_REFERENCE,
|
||||
ZEND_AST_NAMESPACE,
|
||||
ZEND_AST_USE_ELEM,
|
||||
ZEND_AST_TRAIT_ALIAS,
|
||||
|
||||
/* 3 child nodes */
|
||||
ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
ZEND_AST_STATIC_CALL,
|
||||
ZEND_AST_CONDITIONAL,
|
||||
|
||||
ZEND_AST_TRY,
|
||||
ZEND_AST_CATCH_LIST,
|
||||
ZEND_AST_CATCH,
|
||||
ZEND_AST_DECLARE,
|
||||
|
||||
ZEND_AST_PARAM_LIST,
|
||||
ZEND_AST_PARAM,
|
||||
ZEND_AST_TYPE,
|
||||
|
||||
ZEND_AST_FUNC_DECL,
|
||||
ZEND_AST_CLOSURE,
|
||||
ZEND_AST_CLOSURE_USES,
|
||||
ZEND_AST_METHOD,
|
||||
|
||||
ZEND_AST_PROP_DECL,
|
||||
ZEND_AST_PROP_ELEM,
|
||||
|
||||
ZEND_AST_CONST_DECL,
|
||||
ZEND_AST_CLASS_CONST_DECL,
|
||||
ZEND_AST_CONST_ELEM,
|
||||
|
||||
ZEND_AST_USE_TRAIT,
|
||||
ZEND_AST_NAME_LIST,
|
||||
ZEND_AST_TRAIT_ADAPTATIONS,
|
||||
ZEND_AST_TRAIT_PRECEDENCE,
|
||||
ZEND_AST_TRAIT_ALIAS,
|
||||
ZEND_AST_METHOD_REFERENCE,
|
||||
|
||||
ZEND_AST_CLASS,
|
||||
|
||||
ZEND_AST_USE,
|
||||
ZEND_AST_USE_ELEM,
|
||||
ZEND_AST_NAMESPACE,
|
||||
ZEND_AST_HALT_COMPILER,
|
||||
/* 4 child nodes */
|
||||
ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
ZEND_AST_FOREACH,
|
||||
};
|
||||
|
||||
typedef unsigned short zend_ast_kind;
|
||||
|
@ -135,10 +153,18 @@ struct _zend_ast {
|
|||
zend_ast_kind kind; /* Type of the node (either opcode or ZEND_AST_* constant) */
|
||||
zend_ast_attr attr; /* Additional attribute, use depending on node type */
|
||||
zend_uint lineno; /* Line number */
|
||||
zend_uint children; /* Number of children */
|
||||
zend_ast *child[1]; /* Array of children (using struct hack) */
|
||||
};
|
||||
|
||||
/* Same as zend_ast, but with children count, which is updated dynamically */
|
||||
typedef struct _zend_ast_list {
|
||||
zend_ast_kind kind;
|
||||
zend_ast_attr attr;
|
||||
zend_uint lineno;
|
||||
zend_uint children;
|
||||
zend_ast *child[1];
|
||||
} zend_ast_list;
|
||||
|
||||
typedef struct _zend_ast_zval {
|
||||
zend_ast_kind kind;
|
||||
zend_ast_attr attr;
|
||||
|
@ -173,9 +199,6 @@ ZEND_API zend_ast *zend_ast_create_decl(
|
|||
|
||||
ZEND_API zend_ast *zend_ast_create_dynamic(zend_ast_kind kind);
|
||||
ZEND_API zend_ast *zend_ast_dynamic_add(zend_ast *ast, zend_ast *op);
|
||||
ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast);
|
||||
|
||||
ZEND_API int zend_ast_is_ct_constant(zend_ast *ast);
|
||||
|
||||
ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC);
|
||||
|
||||
|
@ -183,6 +206,22 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);
|
|||
ZEND_API void zend_ast_destroy(zend_ast *ast);
|
||||
ZEND_API void zend_ast_destroy_and_free(zend_ast *ast);
|
||||
|
||||
typedef void (*zend_ast_apply_func)(zend_ast **ast_ptr TSRMLS_DC);
|
||||
ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC);
|
||||
|
||||
static inline zend_bool zend_ast_is_list(zend_ast *ast) {
|
||||
return (ast->kind >> ZEND_AST_IS_LIST_SHIFT) & 1;
|
||||
}
|
||||
static inline zend_ast_list *zend_ast_get_list(zend_ast *ast) {
|
||||
ZEND_ASSERT(zend_ast_is_list(ast));
|
||||
return (zend_ast_list *) ast;
|
||||
}
|
||||
|
||||
/* Only for non-lists! */
|
||||
static inline zend_uint zend_ast_get_num_children(zend_ast *ast) {
|
||||
return ast->kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
|
||||
}
|
||||
|
||||
static inline zval *zend_ast_get_zval(zend_ast *ast) {
|
||||
return &((zend_ast_zval *) ast)->val;
|
||||
}
|
||||
|
|
|
@ -3823,15 +3823,16 @@ static zend_uchar get_list_fetch_opcode(zend_uchar op_type) {
|
|||
}
|
||||
}
|
||||
|
||||
static void zend_compile_list_assign(znode *result, zend_ast *list_ast, znode *expr_node TSRMLS_DC) {
|
||||
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
|
||||
if (list_ast->children == 1 && !list_ast->child[0]) {
|
||||
if (list->children == 1 && !list->child[0]) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
|
||||
}
|
||||
|
||||
for (i = 0; i < list_ast->children; ++i) {
|
||||
zend_ast *var_ast = list_ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *var_ast = list->child[i];
|
||||
znode fetch_result, dim_node, var_node, assign_result;
|
||||
zend_op *opline;
|
||||
|
||||
|
@ -3985,7 +3986,7 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
if (zend_is_call(source_ast)) {
|
||||
opline->extended_value = ZEND_RETURNS_FUNCTION;
|
||||
} else if (source_ast->kind == ZEND_NEW) {
|
||||
} else if (source_ast->kind == ZEND_AST_NEW) {
|
||||
opline->extended_value = ZEND_RETURNS_NEW;
|
||||
}
|
||||
}
|
||||
|
@ -4031,8 +4032,9 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
}
|
||||
|
||||
zend_uint zend_compile_args(zend_ast *args, zend_function *fbc TSRMLS_DC) {
|
||||
zend_uint zend_compile_args(zend_ast *ast, zend_function *fbc TSRMLS_DC) {
|
||||
// TODO.AST &var error
|
||||
zend_ast_list *args = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
zend_bool uses_arg_unpack = 0;
|
||||
zend_uint arg_count = 0; /* number of arguments not including unpacks */
|
||||
|
@ -4183,7 +4185,7 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
|
|||
zend_compile_call_common(result, args_ast, NULL TSRMLS_CC);
|
||||
}
|
||||
|
||||
static zend_bool zend_args_contain_unpack(zend_ast *args) {
|
||||
static zend_bool zend_args_contain_unpack(zend_ast_list *args) {
|
||||
zend_uint i;
|
||||
for (i = 0; i < args->children; ++i) {
|
||||
if (args->child[i]->kind == ZEND_AST_UNPACK) {
|
||||
|
@ -4193,43 +4195,43 @@ static zend_bool zend_args_contain_unpack(zend_ast *args) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int zend_compile_func_strlen(znode *result, zend_ast *args_ast TSRMLS_DC) {
|
||||
int zend_compile_func_strlen(znode *result, zend_ast_list *args TSRMLS_DC) {
|
||||
znode arg_node;
|
||||
|
||||
if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN)
|
||||
|| args_ast->children != 1 || args_ast->child[0]->kind == ZEND_AST_UNPACK
|
||||
|| args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK
|
||||
) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
zend_compile_expr(&arg_node, args_ast->child[0] TSRMLS_CC);
|
||||
zend_compile_expr(&arg_node, args->child[0] TSRMLS_CC);
|
||||
emit_op(result, ZEND_STRLEN, &arg_node, NULL TSRMLS_CC);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int zend_compile_func_typecheck(znode *result, zend_ast *args_ast, zend_uint type TSRMLS_DC) {
|
||||
int zend_compile_func_typecheck(znode *result, zend_ast_list *args, zend_uint type TSRMLS_DC) {
|
||||
znode arg_node;
|
||||
zend_op *opline;
|
||||
|
||||
if (args_ast->children != 1 || args_ast->child[0]->kind == ZEND_AST_UNPACK) {
|
||||
if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
zend_compile_expr(&arg_node, args_ast->child[0] TSRMLS_CC);
|
||||
zend_compile_expr(&arg_node, args->child[0] TSRMLS_CC);
|
||||
opline = emit_op(result, ZEND_TYPE_CHECK, &arg_node, NULL TSRMLS_CC);
|
||||
opline->extended_value = type;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int zend_compile_func_defined(znode *result, zend_ast *args_ast TSRMLS_DC) {
|
||||
int zend_compile_func_defined(znode *result, zend_ast_list *args TSRMLS_DC) {
|
||||
zend_string *name;
|
||||
zend_op *opline;
|
||||
|
||||
if (args_ast->children != 1 || args_ast->child[0]->kind != ZEND_AST_ZVAL) {
|
||||
if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
name = zval_get_string(zend_ast_get_zval(args_ast->child[0]));
|
||||
name = zval_get_string(zend_ast_get_zval(args->child[0]));
|
||||
if (zend_memrchr(name->val, '\\', name->len) || zend_memrchr(name->val, ':', name->len)) {
|
||||
STR_RELEASE(name);
|
||||
return FAILURE;
|
||||
|
@ -4301,15 +4303,15 @@ static void zend_compile_init_user_func(
|
|||
}
|
||||
|
||||
/* cufa = call_user_func_array */
|
||||
int zend_compile_func_cufa(znode *result, zend_ast *args_ast, zend_string *lcname TSRMLS_DC) {
|
||||
int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname TSRMLS_DC) {
|
||||
znode arg_node;
|
||||
|
||||
if (args_ast->children != 2 || zend_args_contain_unpack(args_ast)) {
|
||||
if (args->children != 2 || zend_args_contain_unpack(args)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
zend_compile_init_user_func(NULL, args_ast->child[0], 1, lcname TSRMLS_CC);
|
||||
zend_compile_expr(&arg_node, args_ast->child[1] TSRMLS_CC);
|
||||
zend_compile_init_user_func(NULL, args->child[0], 1, lcname TSRMLS_CC);
|
||||
zend_compile_expr(&arg_node, args->child[1] TSRMLS_CC);
|
||||
emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL TSRMLS_CC);
|
||||
emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC);
|
||||
|
||||
|
@ -4317,16 +4319,16 @@ int zend_compile_func_cufa(znode *result, zend_ast *args_ast, zend_string *lcnam
|
|||
}
|
||||
|
||||
/* cuf = call_user_func */
|
||||
int zend_compile_func_cuf(znode *result, zend_ast *args_ast, zend_string *lcname TSRMLS_DC) {
|
||||
int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname TSRMLS_DC) {
|
||||
zend_uint i;
|
||||
|
||||
if (args_ast->children < 1 || zend_args_contain_unpack(args_ast)) {
|
||||
if (args->children < 1 || zend_args_contain_unpack(args)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
zend_compile_init_user_func(NULL, args_ast->child[0], args_ast->children - 1, lcname TSRMLS_CC);
|
||||
for (i = 1; i < args_ast->children; ++i) {
|
||||
zend_ast *arg_ast = args_ast->child[i];
|
||||
zend_compile_init_user_func(NULL, args->child[0], args->children - 1, lcname TSRMLS_CC);
|
||||
for (i = 1; i < args->children; ++i) {
|
||||
zend_ast *arg_ast = args->child[i];
|
||||
znode arg_node;
|
||||
zend_op *opline;
|
||||
zend_bool send_user = 0;
|
||||
|
@ -4355,32 +4357,32 @@ int zend_compile_func_cuf(znode *result, zend_ast *args_ast, zend_string *lcname
|
|||
}
|
||||
|
||||
int zend_try_compile_special_func(
|
||||
znode *result, zend_string *lcname, zend_ast *args_ast TSRMLS_DC
|
||||
znode *result, zend_string *lcname, zend_ast_list *args TSRMLS_DC
|
||||
) {
|
||||
if (zend_str_equals(lcname, "strlen")) {
|
||||
return zend_compile_func_strlen(result, args_ast TSRMLS_CC);
|
||||
return zend_compile_func_strlen(result, args TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_null")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, IS_NULL TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, IS_NULL TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_bool")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, _IS_BOOL TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, _IS_BOOL TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_long")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, IS_LONG TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, IS_LONG TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_float")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, IS_DOUBLE TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, IS_DOUBLE TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_string")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, IS_STRING TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, IS_STRING TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_array")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, IS_ARRAY TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, IS_ARRAY TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_object")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, IS_OBJECT TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, IS_OBJECT TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "is_resource")) {
|
||||
return zend_compile_func_typecheck(result, args_ast, IS_RESOURCE TSRMLS_CC);
|
||||
return zend_compile_func_typecheck(result, args, IS_RESOURCE TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "defined")) {
|
||||
return zend_compile_func_defined(result, args_ast TSRMLS_CC);
|
||||
return zend_compile_func_defined(result, args TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "call_user_func_array")) {
|
||||
return zend_compile_func_cufa(result, args_ast, lcname TSRMLS_CC);
|
||||
return zend_compile_func_cufa(result, args, lcname TSRMLS_CC);
|
||||
} else if (zend_str_equals(lcname, "call_user_func")) {
|
||||
return zend_compile_func_cuf(result, args_ast, lcname TSRMLS_CC);
|
||||
return zend_compile_func_cuf(result, args, lcname TSRMLS_CC);
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
|
@ -4423,7 +4425,9 @@ void zend_compile_call(znode *result, zend_ast *ast, int type TSRMLS_DC) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (zend_try_compile_special_func(result, lcname, args_ast TSRMLS_CC) == SUCCESS) {
|
||||
if (zend_try_compile_special_func(result, lcname,
|
||||
zend_ast_get_list(args_ast) TSRMLS_CC) == SUCCESS
|
||||
) {
|
||||
STR_RELEASE(lcname);
|
||||
zval_ptr_dtor(&name_node.u.constant);
|
||||
return;
|
||||
|
@ -4731,31 +4735,31 @@ void zend_compile_throw(zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
void zend_compile_break_continue(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast *depth_ast = ast->child[0];
|
||||
zend_uint opcode = ast->kind;
|
||||
|
||||
znode depth_node;
|
||||
zend_op *opline;
|
||||
|
||||
ZEND_ASSERT(opcode == ZEND_BRK || opcode == ZEND_CONT);
|
||||
ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
|
||||
|
||||
if (depth_ast) {
|
||||
if (depth_ast->kind != ZEND_AST_ZVAL) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
|
||||
"is no longer supported", opcode == ZEND_BRK ? "break" : "continue");
|
||||
"is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
|
||||
}
|
||||
|
||||
zend_compile_expr(&depth_node, depth_ast TSRMLS_CC);
|
||||
|
||||
if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
|
||||
opcode == ZEND_BRK ? "break" : "continue");
|
||||
ast->kind == ZEND_AST_BREAK ? "break" : "continue");
|
||||
}
|
||||
} else {
|
||||
depth_node.op_type = IS_CONST;
|
||||
ZVAL_LONG(&depth_node.u.constant, 1);
|
||||
}
|
||||
|
||||
opline = emit_op(NULL, opcode, NULL, &depth_node TSRMLS_CC);
|
||||
opline = emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT,
|
||||
NULL, &depth_node TSRMLS_CC);
|
||||
opline->op1.opline_num = CG(context).current_brk_cont;
|
||||
}
|
||||
|
||||
|
@ -4832,6 +4836,7 @@ void zend_compile_do_while(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_expr_list(znode *result, zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list;
|
||||
zend_uint i;
|
||||
|
||||
result->op_type = IS_CONST;
|
||||
|
@ -4840,8 +4845,10 @@ void zend_compile_expr_list(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
if (!ast) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *expr_ast = ast->child[i];
|
||||
|
||||
list = zend_ast_get_list(ast);
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *expr_ast = list->child[i];
|
||||
|
||||
zend_do_free(result TSRMLS_CC);
|
||||
zend_compile_expr(result, expr_ast TSRMLS_CC);
|
||||
|
@ -4988,12 +4995,13 @@ void zend_compile_foreach(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_if(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), ast->children - 1, 0);
|
||||
zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), list->children - 1, 0);
|
||||
zend_uint opnum_last_jmpz = 0;
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *elem_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *elem_ast = list->child[i];
|
||||
zend_ast *cond_ast = elem_ast->child[0];
|
||||
zend_ast *stmt_ast = elem_ast->child[1];
|
||||
|
||||
|
@ -5005,7 +5013,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
zend_compile_stmt(stmt_ast TSRMLS_CC);
|
||||
|
||||
if (i != ast->children - 1) {
|
||||
if (i != list->children - 1) {
|
||||
jmp_opnums[i] = zend_emit_jump(0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
@ -5014,7 +5022,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ast->children - 1; ++i) {
|
||||
for (i = 0; i < list->children - 1; ++i) {
|
||||
zend_update_jump_target_to_next(jmp_opnums[i] TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
@ -5023,7 +5031,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
void zend_compile_switch(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast *expr_ast = ast->child[0];
|
||||
zend_ast *cases_ast = ast->child[1];
|
||||
zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
|
||||
|
||||
zend_uint i;
|
||||
zend_bool has_default_case = 0;
|
||||
|
@ -5031,7 +5039,7 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
znode expr_node, case_node;
|
||||
zend_op *opline;
|
||||
zend_uint *jmpnz_opnums = safe_emalloc(sizeof(zend_uint), cases_ast->children, 0);
|
||||
zend_uint *jmpnz_opnums = safe_emalloc(sizeof(zend_uint), cases->children, 0);
|
||||
zend_uint opnum_default_jmp;
|
||||
|
||||
zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
|
||||
|
@ -5046,8 +5054,8 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) {
|
|||
case_node.op_type = IS_TMP_VAR;
|
||||
case_node.u.op.var = get_temporary_variable(CG(active_op_array));
|
||||
|
||||
for (i = 0; i < cases_ast->children; ++i) {
|
||||
zend_ast *case_ast = cases_ast->child[i];
|
||||
for (i = 0; i < cases->children; ++i) {
|
||||
zend_ast *case_ast = cases->child[i];
|
||||
zend_ast *cond_ast = case_ast->child[0];
|
||||
znode cond_node;
|
||||
|
||||
|
@ -5069,8 +5077,8 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
opnum_default_jmp = zend_emit_jump(0 TSRMLS_CC);
|
||||
|
||||
for (i = 0; i < cases_ast->children; ++i) {
|
||||
zend_ast *case_ast = cases_ast->child[i];
|
||||
for (i = 0; i < cases->children; ++i) {
|
||||
zend_ast *case_ast = cases->child[i];
|
||||
zend_ast *cond_ast = case_ast->child[0];
|
||||
zend_ast *stmt_ast = case_ast->child[1];
|
||||
|
||||
|
@ -5102,32 +5110,32 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
void zend_compile_try(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast *try_ast = ast->child[0];
|
||||
zend_ast *catches_ast = ast->child[1];
|
||||
zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
|
||||
zend_ast *finally_ast = ast->child[2];
|
||||
|
||||
zend_uint i;
|
||||
zend_op *opline;
|
||||
zend_uint try_catch_offset = zend_add_try_element(
|
||||
get_next_op_number(CG(active_op_array)) TSRMLS_CC);
|
||||
zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), catches_ast->children, 0);
|
||||
zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), catches->children, 0);
|
||||
|
||||
if (catches_ast->children == 0 && !finally_ast) {
|
||||
if (catches->children == 0 && !finally_ast) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
|
||||
}
|
||||
|
||||
zend_compile_stmt(try_ast TSRMLS_CC);
|
||||
|
||||
if (catches_ast->children != 0) {
|
||||
if (catches->children != 0) {
|
||||
jmp_opnums[0] = zend_emit_jump(0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
for (i = 0; i < catches_ast->children; ++i) {
|
||||
zend_ast *catch_ast = catches_ast->child[i];
|
||||
for (i = 0; i < catches->children; ++i) {
|
||||
zend_ast *catch_ast = catches->child[i];
|
||||
zend_ast *class_ast = catch_ast->child[0];
|
||||
zend_ast *var_ast = catch_ast->child[1];
|
||||
zend_ast *stmt_ast = catch_ast->child[2];
|
||||
zval *var_name = zend_ast_get_zval(var_ast);
|
||||
zend_bool is_last_catch = (i + 1 == catches_ast->children);
|
||||
zend_bool is_last_catch = (i + 1 == catches->children);
|
||||
|
||||
zend_uint opnum_catch;
|
||||
|
||||
|
@ -5162,7 +5170,7 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) {
|
|||
opline->extended_value = get_next_op_number(CG(active_op_array));
|
||||
}
|
||||
|
||||
for (i = 0; i < catches_ast->children; ++i) {
|
||||
for (i = 0; i < catches->children; ++i) {
|
||||
zend_update_jump_target_to_next(jmp_opnums[i] TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
@ -5192,13 +5200,13 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_declare(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast *declares_ast = ast->child[0];
|
||||
zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
|
||||
zend_ast *stmt_ast = ast->child[1];
|
||||
zend_declarables orig_declarables = CG(declarables);
|
||||
zend_uint i;
|
||||
|
||||
for (i = 0; i < declares_ast->children; ++i) {
|
||||
zend_ast *declare_ast = declares_ast->child[i];
|
||||
for (i = 0; i < declares->children; ++i) {
|
||||
zend_ast *declare_ast = declares->child[i];
|
||||
zend_ast *name_ast = declare_ast->child[0];
|
||||
zend_ast *value_ast = declare_ast->child[1];
|
||||
|
||||
|
@ -5276,24 +5284,26 @@ void zend_compile_declare(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_stmt_list(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_compile_stmt(ast->child[i] TSRMLS_CC);
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_compile_stmt(list->child[i] TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
void zend_compile_params(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
zend_op_array *op_array = CG(active_op_array);
|
||||
zend_arg_info *arg_infos;
|
||||
|
||||
if (ast->children == 0) {
|
||||
if (list->children == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
arg_infos = safe_emalloc(sizeof(zend_arg_info), ast->children, 0);
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *param_ast = ast->child[i];
|
||||
arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *param_ast = list->child[i];
|
||||
zend_ast *type_ast = param_ast->child[0];
|
||||
zend_ast *var_ast = param_ast->child[1];
|
||||
zend_ast *default_ast = param_ast->child[2];
|
||||
|
@ -5412,19 +5422,16 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
/* These are assigned at the end to avoid unitialized memory in case of an error */
|
||||
op_array->num_args = ast->children;
|
||||
op_array->num_args = list->children;
|
||||
op_array->arg_info = arg_infos;
|
||||
}
|
||||
|
||||
void zend_compile_closure_uses(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
|
||||
if (!ast) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *var_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *var_ast = list->child[i];
|
||||
zend_string *name = Z_STR_P(zend_ast_get_zval(var_ast));
|
||||
zend_bool by_ref = var_ast->attr;
|
||||
zval zv;
|
||||
|
@ -5657,7 +5664,9 @@ static void zend_begin_func_decl(
|
|||
}
|
||||
}
|
||||
|
||||
if (zend_str_equals(lcname, ZEND_AUTOLOAD_FUNC_NAME) && params_ast->children != 1) {
|
||||
if (zend_str_equals(lcname, ZEND_AUTOLOAD_FUNC_NAME)
|
||||
&& zend_ast_get_list(params_ast)->children != 1
|
||||
) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument",
|
||||
ZEND_AUTOLOAD_FUNC_NAME);
|
||||
}
|
||||
|
@ -5745,7 +5754,9 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
zend_compile_params(params_ast TSRMLS_CC);
|
||||
if (uses_ast) {
|
||||
zend_compile_closure_uses(uses_ast TSRMLS_CC);
|
||||
}
|
||||
zend_compile_stmt(stmt_ast TSRMLS_CC);
|
||||
|
||||
if (is_method) {
|
||||
|
@ -5767,7 +5778,8 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) {
|
||||
zend_uint flags = ast->attr;
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint flags = list->attr;
|
||||
zend_class_entry *ce = CG(active_class_entry);
|
||||
zend_uint i;
|
||||
|
||||
|
@ -5779,8 +5791,8 @@ void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) {
|
|||
zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
|
||||
}
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *prop_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *prop_ast = list->child[i];
|
||||
zend_ast *name_ast = prop_ast->child[0];
|
||||
zend_ast *value_ast = prop_ast->child[1];
|
||||
zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast));
|
||||
|
@ -5809,11 +5821,12 @@ void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_class_const_decl(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_class_entry *ce = CG(active_class_entry);
|
||||
zend_uint i;
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *const_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *const_ast = list->child[i];
|
||||
zend_ast *name_ast = const_ast->child[0];
|
||||
zend_ast *value_ast = const_ast->child[1];
|
||||
zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast));
|
||||
|
@ -5862,15 +5875,16 @@ static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast TSRMLS
|
|||
}
|
||||
|
||||
static zend_string **zend_compile_name_list(zend_ast *ast TSRMLS_DC) {
|
||||
zend_string **names = safe_emalloc(sizeof(zend_string *), ast->children + 1, 0);
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_string **names = safe_emalloc(sizeof(zend_string *), list->children + 1, 0);
|
||||
zend_uint i;
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *name_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *name_ast = list->child[i];
|
||||
names[i] = zend_resolve_class_name_ast(name_ast TSRMLS_CC);
|
||||
}
|
||||
|
||||
names[ast->children] = NULL;
|
||||
names[list->children] = NULL;
|
||||
|
||||
return names;
|
||||
}
|
||||
|
@ -5916,14 +5930,14 @@ static void zend_compile_trait_alias(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast *traits_ast = ast->child[0];
|
||||
zend_ast *adaptations_ast = ast->child[1];
|
||||
zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
|
||||
zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
|
||||
zend_class_entry *ce = CG(active_class_entry);
|
||||
zend_op *opline;
|
||||
zend_uint i;
|
||||
|
||||
for (i = 0; i < traits_ast->children; ++i) {
|
||||
zend_ast *trait_ast = traits_ast->child[i];
|
||||
for (i = 0; i < traits->children; ++i) {
|
||||
zend_ast *trait_ast = traits->child[i];
|
||||
zend_string *name = Z_STR_P(zend_ast_get_zval(trait_ast));
|
||||
|
||||
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
||||
|
@ -5951,12 +5965,12 @@ void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) {
|
|||
ce->num_traits++;
|
||||
}
|
||||
|
||||
if (!adaptations_ast) {
|
||||
if (!adaptations) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < adaptations_ast->children; ++i) {
|
||||
zend_ast *adaptation_ast = adaptations_ast->child[i];
|
||||
for (i = 0; i < adaptations->children; ++i) {
|
||||
zend_ast *adaptation_ast = adaptations->child[i];
|
||||
switch (adaptation_ast->kind) {
|
||||
case ZEND_AST_TRAIT_PRECEDENCE:
|
||||
zend_compile_trait_precedence(adaptation_ast TSRMLS_CC);
|
||||
|
@ -5970,9 +5984,10 @@ void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_implements(znode *class_node, zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *class_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *class_ast = list->child[i];
|
||||
zend_string *name = Z_STR_P(zend_ast_get_zval(class_ast));
|
||||
|
||||
zend_op *opline;
|
||||
|
@ -6221,6 +6236,7 @@ static void zend_check_already_in_use(
|
|||
}
|
||||
|
||||
void zend_compile_use(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
zend_string *current_ns = Z_TYPE(CG(current_namespace)) != IS_UNDEF
|
||||
? Z_STR(CG(current_namespace)) : NULL;
|
||||
|
@ -6228,8 +6244,8 @@ void zend_compile_use(zend_ast *ast TSRMLS_DC) {
|
|||
HashTable *current_import = zend_get_import_ht(type TSRMLS_CC);
|
||||
zend_bool case_sensitive = type == T_CONST;
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *use_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *use_ast = list->child[i];
|
||||
zend_ast *old_name_ast = use_ast->child[0];
|
||||
zend_ast *new_name_ast = use_ast->child[1];
|
||||
zend_string *old_name = Z_STR_P(zend_ast_get_zval(old_name_ast));
|
||||
|
@ -6328,9 +6344,10 @@ void zend_compile_use(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_const_decl(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *const_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *const_ast = list->child[i];
|
||||
zend_ast *name_ast = const_ast->child[0];
|
||||
zend_ast *value_ast = const_ast->child[1];
|
||||
zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast));
|
||||
|
@ -6518,11 +6535,12 @@ void zend_compile_greater(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
void zend_compile_unary_op(znode *result, zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast *expr_ast = ast->child[0];
|
||||
zend_uint opcode = ast->attr;
|
||||
|
||||
znode expr_node;
|
||||
zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
|
||||
|
||||
emit_op_tmp(result, ast->kind, &expr_node, NULL TSRMLS_CC);
|
||||
emit_op_tmp(result, opcode, &expr_node, NULL TSRMLS_CC);
|
||||
}
|
||||
|
||||
void zend_compile_unary_pm(znode *result, zend_ast *ast TSRMLS_DC) {
|
||||
|
@ -6578,17 +6596,18 @@ void zend_compile_post_incdec(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
znode var_node;
|
||||
zend_op *opline;
|
||||
|
||||
ZEND_ASSERT(ast->kind == ZEND_POST_INC || ast->kind == ZEND_POST_DEC);
|
||||
ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_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->opcode = ast->kind == ZEND_AST_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);
|
||||
emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
|
||||
&var_node, NULL TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6598,14 +6617,15 @@ void zend_compile_pre_incdec(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
znode var_node;
|
||||
zend_op *opline;
|
||||
|
||||
ZEND_ASSERT(ast->kind == ZEND_PRE_INC || ast->kind == ZEND_PRE_DEC);
|
||||
ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_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;
|
||||
opline->opcode = ast->kind == ZEND_AST_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);
|
||||
emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
|
||||
&var_node, NULL TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6801,7 +6821,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
if (!zend_is_variable(var_ast) || zend_is_call(var_ast)) {
|
||||
if (ast->kind == ZEND_AST_EMPTY) {
|
||||
/* empty(expr) can be transformed to !expr */
|
||||
zend_ast *not_ast = zend_ast_create_unary(ZEND_BOOL_NOT, var_ast);
|
||||
zend_ast *not_ast = zend_ast_create_ex(1, ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
|
||||
zend_compile_expr(result, not_ast TSRMLS_CC);
|
||||
return;
|
||||
} else {
|
||||
|
@ -6874,14 +6894,15 @@ void zend_compile_shell_exec(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_op *opline;
|
||||
zend_uint i, opnum_init;
|
||||
zend_bool packed = 1;
|
||||
|
||||
opnum_init = get_next_op_number(CG(active_op_array));
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *elem_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *elem_ast = list->child[i];
|
||||
zend_ast *value_ast = elem_ast->child[0];
|
||||
zend_ast *key_ast = elem_ast->child[1];
|
||||
zend_bool by_ref = elem_ast->attr;
|
||||
|
@ -6902,7 +6923,7 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
|
||||
if (i == 0) {
|
||||
opline = emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr TSRMLS_CC);
|
||||
opline->extended_value = ast->children << ZEND_ARRAY_SIZE_SHIFT;
|
||||
opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT;
|
||||
} else {
|
||||
opline = emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT, &value_node, key_node_ptr TSRMLS_CC);
|
||||
SET_NODE(opline->result, result);
|
||||
|
@ -6918,7 +6939,7 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
/* Handle empty array */
|
||||
if (!ast->children) {
|
||||
if (!list->children) {
|
||||
emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
@ -7035,15 +7056,16 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
void zend_compile_encaps_list(znode *result, zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
|
||||
ZEND_ASSERT(ast->children > 0);
|
||||
ZEND_ASSERT(list->children > 0);
|
||||
|
||||
result->op_type = IS_TMP_VAR;
|
||||
result->u.op.var = get_temporary_variable(CG(active_op_array));
|
||||
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *elem_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *elem_ast = list->child[i];
|
||||
znode elem_node;
|
||||
zend_op *opline;
|
||||
|
||||
|
@ -7165,7 +7187,7 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) {
|
|||
return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
|
||||
|| kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
|
||||
|| kind == ZEND_AST_AND || kind == ZEND_AST_OR
|
||||
|| kind == ZEND_BW_NOT || kind == ZEND_BOOL_NOT
|
||||
|| kind == ZEND_AST_UNARY_OP
|
||||
|| kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
|
||||
|| kind == ZEND_AST_CONDITIONAL
|
||||
|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
|
||||
|
@ -7301,12 +7323,7 @@ void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) {
|
|||
zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
|
||||
}
|
||||
|
||||
{
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_compile_const_expr(&ast->child[i] TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
zend_ast_apply(ast, zend_compile_const_expr TSRMLS_CC);
|
||||
|
||||
switch (ast->kind) {
|
||||
case ZEND_AST_CLASS_CONST:
|
||||
|
@ -7331,9 +7348,10 @@ void zend_compile_top_stmt(zend_ast *ast TSRMLS_DC) {
|
|||
}
|
||||
|
||||
if (ast->kind == ZEND_AST_STMT_LIST) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_compile_top_stmt(ast->child[i] TSRMLS_CC);
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_compile_top_stmt(list->child[i] TSRMLS_CC);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -7372,17 +7390,17 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) {
|
|||
case ZEND_AST_RETURN:
|
||||
zend_compile_return(ast TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_ECHO:
|
||||
case ZEND_AST_ECHO:
|
||||
zend_compile_echo(ast TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_THROW:
|
||||
case ZEND_AST_THROW:
|
||||
zend_compile_throw(ast TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_BRK:
|
||||
case ZEND_CONT:
|
||||
case ZEND_AST_BREAK:
|
||||
case ZEND_AST_CONTINUE:
|
||||
zend_compile_break_continue(ast TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_GOTO:
|
||||
case ZEND_AST_GOTO:
|
||||
zend_compile_goto(ast TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_AST_LABEL:
|
||||
|
@ -7480,10 +7498,10 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
case ZEND_AST_ASSIGN_REF:
|
||||
zend_compile_assign_ref(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_NEW:
|
||||
case ZEND_AST_NEW:
|
||||
zend_compile_new(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_CLONE:
|
||||
case ZEND_AST_CLONE:
|
||||
zend_compile_clone(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_AST_ASSIGN_OP:
|
||||
|
@ -7496,8 +7514,7 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
case ZEND_AST_GREATER_EQUAL:
|
||||
zend_compile_greater(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_BOOL_NOT:
|
||||
case ZEND_BW_NOT:
|
||||
case ZEND_AST_UNARY_OP:
|
||||
zend_compile_unary_op(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_AST_UNARY_PLUS:
|
||||
|
@ -7508,12 +7525,12 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
case ZEND_AST_OR:
|
||||
zend_compile_short_circuiting(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_POST_INC:
|
||||
case ZEND_POST_DEC:
|
||||
case ZEND_AST_POST_INC:
|
||||
case ZEND_AST_POST_DEC:
|
||||
zend_compile_post_incdec(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_PRE_INC:
|
||||
case ZEND_PRE_DEC:
|
||||
case ZEND_AST_PRE_INC:
|
||||
case ZEND_AST_PRE_DEC:
|
||||
zend_compile_pre_incdec(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_AST_CAST:
|
||||
|
@ -7522,19 +7539,19 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) {
|
|||
case ZEND_AST_CONDITIONAL:
|
||||
zend_compile_conditional(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_PRINT:
|
||||
case ZEND_AST_PRINT:
|
||||
zend_compile_print(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_EXIT:
|
||||
case ZEND_AST_EXIT:
|
||||
zend_compile_exit(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_YIELD:
|
||||
case ZEND_AST_YIELD:
|
||||
zend_compile_yield(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_INSTANCEOF:
|
||||
case ZEND_AST_INSTANCEOF:
|
||||
zend_compile_instanceof(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_INCLUDE_OR_EVAL:
|
||||
case ZEND_AST_INCLUDE_OR_EVAL:
|
||||
zend_compile_include_or_eval(result, ast TSRMLS_CC);
|
||||
return;
|
||||
case ZEND_AST_ISSET:
|
||||
|
@ -7601,7 +7618,7 @@ void zend_compile_var(znode *result, zend_ast *ast, int type TSRMLS_DC) {
|
|||
|| type == BP_VAR_RW || type == BP_VAR_UNSET
|
||||
) {
|
||||
/* For BC reasons =& new Foo is allowed */
|
||||
if (type != BP_VAR_REF || ast->kind != ZEND_NEW) {
|
||||
if (type != BP_VAR_REF || ast->kind != ZEND_AST_NEW) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Cannot use temporary expression in write context");
|
||||
}
|
||||
|
@ -7665,12 +7682,13 @@ void zend_eval_const_greater(zend_ast **ast_ptr TSRMLS_DC) {
|
|||
|
||||
void zend_eval_const_array(zend_ast **ast_ptr TSRMLS_DC) {
|
||||
zend_ast *ast = *ast_ptr;
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
zend_uint i;
|
||||
zval array;
|
||||
|
||||
/* First ensure that *all* child nodes are constant */
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *elem_ast = ast->child[i];
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *elem_ast = list->child[i];
|
||||
zend_ast *value_ast = elem_ast->child[0];
|
||||
zend_ast *key_ast = elem_ast->child[1];
|
||||
zend_bool by_ref = elem_ast->attr;
|
||||
|
@ -7680,9 +7698,9 @@ void zend_eval_const_array(zend_ast **ast_ptr TSRMLS_DC) {
|
|||
}
|
||||
}
|
||||
|
||||
array_init_size(&array, ast->children);
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_ast *elem_ast = ast->child[i];
|
||||
array_init_size(&array, list->children);
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *elem_ast = list->child[i];
|
||||
zend_ast *value_ast = elem_ast->child[0];
|
||||
zend_ast *key_ast = elem_ast->child[1];
|
||||
|
||||
|
@ -7741,12 +7759,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr TSRMLS_DC) {
|
|||
return;
|
||||
}
|
||||
|
||||
{
|
||||
zend_uint i;
|
||||
for (i = 0; i < ast->children; ++i) {
|
||||
zend_eval_const_expr(&ast->child[i] TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
zend_ast_apply(ast, zend_eval_const_expr TSRMLS_CC);
|
||||
|
||||
switch (ast->kind) {
|
||||
case ZEND_AST_BINARY_OP:
|
||||
|
|
|
@ -329,10 +329,10 @@ unticked_statement:
|
|||
{ $$.ast = zend_ast_create(4, ZEND_AST_FOR, $3.ast, $5.ast, $7.ast, $9.ast); }
|
||||
| T_SWITCH parenthesis_expr switch_case_list
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_AST_SWITCH, $2.ast, $3.ast); }
|
||||
| T_BREAK ';' { $$.ast = zend_ast_create_unary(ZEND_BRK, NULL); }
|
||||
| T_BREAK expr ';' { $$.ast = zend_ast_create_unary(ZEND_BRK, $2.ast); }
|
||||
| T_CONTINUE ';' { $$.ast = zend_ast_create_unary(ZEND_CONT, NULL); }
|
||||
| T_CONTINUE expr ';' { $$.ast = zend_ast_create_unary(ZEND_CONT, $2.ast); }
|
||||
| T_BREAK ';' { $$.ast = zend_ast_create_unary(ZEND_AST_BREAK, NULL); }
|
||||
| T_BREAK expr ';' { $$.ast = zend_ast_create_unary(ZEND_AST_BREAK, $2.ast); }
|
||||
| T_CONTINUE ';' { $$.ast = zend_ast_create_unary(ZEND_AST_CONTINUE, NULL); }
|
||||
| T_CONTINUE expr ';' { $$.ast = zend_ast_create_unary(ZEND_AST_CONTINUE, $2.ast); }
|
||||
| T_RETURN ';'
|
||||
{ $$.ast = zend_ast_create_unary(ZEND_AST_RETURN, NULL); }
|
||||
| T_RETURN expr ';'
|
||||
|
@ -340,7 +340,7 @@ unticked_statement:
|
|||
| T_GLOBAL global_var_list ';' { $$.ast = $2.ast; }
|
||||
| T_STATIC static_var_list ';' { $$.ast = $2.ast; }
|
||||
| T_ECHO echo_expr_list ';' { $$.ast = $2.ast; }
|
||||
| T_INLINE_HTML { $$.ast = zend_ast_create_unary(ZEND_ECHO, $1.ast); }
|
||||
| T_INLINE_HTML { $$.ast = zend_ast_create_unary(ZEND_AST_ECHO, $1.ast); }
|
||||
| expr ';' { $$.ast = $1.ast; }
|
||||
| T_UNSET '(' unset_variables ')' ';' { $$.ast = $3.ast; }
|
||||
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
|
||||
|
@ -355,8 +355,8 @@ unticked_statement:
|
|||
| ';' /* empty statement */ { $$.ast = NULL; }
|
||||
| T_TRY '{' inner_statement_list '}' catch_list finally_statement
|
||||
{ $$.ast = zend_ast_create_ternary(ZEND_AST_TRY, $3.ast, $5.ast, $6.ast); }
|
||||
| T_THROW expr ';' { $$.ast = zend_ast_create_unary(ZEND_THROW, $2.ast); }
|
||||
| T_GOTO T_STRING ';' { $$.ast = zend_ast_create_unary(ZEND_GOTO, $2.ast); }
|
||||
| T_THROW expr ';' { $$.ast = zend_ast_create_unary(ZEND_AST_THROW, $2.ast); }
|
||||
| T_GOTO T_STRING ';' { $$.ast = zend_ast_create_unary(ZEND_AST_GOTO, $2.ast); }
|
||||
;
|
||||
|
||||
catch_list:
|
||||
|
@ -733,7 +733,7 @@ echo_expr_list:
|
|||
| echo_expr { $$.ast = zend_ast_create_dynamic_and_add(ZEND_AST_STMT_LIST, $1.ast); }
|
||||
;
|
||||
echo_expr:
|
||||
expr { $$.ast = zend_ast_create_unary(ZEND_ECHO, $1.ast); }
|
||||
expr { $$.ast = zend_ast_create_unary(ZEND_AST_ECHO, $1.ast); }
|
||||
;
|
||||
|
||||
for_expr:
|
||||
|
@ -748,7 +748,7 @@ non_empty_for_expr:
|
|||
|
||||
new_expr:
|
||||
T_NEW class_name_reference ctor_arguments
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_NEW, $2.ast, $3.ast); }
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_AST_NEW, $2.ast, $3.ast); }
|
||||
;
|
||||
|
||||
expr_without_variable:
|
||||
|
@ -761,8 +761,8 @@ expr_without_variable:
|
|||
| variable '=' '&' T_NEW class_name_reference ctor_arguments
|
||||
{ zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");
|
||||
$$.ast = zend_ast_create_binary(ZEND_AST_ASSIGN_REF, $1.ast,
|
||||
zend_ast_create_binary(ZEND_NEW, $5.ast, $6.ast)); }
|
||||
| T_CLONE expr { $$.ast = zend_ast_create_unary(ZEND_CLONE, $2.ast); }
|
||||
zend_ast_create_binary(ZEND_AST_NEW, $5.ast, $6.ast)); }
|
||||
| T_CLONE expr { $$.ast = zend_ast_create_unary(ZEND_AST_CLONE, $2.ast); }
|
||||
| variable T_PLUS_EQUAL expr
|
||||
{ $$.ast = zend_ast_create_assign_op(ZEND_ASSIGN_ADD, $1.ast, $3.ast); }
|
||||
| variable T_MINUS_EQUAL expr
|
||||
|
@ -787,10 +787,10 @@ expr_without_variable:
|
|||
{ $$.ast = zend_ast_create_assign_op(ZEND_ASSIGN_SL, $1.ast, $3.ast); }
|
||||
| variable T_SR_EQUAL expr
|
||||
{ $$.ast = zend_ast_create_assign_op(ZEND_ASSIGN_SR, $1.ast, $3.ast); }
|
||||
| variable T_INC { $$.ast = zend_ast_create_unary(ZEND_POST_INC, $1.ast); }
|
||||
| T_INC variable { $$.ast = zend_ast_create_unary(ZEND_PRE_INC, $2.ast); }
|
||||
| variable T_DEC { $$.ast = zend_ast_create_unary(ZEND_POST_DEC, $1.ast); }
|
||||
| T_DEC variable { $$.ast = zend_ast_create_unary(ZEND_PRE_DEC, $2.ast); }
|
||||
| variable T_INC { $$.ast = zend_ast_create_unary(ZEND_AST_POST_INC, $1.ast); }
|
||||
| T_INC variable { $$.ast = zend_ast_create_unary(ZEND_AST_PRE_INC, $2.ast); }
|
||||
| variable T_DEC { $$.ast = zend_ast_create_unary(ZEND_AST_POST_DEC, $1.ast); }
|
||||
| T_DEC variable { $$.ast = zend_ast_create_unary(ZEND_AST_PRE_DEC, $2.ast); }
|
||||
| expr T_BOOLEAN_OR expr
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_AST_OR, $1.ast, $3.ast); }
|
||||
| expr T_BOOLEAN_AND expr
|
||||
|
@ -815,8 +815,8 @@ expr_without_variable:
|
|||
| expr T_SR expr { $$.ast = zend_ast_create_binary_op(ZEND_SR, $1.ast, $3.ast); }
|
||||
| '+' expr %prec T_INC { $$.ast = zend_ast_create_unary(ZEND_AST_UNARY_PLUS, $2.ast); }
|
||||
| '-' expr %prec T_INC { $$.ast = zend_ast_create_unary(ZEND_AST_UNARY_MINUS, $2.ast); }
|
||||
| '!' expr { $$.ast = zend_ast_create_unary(ZEND_BOOL_NOT, $2.ast); }
|
||||
| '~' expr { $$.ast = zend_ast_create_unary(ZEND_BW_NOT, $2.ast); }
|
||||
| '!' expr { $$.ast = zend_ast_create_ex(1, ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2.ast); }
|
||||
| '~' expr { $$.ast = zend_ast_create_ex(1, ZEND_AST_UNARY_OP, ZEND_BW_NOT, $2.ast); }
|
||||
| expr T_IS_IDENTICAL expr
|
||||
{ $$.ast = zend_ast_create_binary_op(ZEND_IS_IDENTICAL, $1.ast, $3.ast); }
|
||||
| expr T_IS_NOT_IDENTICAL expr
|
||||
|
@ -834,7 +834,7 @@ expr_without_variable:
|
|||
| expr T_IS_GREATER_OR_EQUAL expr
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_AST_GREATER_EQUAL, $1.ast, $3.ast); }
|
||||
| expr T_INSTANCEOF class_name_reference
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_INSTANCEOF, $1.ast, $3.ast); }
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_AST_INSTANCEOF, $1.ast, $3.ast); }
|
||||
| parenthesis_expr { $$.ast = $1.ast; }
|
||||
| new_expr { $$.ast = $1.ast; }
|
||||
| expr '?' expr ':' expr
|
||||
|
@ -857,15 +857,15 @@ expr_without_variable:
|
|||
{ $$.ast = zend_ast_create_cast(_IS_BOOL, $2.ast); }
|
||||
| T_UNSET_CAST expr
|
||||
{ $$.ast = zend_ast_create_cast(IS_NULL, $2.ast); }
|
||||
| T_EXIT exit_expr { $$.ast = zend_ast_create_unary(ZEND_EXIT, $2.ast); }
|
||||
| T_EXIT exit_expr { $$.ast = zend_ast_create_unary(ZEND_AST_EXIT, $2.ast); }
|
||||
| '@' expr { $$.ast = zend_ast_create_unary(ZEND_AST_SILENCE, $2.ast); }
|
||||
| scalar { $$.ast = $1.ast; }
|
||||
| '`' backticks_expr '`' { $$.ast = zend_ast_create_unary(ZEND_AST_SHELL_EXEC, $2.ast); }
|
||||
| T_PRINT expr { $$.ast = zend_ast_create_unary(ZEND_PRINT, $2.ast); }
|
||||
| T_YIELD { $$.ast = zend_ast_create_binary(ZEND_YIELD, NULL, NULL); }
|
||||
| T_YIELD expr { $$.ast = zend_ast_create_binary(ZEND_YIELD, $2.ast, NULL); }
|
||||
| T_PRINT expr { $$.ast = zend_ast_create_unary(ZEND_AST_PRINT, $2.ast); }
|
||||
| T_YIELD { $$.ast = zend_ast_create_binary(ZEND_AST_YIELD, NULL, NULL); }
|
||||
| T_YIELD expr { $$.ast = zend_ast_create_binary(ZEND_AST_YIELD, $2.ast, NULL); }
|
||||
| T_YIELD expr T_DOUBLE_ARROW expr
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_YIELD, $4.ast, $2.ast); }
|
||||
{ $$.ast = zend_ast_create_binary(ZEND_AST_YIELD, $4.ast, $2.ast); }
|
||||
| function returns_ref '(' parameter_list ')' lexical_vars
|
||||
{ $$.str = CG(doc_comment); CG(doc_comment) = NULL; }
|
||||
'{' inner_statement_list '}'
|
||||
|
@ -1151,15 +1151,15 @@ internal_functions_in_yacc:
|
|||
T_ISSET '(' isset_variables ')' { $$.ast = $3.ast; }
|
||||
| T_EMPTY '(' expr ')' { $$.ast = zend_ast_create_unary(ZEND_AST_EMPTY, $3.ast); }
|
||||
| T_INCLUDE expr
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2.ast); }
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2.ast); }
|
||||
| T_INCLUDE_ONCE expr
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2.ast); }
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2.ast); }
|
||||
| T_EVAL '(' expr ')'
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_EVAL, $3.ast); }
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, $3.ast); }
|
||||
| T_REQUIRE expr
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2.ast); }
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2.ast); }
|
||||
| T_REQUIRE_ONCE expr
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2.ast); }
|
||||
{ $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2.ast); }
|
||||
;
|
||||
|
||||
isset_variables:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue