summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Weinand <bobwei9@hotmail.com>2013-10-31 08:57:12 +0100
committerBob Weinand <bobwei9@hotmail.com>2013-10-31 08:57:12 +0100
commit2361745806553db9099542d9237ade00dcee799b (patch)
tree8db4023bf325be29ba4f386cb6d1aac4f7911c9a
parent4218e89f8df4ca3897e3aad595e0c2c9cf4c3aca (diff)
downloadphp-git-2361745806553db9099542d9237ade00dcee799b.tar.gz
Working commit for constant scalar expressions (with constants).
Tests will follow.
-rw-r--r--Zend/Makefile.am3
-rw-r--r--Zend/Zend.dsp4
-rw-r--r--Zend/ZendTS.dsp4
-rw-r--r--Zend/zend.h23
-rw-r--r--Zend/zend_API.c57
-rw-r--r--Zend/zend_ast.c128
-rw-r--r--Zend/zend_ast.h60
-rw-r--r--Zend/zend_builtin_functions.c7
-rw-r--r--Zend/zend_compile.c25
-rw-r--r--Zend/zend_compile.h1
-rw-r--r--Zend/zend_execute_API.c334
-rw-r--r--Zend/zend_language_parser.y34
-rw-r--r--Zend/zend_operators.h3
-rw-r--r--Zend/zend_variables.c10
-rw-r--r--Zend/zend_vm_def.h64
-rw-r--r--Zend/zend_vm_execute.h92
-rw-r--r--configure.in4
-rw-r--r--ext/reflection/php_reflection.c18
-rw-r--r--win32/build/config.w324
19 files changed, 599 insertions, 276 deletions
diff --git a/Zend/Makefile.am b/Zend/Makefile.am
index 6417f3eb14..d0316083b0 100644
--- a/Zend/Makefile.am
+++ b/Zend/Makefile.am
@@ -18,7 +18,8 @@ libZend_la_SOURCES=\
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
- zend_generators.c
+ zend_generators.c \
+ zend_ast.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp
index 23ebd4532b..9baf628b84 100644
--- a/Zend/Zend.dsp
+++ b/Zend/Zend.dsp
@@ -119,6 +119,10 @@ SOURCE=.\zend_API.c
# End Source File
# Begin Source File
+SOURCE=.\zend_ast.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_builtin_functions.c
# End Source File
# Begin Source File
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp
index 3be2c58bed..5dfa24d5b9 100644
--- a/Zend/ZendTS.dsp
+++ b/Zend/ZendTS.dsp
@@ -140,6 +140,10 @@ SOURCE=.\zend_alloc.c
# End Source File
# Begin Source File
+SOURCE=.\zend_ast.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_API.c
# End Source File
# Begin Source File
diff --git a/Zend/zend.h b/Zend/zend.h
index acbb6acaf7..7ccd0814e0 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -317,6 +317,7 @@ typedef struct _zend_object {
} zend_object;
#include "zend_object_handlers.h"
+#include "zend_ast.h"
typedef union _zvalue_value {
long lval; /* long value */
@@ -327,6 +328,7 @@ typedef union _zvalue_value {
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
+ zend_ast *ast;
} zvalue_value;
struct _zval_struct {
@@ -577,17 +579,18 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
/* data types */
/* All data types <= IS_BOOL have their constructor/destructors skipped */
-#define IS_NULL 0
-#define IS_LONG 1
-#define IS_DOUBLE 2
-#define IS_BOOL 3
-#define IS_ARRAY 4
-#define IS_OBJECT 5
-#define IS_STRING 6
-#define IS_RESOURCE 7
-#define IS_CONSTANT 8
+#define IS_NULL 0
+#define IS_LONG 1
+#define IS_DOUBLE 2
+#define IS_BOOL 3
+#define IS_ARRAY 4
+#define IS_OBJECT 5
+#define IS_STRING 6
+#define IS_RESOURCE 7
+#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
-#define IS_CALLABLE 10
+#define IS_CONSTANT_AST 10
+#define IS_CALLABLE 11
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK 0x00f
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 5fa7fb908e..3051d19729 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1053,34 +1053,37 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
static int zval_update_class_constant(zval **pp, int is_static, int offset TSRMLS_DC) /* {{{ */
{
- if ((Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
- (Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_ARRAY) {
- zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
-
- if ((*scope)->parent) {
- zend_class_entry *ce = *scope;
- HashPosition pos;
- zend_property_info *prop_info;
-
- do {
- for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
- zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
- zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
- if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
- offset == prop_info->offset) {
- int ret;
- zend_class_entry *old_scope = *scope;
- *scope = prop_info->ce;
- ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
- *scope = old_scope;
- return ret;
- }
- }
- ce = ce->parent;
- } while (ce);
-
+ switch (Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST: {
+ zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
+
+ if ((*scope)->parent) {
+ zend_class_entry *ce = *scope;
+ HashPosition pos;
+ zend_property_info *prop_info;
+
+ do {
+ for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+ zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
+ if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
+ offset == prop_info->offset) {
+ int ret;
+ zend_class_entry *old_scope = *scope;
+ *scope = prop_info->ce;
+ ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
+ *scope = old_scope;
+ return ret;
+ }
+ }
+ ce = ce->parent;
+ } while (ce);
+
+ }
+ return zval_update_constant(pp, (void*)1 TSRMLS_CC);
}
- return zval_update_constant(pp, (void*)1 TSRMLS_CC);
}
return 0;
}
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
new file mode 100644
index 0000000000..705c4df465
--- /dev/null
+++ b/Zend/zend_ast.c
@@ -0,0 +1,128 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Bob Weinand <bwoebi@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "zend_ast.h"
+#include "zend_execute.h"
+
+#define OP_IS_CONST_THEN(op, do_code) \
+ switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
+ case IS_CONSTANT: \
+ case IS_CONSTANT_ARRAY: \
+ case IS_CONSTANT_AST: { \
+ do_code \
+ } \
+ }
+
+#define OP_IS_NOT_CONST_THEN(op, do_code) \
+ switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
+ case IS_CONSTANT: \
+ case IS_CONSTANT_ARRAY: \
+ case IS_CONSTANT_AST: \
+ break; \
+\
+ default: { \
+ do_code \
+ } \
+ }
+
+#define COPY_ZVAL_TO_OP(nr) \
+ Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
+ *Z_AST_P(result)->ops[nr] = *op##nr;
+
+void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) {
+ zend_ast *ast = emalloc(sizeof(zend_ast));
+ ast->op_count = op_count;
+ ast->ops = emalloc(op_count * sizeof(zval *));
+ ast->refcount = 1;
+ ast->func = func;
+ Z_AST_P(result) = ast;
+ Z_TYPE_P(result) = IS_CONSTANT_AST;
+}
+
+/* Do operations on constant operators at compile time (AST building time) */
+
+void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0) {
+ OP_IS_NOT_CONST_THEN(op0,
+ func(result, op0);
+ return;
+ )
+
+ zend_ast_add(result, (intermediary_ast_function_type)func, 1);
+ COPY_ZVAL_TO_OP(0)
+}
+
+void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1) {
+ OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1,
+ func(result, op0, op1);
+ return;
+ ))
+
+ zend_ast_add(result, (intermediary_ast_function_type)func, 2);
+ COPY_ZVAL_TO_OP(0)
+ COPY_ZVAL_TO_OP(1)
+}
+
+void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2) {
+ OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1, OP_IS_NOT_CONST_THEN(op2,
+ func(result, op0, op1, op2);
+ return;
+ )))
+
+ zend_ast_add(result, (intermediary_ast_function_type)func, 3);
+ COPY_ZVAL_TO_OP(0)
+ COPY_ZVAL_TO_OP(1)
+ COPY_ZVAL_TO_OP(2)
+}
+
+void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) {
+ int i;
+
+ for (i = ast->op_count; i--;) {
+ OP_IS_CONST_THEN(ast->ops[i],
+ zval_update_constant_ex(&ast->ops[i], (void *)1, NULL TSRMLS_CC);
+ )
+ }
+
+ switch (ast->op_count) {
+ case 1:
+ ((unary_ast_func)ast->func)(result, ast->ops[0]);
+ break;
+ case 2:
+ ((binary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1]);
+ break;
+ case 3:
+ ((ternary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1], ast->ops[2]);
+ break;
+ }
+}
+
+void zend_ast_destroy(zend_ast *ast TSRMLS_DC) {
+ int i;
+
+ for (i = ast->op_count; i--;) {
+ if (!Z_DELREF_P(ast->ops[i])) {
+ zval_dtor(ast->ops[i]);
+ efree(ast->ops[i]);
+ }
+ }
+
+ efree(ast->ops);
+ efree(ast);
+}
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
new file mode 100644
index 0000000000..9841c3463e
--- /dev/null
+++ b/Zend/zend_ast.h
@@ -0,0 +1,60 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Bob Weinand <bwoebi@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef ZEND_AST_H
+#define ZEND_AST_H
+
+typedef struct _zend_ast zend_ast;
+
+#include "zend.h"
+
+typedef void(*intermediary_ast_function_type)(zval *, ...);
+typedef int(*unary_ast_func)(zval *result, zval *op0);
+typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1);
+typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2);
+
+struct _zend_ast {
+ char op_count;
+ zval **ops;
+ intermediary_ast_function_type func;
+ int refcount;
+};
+
+void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0);
+void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1);
+void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2);
+
+void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
+
+void zend_ast_destroy(zend_ast *ast TSRMLS_DC);
+
+#define ZEND_AST_ADD_REF(ast) ++ast->refcount
+
+static inline int ZEND_AST_DEL_REF(zend_ast *ast) {
+ if (ast->refcount == 1) {
+ TSRMLS_FETCH();
+
+ zend_ast_destroy(ast TSRMLS_CC);
+ return 0;
+ }
+ return --ast->refcount;
+}
+
+#endif
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 55e5f34e83..b3b7529d9b 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -946,8 +946,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
/* this is necessary to make it able to work with default array
* properties, returned to user */
- if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- zval_update_constant(&prop_copy, 0 TSRMLS_CC);
+ switch (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST:
+ zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
add_assoc_zval(return_value, key, prop_copy);
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 7ee8dd1e74..f3bf5be380 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1891,7 +1891,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
if (class_type->u.constant.type == IS_ARRAY) {
cur_arg_info->type_hint = IS_ARRAY;
if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
cur_arg_info->allow_null = 1;
} else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
@@ -1900,7 +1900,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
} else if (class_type->u.constant.type == IS_CALLABLE) {
cur_arg_info->type_hint = IS_CALLABLE;
if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
cur_arg_info->allow_null = 1;
} else {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
@@ -1915,7 +1915,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
cur_arg_info->allow_null = 1;
} else {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
@@ -5530,7 +5530,8 @@ static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal
(c->flags & CONST_PERSISTENT) &&
!(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
Z_TYPE(c->value) != IS_CONSTANT &&
- Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
+ Z_TYPE(c->value) != IS_CONSTANT_ARRAY &&
+ Z_TYPE(c->value) != IS_CONSTANT_AST) {
return c;
}
return NULL;
@@ -5772,7 +5773,7 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
ALLOC_ZVAL(element);
*element = expr->u.constant;
if (offset) {
- switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
+ switch (Z_TYPE(offset->u.constant) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
/* Ugly hack to denote that this value has a constant index */
Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
@@ -5782,6 +5783,20 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
break;
+ case IS_CONSTANT_AST: {
+ /* Another ugly hack to store the data about the AST in the array */
+ char* key;
+ int len = sizeof(zend_ast *);
+ Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
+
+ key = emalloc(len + 2);
+ *(zend_ast **)key = Z_AST(offset->u.constant);
+ key[len] = Z_TYPE(offset->u.constant);
+ key[len + 1] = 0;
+ zend_symtable_update(Z_ARRVAL(result->u.constant), key, len + 2, &element, sizeof(zval *), NULL);
+ efree(key);
+ }
+ break;
case IS_STRING:
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+1, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index f9520c98ea..bbc6e47383 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -23,6 +23,7 @@
#define ZEND_COMPILE_H
#include "zend.h"
+#include "zend_ast.h"
#ifdef HAVE_STDARG_H
# include <stdarg.h>
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 779e6d886f..eabebacce4 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -478,188 +478,208 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
if (IS_CONSTANT_VISITED(p)) {
zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
- } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- int refcount;
- zend_uchar is_ref;
+ return FAILURE;
+ }
+ switch (Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT: {
+ int refcount;
+ zend_uchar is_ref;
- SEPARATE_ZVAL_IF_NOT_REF(pp);
- p = *pp;
+ SEPARATE_ZVAL_IF_NOT_REF(pp);
+ p = *pp;
- MARK_CONSTANT_VISITED(p);
+ MARK_CONSTANT_VISITED(p);
- refcount = Z_REFCOUNT_P(p);
- is_ref = Z_ISREF_P(p);
+ refcount = Z_REFCOUNT_P(p);
+ is_ref = Z_ISREF_P(p);
- if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
- char *actual = Z_STRVAL_P(p);
+ if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
+ char *actual = Z_STRVAL_P(p);
- if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
- zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
- Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
- if (inline_change) {
- colon = estrndup(colon, Z_STRLEN_P(p));
- str_efree(Z_STRVAL_P(p));
- Z_STRVAL_P(p) = colon;
- } else {
- Z_STRVAL_P(p) = colon + 1;
- }
- } else {
- char *save = actual, *slash;
- int actual_len = Z_STRLEN_P(p);
- if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
- actual = slash + 1;
- actual_len -= (actual - Z_STRVAL_P(p));
+ if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
+ Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
if (inline_change) {
- actual = estrndup(actual, actual_len);
- Z_STRVAL_P(p) = actual;
- Z_STRLEN_P(p) = actual_len;
- }
- }
- if (actual[0] == '\\') {
- if (inline_change) {
- memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
- --Z_STRLEN_P(p);
+ colon = estrndup(colon, Z_STRLEN_P(p));
+ str_efree(Z_STRVAL_P(p));
+ Z_STRVAL_P(p) = colon;
} else {
- ++actual;
+ Z_STRVAL_P(p) = colon + 1;
}
- --actual_len;
- }
- if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
- int fix_save = 0;
- if (save[0] == '\\') {
- save++;
- fix_save = 1;
+ } else {
+ char *save = actual, *slash;
+ int actual_len = Z_STRLEN_P(p);
+ if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
+ actual = slash + 1;
+ actual_len -= (actual - Z_STRVAL_P(p));
+ if (inline_change) {
+ actual = estrndup(actual, actual_len);
+ Z_STRVAL_P(p) = actual;
+ Z_STRLEN_P(p) = actual_len;
+ }
}
- zend_error(E_ERROR, "Undefined constant '%s'", save);
- if (fix_save) {
- save--;
+ if (actual[0] == '\\') {
+ if (inline_change) {
+ memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
+ --Z_STRLEN_P(p);
+ } else {
+ ++actual;
+ }
+ --actual_len;
}
- if (inline_change) {
+ if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
+ int fix_save = 0;
+ if (save[0] == '\\') {
+ save++;
+ fix_save = 1;
+ }
+ zend_error(E_ERROR, "Undefined constant '%s'", save);
+ if (fix_save) {
+ save--;
+ }
+ if (inline_change) {
+ str_efree(save);
+ }
+ save = NULL;
+ }
+ if (inline_change && save && save != actual) {
str_efree(save);
}
- save = NULL;
- }
- if (inline_change && save && save != actual) {
- str_efree(save);
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
+ p->type = IS_STRING;
+ if (!inline_change) {
+ Z_STRVAL_P(p) = actual;
+ Z_STRLEN_P(p) = actual_len;
+ zval_copy_ctor(p);
+ }
}
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
- p->type = IS_STRING;
- if (!inline_change) {
- Z_STRVAL_P(p) = actual;
- Z_STRLEN_P(p) = actual_len;
- zval_copy_ctor(p);
+ } else {
+ if (inline_change) {
+ str_efree(Z_STRVAL_P(p));
}
+ *p = const_value;
}
- } else {
- if (inline_change) {
- str_efree(Z_STRVAL_P(p));
- }
- *p = const_value;
- }
- Z_SET_REFCOUNT_P(p, refcount);
- Z_SET_ISREF_TO_P(p, is_ref);
- } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
- zval **element, *new_val;
- char *str_index;
- uint str_index_len;
- ulong num_index;
- int ret;
-
- SEPARATE_ZVAL_IF_NOT_REF(pp);
- p = *pp;
- Z_TYPE_P(p) = IS_ARRAY;
-
- if (!inline_change) {
- zval *tmp;
- HashTable *tmp_ht = NULL;
-
- ALLOC_HASHTABLE(tmp_ht);
- zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
- Z_ARRVAL_P(p) = tmp_ht;
+ Z_SET_REFCOUNT_P(p, refcount);
+ Z_SET_ISREF_TO_P(p, is_ref);
}
-
- /* First go over the array and see if there are any constant indices */
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
- while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
- if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
- continue;
+ break;
+
+ case IS_CONSTANT_ARRAY: {
+ zval **element, *new_val;
+ char *str_index;
+ uint str_index_len;
+ ulong num_index;
+ int ret;
+
+ SEPARATE_ZVAL_IF_NOT_REF(pp);
+ p = *pp;
+ Z_TYPE_P(p) = IS_ARRAY;
+
+ if (!inline_change) {
+ zval *tmp;
+ HashTable *tmp_ht = NULL;
+
+ ALLOC_HASHTABLE(tmp_ht);
+ zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
+ Z_ARRVAL_P(p) = tmp_ht;
}
- Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
- if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
- continue;
- }
- if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
- char *actual;
- const char *save = str_index;
- if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
- zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
- str_index_len -= ((colon - str_index) + 1);
- str_index = colon;
- } else {
- if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
- if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
- actual++;
- str_index_len -= (actual - str_index);
- str_index = actual;
+
+ /* First go over the array and see if there are any constant indices */
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
+ while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
+ if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ continue;
+ }
+ Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
+ if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ continue;
+ }
+ if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
+ zend_ast_evaluate(&const_value, *(zend_ast **)str_index);
+ ZEND_AST_DEL_REF(*(zend_ast **)str_index);
+ } else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
+ char *actual;
+ const char *save = str_index;
+ if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
+ zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
+ str_index_len -= ((colon - str_index) + 1);
+ str_index = colon;
+ } else {
+ if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
+ if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
+ actual++;
+ str_index_len -= (actual - str_index);
+ str_index = actual;
+ }
}
+ if (str_index[0] == '\\') {
+ ++str_index;
+ --str_index_len;
+ }
+ if (save[0] == '\\') {
+ ++save;
+ }
+ if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
+ zend_error(E_ERROR, "Undefined constant '%s'", save);
+ }
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
}
- if (str_index[0] == '\\') {
- ++str_index;
- --str_index_len;
- }
- if (save[0] == '\\') {
- ++save;
- }
- if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
- zend_error(E_ERROR, "Undefined constant '%s'", save);
- }
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
+ ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
}
- ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
- }
- if (Z_REFCOUNT_PP(element) > 1) {
- ALLOC_ZVAL(new_val);
- *new_val = **element;
- zval_copy_ctor(new_val);
- Z_SET_REFCOUNT_P(new_val, 1);
- Z_UNSET_ISREF_P(new_val);
-
- /* preserve this bit for inheritance */
- Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
- zval_ptr_dtor(element);
- *element = new_val;
- }
+ if (Z_REFCOUNT_PP(element) > 1) {
+ ALLOC_ZVAL(new_val);
+ *new_val = **element;
+ zval_copy_ctor(new_val);
+ Z_SET_REFCOUNT_P(new_val, 1);
+ Z_UNSET_ISREF_P(new_val);
+
+ /* preserve this bit for inheritance */
+ Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
+ zval_ptr_dtor(element);
+ *element = new_val;
+ }
- switch (Z_TYPE(const_value)) {
- case IS_STRING:
- ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
- break;
- case IS_BOOL:
- case IS_LONG:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- case IS_DOUBLE:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- case IS_NULL:
- ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
- break;
- default:
- ret = SUCCESS;
- break;
- }
- if (ret == SUCCESS) {
- zend_hash_move_forward(Z_ARRVAL_P(p));
+ switch (Z_TYPE(const_value)) {
+ case IS_STRING:
+ ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
+ break;
+ case IS_BOOL:
+ case IS_LONG:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ case IS_DOUBLE:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ case IS_NULL:
+ ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
+ break;
+ default:
+ ret = SUCCESS;
+ break;
+ }
+ if (ret == SUCCESS) {
+ zend_hash_move_forward(Z_ARRVAL_P(p));
+ }
+ zval_dtor(&const_value);
}
- zval_dtor(&const_value);
+ zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
+ }
+ break;
+
+ case IS_CONSTANT_AST: {
+ zend_ast *ast = Z_AST_P(p);
+
+ MARK_CONSTANT_VISITED(p);
+
+ zend_ast_evaluate(p, ast TSRMLS_CC);
+ ZEND_AST_DEL_REF(ast);
}
- zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
}
return 0;
}
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index f76b77b555..517ae56e41 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -947,24 +947,46 @@ common_scalar:
| T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
;
+static_class_constant:
+ class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
+;
static_scalar: /* compile-time evaluated scalars */
- common_scalar { $$ = $1; }
+ static_scalar_value { $$ = $1; }
+;
+
+static_scalar_value:
+ common_scalar { $$ = $1; }
| static_class_name_scalar { $$ = $1; }
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); }
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
- | '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
- | '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
| '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
| static_class_constant { $$ = $1; }
| T_CLASS_C { $$ = $1; }
+ | static_operation { $$ = $1; }
+;
+
+static_operation:
+ static_scalar_value '+' static_scalar_value { zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '-' static_scalar_value { zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '*' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mul_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '/' static_scalar_value { zend_ast_add_binary(&$$.u.constant, div_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '%' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mod_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | '!' static_scalar_value { zend_ast_add_unary(&$$.u.constant, boolean_not_function, &$2.u.constant TSRMLS_CC); }
+ | '~' static_scalar_value { zend_ast_add_unary(&$$.u.constant, bitwise_not_function, &$2.u.constant TSRMLS_CC); }
+ | static_scalar_value '|' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '&' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '^' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_SL static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_left_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_SR static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_right_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '.' static_scalar_value { zend_ast_add_binary(&$$.u.constant, concat_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | '+' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
+ | '-' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
+ | '(' static_scalar_value ')' { $$ = $2; }
;
-static_class_constant:
- class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
-;
scalar:
T_STRING_VARNAME { $$ = $1; }
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 15ad79e4db..ce21af3d2e 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -443,6 +443,7 @@ END_EXTERN_C()
#define Z_STRVAL(zval) (zval).value.str.val
#define Z_STRLEN(zval) (zval).value.str.len
#define Z_ARRVAL(zval) (zval).value.ht
+#define Z_AST(zval) (zval).value.ast
#define Z_OBJVAL(zval) (zval).value.obj
#define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle
#define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers
@@ -458,6 +459,7 @@ END_EXTERN_C()
#define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)
#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
#define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)
+#define Z_AST_P(zval_p) Z_AST(*zval_p)
#define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p)
#define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p)
#define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p)
@@ -473,6 +475,7 @@ END_EXTERN_C()
#define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp)
#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)
#define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp)
+#define Z_AST_PP(zval_p) Z_AST(**zval_p)
#define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp)
#define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp)
#define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp)
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index d82e1642e7..095c16ca91 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include "zend.h"
#include "zend_API.h"
+#include "zend_ast.h"
#include "zend_globals.h"
#include "zend_constants.h"
#include "zend_list.h"
@@ -47,6 +48,9 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
}
}
break;
+ case IS_CONSTANT_AST:
+ ZEND_AST_DEL_REF(Z_AST_P(zvalue));
+ break;
case IS_OBJECT:
{
TSRMLS_FETCH();
@@ -81,6 +85,9 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
CHECK_ZVAL_STRING_REL(zvalue);
str_free(zvalue->value.str.val);
break;
+ case IS_CONSTANT_AST:
+ ZEND_AST_DEL_REF(Z_AST_P(zvalue));
+ break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
case IS_OBJECT:
@@ -139,6 +146,9 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
zvalue->value.ht = tmp_ht;
}
break;
+ case IS_CONSTANT_AST:
+ ZEND_AST_ADD_REF(Z_AST_P(zvalue));
+ break;
case IS_OBJECT:
{
TSRMLS_FETCH();
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 572aac5a20..4ee5a99c7b 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3252,12 +3252,16 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
if (param == NULL) {
ALLOC_ZVAL(assignment_value);
*assignment_value = *opline->op2.zv;
- if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
- Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
- Z_SET_REFCOUNT_P(assignment_value, 1);
- zval_update_constant(&assignment_value, 0 TSRMLS_CC);
- } else {
- zval_copy_ctor(assignment_value);
+ switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST:
+ Z_SET_REFCOUNT_P(assignment_value, 1);
+ zval_update_constant(&assignment_value, 0 TSRMLS_CC);
+ break;
+ default:
+ zval_copy_ctor(assignment_value);
+ break;
}
INIT_PZVAL(assignment_value);
} else {
@@ -3580,13 +3584,16 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
- if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
- (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- zend_class_entry *old_scope = EG(scope);
-
- EG(scope) = ce;
- zval_update_constant(value, (void *) 1 TSRMLS_CC);
- EG(scope) = old_scope;
+ switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST: {
+ zend_class_entry *old_scope = EG(scope);
+
+ EG(scope) = ce;
+ zval_update_constant(value, (void *) 1 TSRMLS_CC);
+ EG(scope) = old_scope;
+ }
}
if (OP1_TYPE == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
@@ -5187,20 +5194,27 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
name = GET_OP1_ZVAL_PTR(BP_VAR_R);
val = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
- zval tmp;
- zval *tmp_ptr = &tmp;
+ switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST: {
+ zval tmp;
+ zval *tmp_ptr = &tmp;
- ZVAL_COPY_VALUE(&tmp, val);
- if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
- zval_copy_ctor(&tmp);
+ ZVAL_COPY_VALUE(&tmp, val);
+ if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
+ zval_copy_ctor(&tmp);
+ }
+ INIT_PZVAL(&tmp);
+ zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
+ c.value = *tmp_ptr;
}
- INIT_PZVAL(&tmp);
- zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
- c.value = *tmp_ptr;
- } else {
- INIT_PZVAL_COPY(&c.value, val);
- zval_copy_ctor(&c.value);
+ break;
+
+ default:
+ INIT_PZVAL_COPY(&c.value, val);
+ zval_copy_ctor(&c.value);
+ break;
}
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 869bb199b2..a90f187fef 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1435,12 +1435,16 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
if (param == NULL) {
ALLOC_ZVAL(assignment_value);
*assignment_value = *opline->op2.zv;
- if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
- Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
- Z_SET_REFCOUNT_P(assignment_value, 1);
- zval_update_constant(&assignment_value, 0 TSRMLS_CC);
- } else {
- zval_copy_ctor(assignment_value);
+ switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST:
+ Z_SET_REFCOUNT_P(assignment_value, 1);
+ zval_update_constant(&assignment_value, 0 TSRMLS_CC);
+ break;
+ default:
+ zval_copy_ctor(assignment_value);
+ break;
}
INIT_PZVAL(assignment_value);
} else {
@@ -3792,13 +3796,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
- if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
- (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- zend_class_entry *old_scope = EG(scope);
+ switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST: {
+ zend_class_entry *old_scope = EG(scope);
- EG(scope) = ce;
- zval_update_constant(value, (void *) 1 TSRMLS_CC);
- EG(scope) = old_scope;
+ EG(scope) = ce;
+ zval_update_constant(value, (void *) 1 TSRMLS_CC);
+ EG(scope) = old_scope;
+ }
}
if (IS_CONST == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
@@ -4089,20 +4096,27 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
name = opline->op1.zv;
val = opline->op2.zv;
- if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
- zval tmp;
- zval *tmp_ptr = &tmp;
+ switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST: {
+ zval tmp;
+ zval *tmp_ptr = &tmp;
- ZVAL_COPY_VALUE(&tmp, val);
- if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
- zval_copy_ctor(&tmp);
+ ZVAL_COPY_VALUE(&tmp, val);
+ if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
+ zval_copy_ctor(&tmp);
+ }
+ INIT_PZVAL(&tmp);
+ zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
+ c.value = *tmp_ptr;
}
- INIT_PZVAL(&tmp);
- zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
- c.value = *tmp_ptr;
- } else {
- INIT_PZVAL_COPY(&c.value, val);
- zval_copy_ctor(&c.value);
+ break;
+
+ default:
+ INIT_PZVAL_COPY(&c.value, val);
+ zval_copy_ctor(&c.value);
+ break;
}
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
@@ -15635,13 +15649,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
- if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
- (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- zend_class_entry *old_scope = EG(scope);
+ switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST: {
+ zend_class_entry *old_scope = EG(scope);
- EG(scope) = ce;
- zval_update_constant(value, (void *) 1 TSRMLS_CC);
- EG(scope) = old_scope;
+ EG(scope) = ce;
+ zval_update_constant(value, (void *) 1 TSRMLS_CC);
+ EG(scope) = old_scope;
+ }
}
if (IS_VAR == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
@@ -25171,13 +25188,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
- if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
- (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- zend_class_entry *old_scope = EG(scope);
+ switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST: {
+ zend_class_entry *old_scope = EG(scope);
- EG(scope) = ce;
- zval_update_constant(value, (void *) 1 TSRMLS_CC);
- EG(scope) = old_scope;
+ EG(scope) = ce;
+ zval_update_constant(value, (void *) 1 TSRMLS_CC);
+ EG(scope) = old_scope;
+ }
}
if (IS_UNUSED == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
diff --git a/configure.in b/configure.in
index 16738fe30a..97fd68ec3a 100644
--- a/configure.in
+++ b/configure.in
@@ -1475,7 +1475,9 @@ PHP_ADD_SOURCES(Zend, \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
- zend_closures.c zend_float.c zend_string.c zend_signal.c zend_generators.c)
+ zend_closures.c zend_float.c zend_string.c zend_signal.c \
+ zend_generators.c \
+ zend_ast.c)
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index cc148b39c5..abebc216c3 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -2599,9 +2599,14 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
*return_value = *precv->op2.zv;
INIT_PZVAL(return_value);
- if ((Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT
- && (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT_ARRAY) {
- zval_copy_ctor(return_value);
+ switch (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST:
+ break;
+
+ default:
+ zval_copy_ctor(return_value);
}
zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC);
}
@@ -3414,8 +3419,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
/* this is necessary to make it able to work with default array
* properties, returned to user */
- if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
+ switch (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) {
+ case IS_CONSTANT:
+ case IS_CONSTANT_ARRAY:
+ case IS_CONSTANT_AST:
+ zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
}
add_assoc_zval(return_value, key, prop_copy);
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index 3401205c8f..d9bbc7e794 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -364,7 +364,9 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \
zend_object_handlers.c zend_objects_API.c \
zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \
- zend_float.c zend_string.c zend_generators.c");
+ zend_float.c zend_string.c \
+ zend_generators.c \
+ zend_ast.c");
if (VCVERS == 1200) {
AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);