summaryrefslogtreecommitdiff
path: root/Zend/zend_ast.c
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 /Zend/zend_ast.c
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
Diffstat (limited to 'Zend/zend_ast.c')
-rw-r--r--Zend/zend_ast.c130
1 files changed, 130 insertions, 0 deletions
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);
+}