summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2013-11-06 15:41:33 +0400
committerDmitry Stogov <dmitry@zend.com>2013-11-06 15:41:33 +0400
commitaf600c240d2efe33291e8dd71ce228b9fbc849c1 (patch)
tree9a0940e0e80bc92ba9c371f850a595f9347cbfb6
parentd87388ba0f6cf29eb495f9af96ab6aa353ebcc4f (diff)
parent18e2b1a9a930d5ae15544c5a2beed6b20d58cdee (diff)
downloadphp-git-af600c240d2efe33291e8dd71ce228b9fbc849c1.tar.gz
Merge branch 'const_scalar_exprs' of github.com:bwoebi/php-src into const_scalar_exprs
* 'const_scalar_exprs' of github.com:bwoebi/php-src: Removed operations on constant arrays. They make no sense as constants are not allowed to be arrays. And as just properties are allowed to; no problem, we still don't need operations on any constant array. Added a few more operators Whitespace fix converted several switches to ifs and made more opcache friendly Fatal error about self referencing constants fixed Fixed mem leaks, added tests and ternary operator Working commit for constant scalar expressions (with constants). Tests will follow. Conflicts: Zend/Makefile.am configure.in win32/build/config.w32
-rw-r--r--Zend/Makefile.am2
-rw-r--r--Zend/Zend.dsp4
-rw-r--r--Zend/ZendTS.dsp4
-rw-r--r--Zend/tests/class_properties_dynamic.phpt13
-rw-r--r--Zend/tests/class_properties_static.phpt20
-rw-r--r--Zend/tests/constant_expressions.phpt91
-rw-r--r--Zend/tests/constant_expressions_dynamic.phpt11
-rw-r--r--Zend/tests/function_arguments_003.phpt17
-rw-r--r--Zend/tests/static_variable.phpt29
-rw-r--r--Zend/zend.h25
-rw-r--r--Zend/zend_API.c5
-rw-r--r--Zend/zend_ast.c130
-rw-r--r--Zend/zend_ast.h60
-rw-r--r--Zend/zend_builtin_functions.c2
-rw-r--r--Zend/zend_compile.c25
-rw-r--r--Zend/zend_compile.h5
-rw-r--r--Zend/zend_execute_API.c331
-rw-r--r--Zend/zend_language_parser.y53
-rw-r--r--Zend/zend_operators.c62
-rw-r--r--Zend/zend_operators.h7
-rw-r--r--Zend/zend_variables.c10
-rw-r--r--Zend/zend_vm_def.h9
-rw-r--r--Zend/zend_vm_execute.h15
-rw-r--r--configure.in2
-rw-r--r--ext/reflection/php_reflection.c5
-rw-r--r--win32/build/config.w322
26 files changed, 734 insertions, 205 deletions
diff --git a/Zend/Makefile.am b/Zend/Makefile.am
index 924a00daeb..d9ce4c61ba 100644
--- a/Zend/Makefile.am
+++ b/Zend/Makefile.am
@@ -18,7 +18,7 @@ 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_virtual_cwd.c
+ zend_generators.c zend_virtual_cwd.c zend_ast.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp
index d1b3b89030..d8bb03b9e8 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/tests/class_properties_dynamic.phpt b/Zend/tests/class_properties_dynamic.phpt
new file mode 100644
index 0000000000..8a1fc6f029
--- /dev/null
+++ b/Zend/tests/class_properties_dynamic.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Class Property Expressions
+--FILE--
+<?php
+class Foo {
+ const BAR = 1 << 0;
+ const BAZ = 1 << 1;
+ public $bar = self::BAR | self::BAZ;
+}
+echo (new Foo)->bar;
+?>
+--EXPECTF--
+3
diff --git a/Zend/tests/class_properties_static.phpt b/Zend/tests/class_properties_static.phpt
new file mode 100644
index 0000000000..9a56466340
--- /dev/null
+++ b/Zend/tests/class_properties_static.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Static Class Property Expressions
+--FILE--
+<?php
+class Foo {
+ public $b1 = 1 + 1;
+ public $b2 = 1 << 2;
+ public $b3 = "foo " . " bar " . " baz";
+}
+$f = new Foo;
+var_dump(
+ $f->b1,
+ $f->b2,
+ $f->b3
+);
+?>
+--EXPECT--
+int(2)
+int(4)
+string(13) "foo bar baz"
diff --git a/Zend/tests/constant_expressions.phpt b/Zend/tests/constant_expressions.phpt
new file mode 100644
index 0000000000..7dea0d83f7
--- /dev/null
+++ b/Zend/tests/constant_expressions.phpt
@@ -0,0 +1,91 @@
+--TEST--
+Constant Expressions
+--FILE--
+<?php
+const T_1 = 1 << 1;
+const T_2 = 1 / 2;
+const T_3 = 1.5 + 1.5;
+const T_4 = "foo" . "bar";
+const T_5 = (1.5 + 1.5) * 2;
+const T_6 = "foo" . 2 . 3 . 4.0;
+const T_7 = __LINE__;
+const T_8 = <<<ENDOFSTRING
+This is a test string
+ENDOFSTRING;
+const T_9 = ~-1;
+const T_10 = (-1?:1) + (0?2:3);
+const T_11 = 1 && 0;
+const T_12 = 1 and 1;
+const T_13 = 0 || 0;
+const T_14 = 1 or 0;
+const T_15 = 1 xor 1;
+const T_16 = 1 xor 0;
+const T_17 = 1 < 0;
+const T_18 = 0 <= 0;
+const T_19 = 1 > 0;
+const T_20 = 1 >= 0;
+const T_21 = 1 === 1;
+const T_22 = 1 !== 1;
+const T_23 = 0 != "0";
+const T_24 = 1 == "1";
+
+// Test order of operations
+const T_25 = 1 + 2 * 3;
+
+// Test for memory leaks
+const T_26 = "1" + 2 + "3";
+
+var_dump(T_1);
+var_dump(T_2);
+var_dump(T_3);
+var_dump(T_4);
+var_dump(T_5);
+var_dump(T_6);
+var_dump(T_7);
+var_dump(T_8);
+var_dump(T_9);
+var_dump(T_10);
+var_dump(T_11);
+var_dump(T_12);
+var_dump(T_13);
+var_dump(T_14);
+var_dump(T_15);
+var_dump(T_16);
+var_dump(T_17);
+var_dump(T_18);
+var_dump(T_19);
+var_dump(T_20);
+var_dump(T_21);
+var_dump(T_22);
+var_dump(T_23);
+var_dump(T_24);
+var_dump(T_25);
+var_dump(T_26);
+?>
+--EXPECT--
+int(2)
+float(0.5)
+float(3)
+string(6) "foobar"
+float(6)
+string(6) "foo234"
+int(8)
+string(21) "This is a test string"
+int(0)
+int(2)
+bool(false)
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+int(7)
+int(6)
diff --git a/Zend/tests/constant_expressions_dynamic.phpt b/Zend/tests/constant_expressions_dynamic.phpt
new file mode 100644
index 0000000000..21c9216cc1
--- /dev/null
+++ b/Zend/tests/constant_expressions_dynamic.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Dynamic Constant Expressions
+--FILE--
+<?php
+const FOO = 1;
+const BAR = FOO | 2;
+
+echo BAR;
+?>
+--EXPECTF--
+3
diff --git a/Zend/tests/function_arguments_003.phpt b/Zend/tests/function_arguments_003.phpt
new file mode 100644
index 0000000000..b882476d1d
--- /dev/null
+++ b/Zend/tests/function_arguments_003.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Function Argument Parsing #003
+--FILE--
+<?php
+const a = 10;
+
+function t1($a = 1 + 1, $b = 1 << 2, $c = "foo" . "bar", $d = a * 10) {
+ var_dump($a, $b, $c, $d);
+}
+
+t1();
+?>
+--EXPECT--
+int(2)
+int(4)
+string(6) "foobar"
+int(100)
diff --git a/Zend/tests/static_variable.phpt b/Zend/tests/static_variable.phpt
new file mode 100644
index 0000000000..ea69a8f86b
--- /dev/null
+++ b/Zend/tests/static_variable.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Static Variable Expressions
+--FILE--
+<?php
+const bar = 2, baz = bar + 1;
+
+function foo() {
+ static $a = 1 + 1;
+ static $b = [bar => 1 + 1, baz * 2 => 1 << 2];
+ static $c = [1 => bar] + [3 => baz];
+ var_dump($a, $b, $c);
+}
+
+foo();
+?>
+--EXPECT--
+int(2)
+array(2) {
+ [2]=>
+ int(2)
+ [6]=>
+ int(4)
+}
+array(2) {
+ [1]=>
+ int(2)
+ [3]=>
+ int(3)
+}
diff --git a/Zend/zend.h b/Zend/zend.h
index 5ac884455d..a949c5b0b6 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
@@ -597,6 +600,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define IS_LEXICAL_REF 0x040
#define IS_CONSTANT_IN_NAMESPACE 0x100
+#define IS_CONSTANT_TYPE(type) (((type) & IS_CONSTANT_TYPE_MASK) >= IS_CONSTANT && ((type) & IS_CONSTANT_TYPE_MASK) <= IS_CONSTANT_AST)
+
/* overloaded elements data types */
#define OE_IS_ARRAY (1<<0)
#define OE_IS_OBJECT (1<<1)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 5fa7fb908e..3687b6a67b 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1053,8 +1053,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_PP(pp))) {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
if ((*scope)->parent) {
@@ -1078,7 +1077,7 @@ static int zval_update_class_constant(zval **pp, int is_static, int offset TSRML
}
ce = ce->parent;
} while (ce);
-
+
}
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
}
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
new file mode 100644
index 0000000000..21c08da510
--- /dev/null
+++ b/Zend/zend_ast.c
@@ -0,0 +1,130 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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 COPY_ZVAL_TO_OP(nr) \
+ if (op##nr) { \
+ Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
+ *Z_AST_P(result)->ops[nr] = *op##nr; \
+ } else { \
+ Z_AST_P(result)->ops[nr] = NULL; \
+ }
+
+void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) {
+ zend_ast *ast = emalloc(sizeof(zend_ast) + op_count * sizeof(zval *));
+ ast->op_count = op_count;
+ ast->ops = (zval **)(ast + 1);
+ 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 TSRMLS_DC) {
+ if (!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) {
+ func(result, op0 TSRMLS_CC);
+ if (op0) zval_dtor(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 TSRMLS_DC) {
+ if ((!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) && (!op1 || !IS_CONSTANT_TYPE(Z_TYPE_P(op1)))) {
+ func(result, op0, op1 TSRMLS_CC);
+ if (op0) zval_dtor(op0);
+ if (op1) zval_dtor(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 TSRMLS_DC) {
+ if ((!op0 || !IS_CONSTANT_TYPE(Z_TYPE_P(op0))) && (!op1 || !IS_CONSTANT_TYPE(Z_TYPE_P(op1))) && (!op2 || !IS_CONSTANT_TYPE(Z_TYPE_P(op2)))) {
+ func(result, op0, op1, op2 TSRMLS_CC);
+ if (op0) zval_dtor(op0);
+ if (op1) zval_dtor(op1);
+ if (op2) zval_dtor(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;
+ zval **ops = emalloc((sizeof(zval *) + sizeof(zval)) * ast->op_count);
+
+ for (i = ast->op_count; i--;) {
+ if (ast->ops[i] && IS_CONSTANT_TYPE(Z_TYPE_P(ast->ops[i]))) {
+ ops[i] = ((zval *)(ops + ast->op_count)) + i;
+ *ops[i] = *ast->ops[i];
+ zval_copy_ctor(ops[i]);
+ zval_update_constant_ex(&ops[i], (void *)1, NULL TSRMLS_CC);
+ } else {
+ ops[i] = ast->ops[i];
+ }
+ }
+
+ switch (ast->op_count) {
+ case 1:
+ ((unary_ast_func)ast->func)(result, ops[0] TSRMLS_CC);
+ break;
+ case 2:
+ ((binary_ast_func)ast->func)(result, ops[0], ops[1] TSRMLS_CC);
+ break;
+ case 3:
+ ((ternary_ast_func)ast->func)(result, ops[0], ops[1], ops[2] TSRMLS_CC);
+ break;
+ }
+
+ for (i = ast->op_count; i--;) {
+ if (ast->ops[i] != ops[i]) {
+ zval_dtor(ops[i]);
+ }
+ }
+
+ efree(ops);
+}
+
+void zend_ast_destroy(zend_ast *ast TSRMLS_DC) {
+ int i;
+
+ for (i = ast->op_count; i--;) {
+ if (ast->ops[i] && !Z_DELREF_P(ast->ops[i])) {
+ zval_dtor(ast->ops[i]);
+ efree(ast->ops[i]);
+ }
+ }
+
+ efree(ast);
+}
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
new file mode 100644
index 0000000000..218f2c02e0
--- /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 TSRMLS_DC);
+typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1 TSRMLS_DC);
+typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
+
+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 TSRMLS_DC);
+void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1 TSRMLS_DC);
+void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2 TSRMLS_DC);
+
+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..049864c54a 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -946,7 +946,7 @@ 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) {
+ switch (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) {
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 7132c3e5fc..77da945153 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");
@@ -5529,8 +5529,7 @@ static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal
if (all_internal_constants_substitution &&
(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) {
+ !IS_CONSTANT_TYPE(Z_TYPE(c->value))) {
return c;
}
return NULL;
@@ -5772,7 +5771,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 +5781,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..b80a7cb84f 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>
@@ -721,6 +722,10 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
#define ZEND_OP_DATA 137
+/* Pseudo-opcodes for internal object overloading */
+#define ZEND_BOOL_AND -1
+#define ZEND_BOOL_OR -2
+
/* END: OPCODES */
/* class fetches */
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 779e6d886f..12047f0518 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -478,188 +478,205 @@ 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)--);
+ } 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 TSRMLS_CC);
+ 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);
+
+ 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..19d6d839a2 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -947,24 +947,61 @@ 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; }
+ | 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_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 T_LOGICAL_XOR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_LOGICAL_AND static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_LOGICAL_OR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_BOOLEAN_AND static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_BOOLEAN_OR static_scalar_value { zend_ast_add_binary(&$$.u.constant, boolean_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_IS_IDENTICAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_identical_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_IS_NOT_IDENTICAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_not_identical_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_IS_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_IS_NOT_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_not_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '<' static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value '>' static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_function, &$3.u.constant, &$1.u.constant TSRMLS_CC); }
+ | static_scalar_value T_IS_SMALLER_OR_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_or_equal_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
+ | static_scalar_value T_IS_GREATER_OR_EQUAL static_scalar_value { zend_ast_add_binary(&$$.u.constant, is_smaller_or_equal_function, &$3.u.constant, &$1.u.constant TSRMLS_CC); }
+ | static_scalar_value '?' ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, NULL, &$4.u.constant TSRMLS_CC); }
+ | static_scalar_value '?' static_scalar_value ':' static_scalar_value { zend_ast_add_ternary(&$$.u.constant, ternary_function, &$1.u.constant, &$3.u.constant, &$5.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.c b/Zend/zend_operators.c
index e8629291e5..8c083542f0 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1082,6 +1082,46 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
/* }}} */
+ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ zval op1_copy, op2_copy;
+ long op1_lval;
+
+ if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_AND);
+
+ zendi_convert_to_boolean(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_boolean(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
+
+ ZVAL_BOOL(result, op1_lval & Z_LVAL_P(op2));
+ return SUCCESS;
+}
+/* }}} */
+
+ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ zval op1_copy, op2_copy;
+ long op1_lval;
+
+ if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_OR);
+
+ zendi_convert_to_boolean(op1, op1_copy, result);
+ op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_boolean(op2, op2_copy, result);
+ } else {
+ op1_lval = Z_LVAL_P(op1);
+ }
+
+ ZVAL_BOOL(result, op1_lval | Z_LVAL_P(op2));
+ return SUCCESS;
+}
+/* }}} */
+
ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
{
zval op1_copy;
@@ -2323,6 +2363,28 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
+#define PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(var) \
+ *result = *var; \
+ if (Z_REFCOUNT_P(var) == 1) { \
+ Z_TYPE_P(var) = IS_NULL; \
+ }
+
+ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC) /* {{{ */
+{
+ if (i_zend_is_true(condition)) {
+ if (then) {
+ PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(then);
+ } else {
+ PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(condition);
+ }
+ } else {
+ PREVENT_DTOR_IF_REFCOUNT_1_AND_ASSIGN_TO_RESULT(if_not);
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 15ad79e4db..3f0fc2ef6a 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -50,6 +50,8 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC);
ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC);
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
@@ -376,6 +378,8 @@ ZEND_API int zend_atoi(const char *str, int str_len);
ZEND_API long zend_atol(const char *str, int str_len);
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
+
+ZEND_API int ternary_function(zval *result, zval *condition, zval *then, zval *if_not TSRMLS_DC);
END_EXTERN_C()
#define convert_to_ex_master(ppzv, lower_type, upper_type) \
@@ -443,6 +447,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 +463,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 +479,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..006f2ec729 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3252,8 +3252,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_P(assignment_value))) {
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
} else {
@@ -3580,8 +3579,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_PP(value))) {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
@@ -5187,7 +5185,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_P(val))) {
zval tmp;
zval *tmp_ptr = &tmp;
@@ -5202,6 +5200,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
+
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 7ad7dcf463..4f850c2978 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1435,8 +1435,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_P(assignment_value))) {
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
} else {
@@ -3792,8 +3791,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_PP(value))) {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
@@ -4089,7 +4087,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_P(val))) {
zval tmp;
zval *tmp_ptr = &tmp;
@@ -4104,6 +4102,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
+
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
@@ -15635,8 +15634,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_PP(value))) {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
@@ -25171,8 +25169,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_PP(value))) {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
diff --git a/configure.in b/configure.in
index 805aa48f59..29358b1c88 100644
--- a/configure.in
+++ b/configure.in
@@ -1476,7 +1476,7 @@ PHP_ADD_SOURCES(Zend, \
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_virtual_cwd.c)
+ zend_virtual_cwd.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..bff5e66472 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -2599,8 +2599,7 @@ 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) {
+ if (!IS_CONSTANT_TYPE(Z_TYPE_P(return_value))) {
zval_copy_ctor(return_value);
}
zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC);
@@ -3414,7 +3413,7 @@ 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) {
+ if (IS_CONSTANT_TYPE(Z_TYPE_P(prop_copy))) {
zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
}
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index af92eb0d4c..6e19c48967 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -364,7 +364,7 @@ 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_virtual_cwd.c");
+ zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c");
if (VCVERS == 1200) {
AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);