return ret;
}
-ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
+static size_t zend_ast_tree_size(zend_ast *ast)
{
- if (ast == NULL) {
- return NULL;
- } else if (ast->kind == ZEND_AST_ZVAL) {
- zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
+ size_t size;
+
+ if (ast->kind == ZEND_AST_ZVAL) {
+ size = sizeof(zend_ast_zval);
+ } else if (zend_ast_is_list(ast)) {
+ uint32_t i;
+ zend_ast_list *list = zend_ast_get_list(ast);
+
+ size = zend_ast_list_size(list->children);
+ for (i = 0; i < list->children; i++) {
+ if (list->child[i]) {
+ size += zend_ast_tree_size(list->child[i]);
+ }
+ }
+ } else {
+ uint32_t i, children = zend_ast_get_num_children(ast);
+
+ size = zend_ast_size(children);
+ for (i = 0; i < children; i++) {
+ if (ast->child[i]) {
+ size += zend_ast_tree_size(ast->child[i]);
+ }
+ }
+ }
+ return size;
+}
+
+static void* zend_ast_tree_copy(zend_ast *ast, void *buf)
+{
+ if (ast->kind == ZEND_AST_ZVAL) {
+ zend_ast_zval *new = (zend_ast_zval*)buf;
new->kind = ZEND_AST_ZVAL;
new->attr = ast->attr;
ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
- return (zend_ast *) new;
+ buf = (void*)((char*)buf + sizeof(zend_ast_zval));
} else if (zend_ast_is_list(ast)) {
zend_ast_list *list = zend_ast_get_list(ast);
- zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
+ zend_ast_list *new = (zend_ast_list*)buf;
uint32_t i;
new->kind = list->kind;
new->attr = list->attr;
new->children = list->children;
+ buf = (void*)((char*)buf + zend_ast_list_size(list->children));
for (i = 0; i < list->children; i++) {
- new->child[i] = zend_ast_copy(list->child[i]);
+ if (list->child[i]) {
+ new->child[i] = (zend_ast*)buf;
+ buf = zend_ast_tree_copy(list->child[i], buf);
+ } else {
+ new->child[i] = NULL;
+ }
}
- return (zend_ast *) new;
} else {
uint32_t i, children = zend_ast_get_num_children(ast);
- zend_ast *new = emalloc(zend_ast_size(children));
+ zend_ast *new = (zend_ast*)buf;
new->kind = ast->kind;
new->attr = ast->attr;
+ buf = (void*)((char*)buf + zend_ast_size(children));
for (i = 0; i < children; i++) {
- new->child[i] = zend_ast_copy(ast->child[i]);
+ if (ast->child[i]) {
+ new->child[i] = (zend_ast*)buf;
+ buf = zend_ast_tree_copy(ast->child[i], buf);
+ } else {
+ new->child[i] = NULL;
+ }
}
- return new;
}
+ return buf;
}
-static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
+ZEND_API zend_ast_ref *zend_ast_copy(zend_ast *ast)
+{
+ size_t tree_size;
+ zend_ast_ref *ref;
+
+ ZEND_ASSERT(ast != NULL);
+ tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
+ ref = emalloc(tree_size);
+ zend_ast_tree_copy(ast, GC_AST(ref));
+ GC_REFCOUNT(ref) = 1;
+ GC_TYPE_INFO(ref) = IS_CONSTANT_AST;
+ return ref;
+}
+
+ZEND_API void zend_ast_destroy(zend_ast *ast) {
if (!ast) {
return;
}
if (decl->doc_comment) {
zend_string_release(decl->doc_comment);
}
- zend_ast_destroy_ex(decl->child[0], free);
- zend_ast_destroy_ex(decl->child[1], free);
- zend_ast_destroy_ex(decl->child[2], free);
- zend_ast_destroy_ex(decl->child[3], free);
+ zend_ast_destroy(decl->child[0]);
+ zend_ast_destroy(decl->child[1]);
+ zend_ast_destroy(decl->child[2]);
+ zend_ast_destroy(decl->child[3]);
break;
}
default:
zend_ast_list *list = zend_ast_get_list(ast);
uint32_t i;
for (i = 0; i < list->children; i++) {
- zend_ast_destroy_ex(list->child[i], free);
+ zend_ast_destroy(list->child[i]);
}
} else {
uint32_t i, children = zend_ast_get_num_children(ast);
for (i = 0; i < children; i++) {
- zend_ast_destroy_ex(ast->child[i], free);
+ zend_ast_destroy(ast->child[i]);
}
}
}
-
- if (free) {
- efree(ast);
- }
-}
-
-ZEND_API void zend_ast_destroy(zend_ast *ast) {
- zend_ast_destroy_ex(ast, 0);
-}
-ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
- zend_ast_destroy_ex(ast, 1);
}
ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) {
struct _zend_ast_ref {
zend_refcounted_h gc;
- zend_ast *ast;
+ /*zend_ast ast; zend_ast follows the zend_ast_ref structure */
};
/* regular data types */
#define Z_AST(zval) (zval).value.ast
#define Z_AST_P(zval_p) Z_AST(*(zval_p))
-#define Z_ASTVAL(zval) (zval).value.ast->ast
+#define GC_AST(p) ((zend_ast*)(((char*)p) + sizeof(zend_ast_ref)))
+
+#define Z_ASTVAL(zval) GC_AST(Z_AST(zval))
#define Z_ASTVAL_P(zval_p) Z_ASTVAL(*(zval_p))
#define Z_INDIRECT(zval) (zval).value.zv
Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \
} while (0)
-#define ZVAL_NEW_AST(z, a) do { \
+#define ZVAL_AST(z, ast) do { \
zval *__z = (z); \
- zend_ast_ref *_ast = \
- (zend_ast_ref *) emalloc(sizeof(zend_ast_ref)); \
- GC_REFCOUNT(_ast) = 1; \
- GC_TYPE_INFO(_ast) = IS_CONSTANT_AST; \
- _ast->ast = (a); \
- Z_AST_P(__z) = _ast; \
+ Z_AST_P(__z) = ast; \
Z_TYPE_INFO_P(__z) = IS_CONSTANT_AST_EX; \
} while (0)