Skip to content

Instantly share code, notes, and snippets.

@dstogov
Last active August 29, 2015 14:15
Show Gist options
  • Save dstogov/dbf2a8f46e43719bd2c2 to your computer and use it in GitHub Desktop.
Save dstogov/dbf2a8f46e43719bd2c2 to your computer and use it in GitHub Desktop.
--TEST--
001 Annotations
--FILE--
<?php
<check>
<optimization_level(2)>
<requires($a >= 0)>
<requires($b >= 0)>
<ensures($ret >= 0)>
function foo($a, $b) {
return $a + $b;
}
$r = new ReflectionFunction('foo');
var_dump($r->getAnnotations());
?>
--EXPECT--
array(4) {
["check"]=>
bool(true)
["optimization_level"]=>
int(2)
["requires"]=>
array(2) {
[0]=>
AST
[1]=>
AST
}
["ensures"]=>
AST
}
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 009d7ba..c71af8a 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -58,6 +58,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%destructor { zend_ast_destroy($$); } <ast>
%destructor { if ($$) zend_string_release($$); } <str>
+%destructor { if ($$) zend_hash_destroy($$); FREE_HASHTABLE($$); } <hash>
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
%left ','
@@ -225,14 +226,14 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%token T_POW "** (T_POW)"
%token T_POW_EQUAL "**= (T_POW_EQUAL)"
-%type <ast> top_statement namespace_name name statement function_declaration_statement
+%type <ast> top_statement namespace_name name statement annotated_statement function_declaration_statement
%type <ast> class_declaration_statement trait_declaration_statement
%type <ast> interface_declaration_statement interface_extends_list
%type <ast> use_declaration const_decl inner_statement
%type <ast> expr optional_expr while_statement for_statement foreach_variable
%type <ast> foreach_statement declare_statement finally_statement unset_variable variable
%type <ast> extends_from parameter optional_type argument expr_without_variable global_var
-%type <ast> static_var class_statement trait_adaptation trait_precedence trait_alias
+%type <ast> static_var class_statement annotated_class_statement trait_adaptation trait_precedence trait_alias
%type <ast> absolute_trait_method_reference trait_method_reference property echo_expr
%type <ast> new_expr class_name class_name_reference simple_variable internal_functions_in_yacc
%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name
@@ -255,6 +256,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <str> backup_doc_comment
+%type <hash> backup_annotations
+
%% /* Rules */
start:
@@ -277,12 +280,28 @@ name:
| T_NS_SEPARATOR namespace_name { $$ = $2; $$->attr = ZEND_NAME_FQ; }
;
-top_statement:
- statement { $$ = $1; }
- | function_declaration_statement { $$ = $1; }
+
+annotation:
+ '<' T_STRING '>' { zend_add_annotation($2, NULL); }
+ | '<' T_STRING '(' expr ')' '>' { zend_add_annotation($2, $4); }
+;
+
+annotations:
+ annotations annotation
+ | annotation
+;
+
+annotated_statement:
+ function_declaration_statement { $$ = $1; }
| class_declaration_statement { $$ = $1; }
| trait_declaration_statement { $$ = $1; }
| interface_declaration_statement { $$ = $1; }
+;
+
+top_statement:
+ statement { $$ = $1; }
+ | annotated_statement { $$ = $1; }
+ | annotations annotated_statement { $$ = $2; }
| T_HALT_COMPILER '(' ')' ';'
{ $$ = zend_ast_create(ZEND_AST_HALT_COMPILER,
zend_ast_create_zval_from_long(zend_get_scanned_file_offset()));
@@ -334,11 +353,9 @@ inner_statement_list:
inner_statement:
- statement { $$ = $1; }
- | function_declaration_statement { $$ = $1; }
- | class_declaration_statement { $$ = $1; }
- | trait_declaration_statement { $$ = $1; }
- | interface_declaration_statement { $$ = $1; }
+ statement { $$ = $1; }
+ | annotated_statement { $$ = $1; }
+ | annotations annotated_statement { $$ = $2; }
| T_HALT_COMPILER '(' ')' ';'
{ $$ = NULL; zend_error_noreturn(E_COMPILE_ERROR,
"__HALT_COMPILER() can only be used from the outermost scope"); }
@@ -406,9 +423,9 @@ unset_variable:
function_declaration_statement:
function returns_ref T_STRING '(' parameter_list ')' return_type
- backup_doc_comment '{' inner_statement_list '}'
- { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2, $1, $8,
- zend_ast_get_str($3), $5, NULL, $10, $7); }
+ backup_doc_comment backup_annotations '{' inner_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2, $1, $8, $9,
+ zend_ast_get_str($3), $5, NULL, $11, $7); }
;
is_reference:
@@ -423,11 +440,11 @@ is_variadic:
class_declaration_statement:
class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); }
- T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
- { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>3, $7, zend_ast_get_str($4), $5, $6, $9, NULL); }
+ T_STRING extends_from implements_list backup_doc_comment backup_annotations '{' class_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>3, $7, $8, zend_ast_get_str($4), $5, $6, $10, NULL); }
| T_CLASS { $<num>$ = CG(zend_lineno); }
- T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
- { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>2, $6, zend_ast_get_str($3), $4, $5, $8, NULL); }
+ T_STRING extends_from implements_list backup_doc_comment backup_annotations '{' class_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>2, $6, $7, zend_ast_get_str($3), $4, $5, $9, NULL); }
;
class_modifiers:
@@ -442,14 +459,14 @@ class_modifier:
trait_declaration_statement:
T_TRAIT { $<num>$ = CG(zend_lineno); }
- T_STRING backup_doc_comment '{' class_statement_list '}'
- { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $<num>2, $4, zend_ast_get_str($3), NULL, NULL, $6, NULL); }
+ T_STRING backup_doc_comment backup_annotations '{' class_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $<num>2, $4, $5, zend_ast_get_str($3), NULL, NULL, $7, NULL); }
;
interface_declaration_statement:
T_INTERFACE { $<num>$ = CG(zend_lineno); }
- T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}'
- { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5, zend_ast_get_str($3), NULL, $4, $7, NULL); }
+ T_STRING interface_extends_list backup_doc_comment backup_annotations '{' class_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5, $6, zend_ast_get_str($3), NULL, $4, $8, NULL); }
;
extends_from:
@@ -629,18 +646,22 @@ class_statement_list:
{ $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
;
-
-class_statement:
+annotated_class_statement:
variable_modifiers property_list ';'
{ $$ = zend_ast_append_doc_comment($2); $$->attr = $1; }
+ | method_modifiers function returns_ref T_STRING '(' parameter_list ')'
+ return_type backup_doc_comment backup_annotations method_body
+ { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1, $2, $9, $10,
+ zend_ast_get_str($4), $6, NULL, $11, $8); }
+;
+
+class_statement:
+ annotated_class_statement { $$ = $1; }
+ | annotations annotated_class_statement { $$ = $2; }
| T_CONST class_const_list ';'
{ $$ = $2; RESET_DOC_COMMENT(); }
| T_USE name_list trait_adaptations
{ $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); }
- | method_modifiers function returns_ref T_STRING '(' parameter_list ')'
- return_type backup_doc_comment method_body
- { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1, $2, $9,
- zend_ast_get_str($4), $6, NULL, $10, $8); }
;
name_list:
@@ -873,15 +894,15 @@ expr_without_variable:
| T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); }
| T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); }
| function returns_ref '(' parameter_list ')' lexical_vars return_type
- backup_doc_comment '{' inner_statement_list '}'
- { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2, $1, $8,
+ backup_doc_comment backup_annotations '{' inner_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2, $1, $8, $9,
zend_string_init("{closure}", sizeof("{closure}") - 1, 0),
- $4, $6, $10, $7); }
+ $4, $6, $11, $7); }
| T_STATIC function returns_ref '(' parameter_list ')' lexical_vars
- return_type backup_doc_comment '{' inner_statement_list '}'
- { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $3 | ZEND_ACC_STATIC, $2, $9,
+ return_type backup_doc_comment backup_annotations '{' inner_statement_list '}'
+ { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $3 | ZEND_ACC_STATIC, $2, $9, $10,
zend_string_init("{closure}", sizeof("{closure}") - 1, 0),
- $5, $7, $11, $8); }
+ $5, $7, $12, $8); }
;
function:
@@ -892,6 +913,10 @@ backup_doc_comment:
/* empty */ { $$ = CG(doc_comment); CG(doc_comment) = NULL; }
;
+backup_annotations:
+ /* empty */ { $$ = CG(annotations); CG(annotations) = NULL; }
+;
+
returns_ref:
/* empty */ { $$ = 0; }
| '&' { $$ = ZEND_ACC_RETURN_REFERENCE; }
diff --git a/Zend/zend.h b/Zend/zend.h
index 9d65675..7968749 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -181,6 +181,7 @@ struct _zend_class_entry {
uint32_t line_start;
uint32_t line_end;
zend_string *doc_comment;
+ HashTable *annotations;
} user;
struct {
const struct _zend_function_entry *builtin_functions;
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 0a4c146..4501b88 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -48,6 +48,11 @@
zend_string_release(CG(doc_comment)); \
CG(doc_comment) = NULL; \
} \
+ if (CG(annotations)) { \
+ zend_hash_destroy(CG(annotations)); \
+ FREE_HASHTABLE(CG(annotations)); \
+ CG(annotations) = NULL; \
+ } \
} while (0)
typedef struct _zend_op_array zend_op_array;
@@ -119,6 +124,7 @@ static zend_always_inline znode *zend_ast_get_znode(zend_ast *ast) {
typedef union _zend_parser_stack_elem {
zend_ast *ast;
zend_string *str;
+ HashTable *hash;
zend_ulong num;
} zend_parser_stack_elem;
@@ -266,6 +272,7 @@ typedef struct _zend_property_info {
uint32_t flags;
zend_string *name;
zend_string *doc_comment;
+ HashTable *annotations;
zend_class_entry *ce;
} zend_property_info;
@@ -347,6 +354,7 @@ struct _zend_op_array {
uint32_t line_start;
uint32_t line_end;
zend_string *doc_comment;
+ HashTable *annotations;
uint32_t early_binding; /* the linked list of delayed declarations */
int last_literal;
@@ -649,6 +657,7 @@ zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right);
uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag);
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag);
zend_ast *zend_ast_append_doc_comment(zend_ast *list);
+void zend_add_annotation(zend_ast *name, zend_ast *value);
void zend_handle_encoding_declaration(zend_ast *ast);
/* parser-driven code generators */
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
index a9d5842..392c1f3 100644
--- a/Zend/zend_ast.h
+++ b/Zend/zend_ast.h
@@ -182,6 +182,7 @@ typedef struct _zend_ast_decl {
uint32_t flags;
unsigned char *lex_pos;
zend_string *doc_comment;
+ HashTable *annotations;
zend_string *name;
zend_ast *child[4];
} zend_ast_decl;
@@ -195,7 +196,7 @@ ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ..
ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...);
ZEND_API zend_ast *zend_ast_create_decl(
- zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
+ zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, HashTable *annotations,
zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3
);
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index abebb19..11f6f64 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -108,6 +108,7 @@ struct _zend_compiler_globals {
znode implementing_class;
zend_string *doc_comment;
+ HashTable *annotations;
uint32_t compiler_options; /* set of ZEND_COMPILE_* constants */
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index fe6ae33..6aa7633 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -3481,6 +3481,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
property_info->name = zend_new_interned_string(property_info->name);
property_info->flags = access_type;
property_info->doc_comment = doc_comment;
+ property_info->annotations = NULL; // TODO: add annotations support???
property_info->ce = ce;
zend_hash_update_ptr(&ce->properties_info, name, property_info);
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 242c99f..fee6d1f 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -66,7 +66,7 @@ ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
}
ZEND_API zend_ast *zend_ast_create_decl(
- zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
+ zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, HashTable *annotations,
zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3
) {
zend_ast_decl *ast;
@@ -79,6 +79,7 @@ ZEND_API zend_ast *zend_ast_create_decl(
ast->flags = flags;
ast->lex_pos = LANG_SCNG(yy_text);
ast->doc_comment = doc_comment;
+ ast->annotations = annotations;
ast->name = name;
ast->child[0] = child0;
ast->child[1] = child1;
@@ -394,6 +395,10 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
if (decl->doc_comment) {
zend_string_release(decl->doc_comment);
}
+ if (decl->annotations) {
+ zend_hash_destroy(decl->annotations);
+ FREE_HASHTABLE(decl->annotations);
+ }
zend_ast_destroy_ex(decl->child[0], free);
zend_ast_destroy_ex(decl->child[1], free);
zend_ast_destroy_ex(decl->child[2], free);
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 3605525..fef93fb 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -79,6 +79,10 @@ static void zend_destroy_property_info(zval *zv) /* {{{ */
if (property_info->doc_comment) {
zend_string_release(property_info->doc_comment);
}
+ if (property_info->annotations) {
+ zend_hash_destroy(property_info->annotations);
+ FREE_HASHTABLE(property_info->annotations);
+ }
}
/* }}} */
@@ -1429,6 +1433,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
} else {
ce->static_members_table = ce->default_static_members_table;
ce->info.user.doc_comment = NULL;
+ ce->info.user.annotations = NULL;
}
ce->default_properties_count = 0;
@@ -1519,10 +1524,53 @@ zend_ast *zend_ast_append_doc_comment(zend_ast *list) /* {{{ */
CG(doc_comment) = NULL;
}
+ if (CG(annotations)) {
+ // TODO: Annotations support
+ }
+
return list;
}
/* }}} */
+void zend_add_annotation(zend_ast *name, zend_ast *value) /* {{{ */
+{
+ zval *old, *val, tmp;
+ zend_string *key = zend_ast_get_str(name);
+
+ if (!CG(annotations)) {
+ ALLOC_HASHTABLE(CG(annotations));
+ zend_hash_init(CG(annotations), 8, NULL, ZVAL_PTR_DTOR, 0);
+ }
+ if (value) {
+ if (value->kind == ZEND_AST_ZVAL) {
+ val = zend_ast_get_zval(value);
+ } else {
+ ZVAL_NEW_AST(&tmp, value);
+ val = &tmp;
+ }
+ } else {
+ ZVAL_TRUE(&tmp);
+ val = &tmp;
+ }
+
+ old = zend_hash_find(CG(annotations), key);
+ if (old) {
+ zval arr;
+
+ if (Z_TYPE_P(old) != IS_ARRAY) {
+ array_init(&arr);
+ zend_hash_next_index_insert_new(Z_ARRVAL(arr), old);
+ if (Z_REFCOUNTED_P(old)) Z_ADDREF_P(old);
+ zend_hash_update(CG(annotations), key, &arr);
+ old = &arr;
+ }
+ zend_hash_next_index_insert_new(Z_ARRVAL_P(old), val);
+ } else {
+ zend_hash_add_new(CG(annotations), key, val);
+ }
+}
+/* }}} */
+
void zend_verify_namespace(void) /* {{{ */
{
if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
@@ -4269,6 +4317,9 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
if (decl->doc_comment) {
op_array->doc_comment = zend_string_copy(decl->doc_comment);
}
+ if (decl->annotations) {
+ op_array->annotations = zend_array_dup(decl->annotations);
+ }
if (decl->kind == ZEND_AST_CLOSURE) {
op_array->fn_flags |= ZEND_ACC_CLOSURE;
}
@@ -4625,6 +4676,9 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
if (decl->doc_comment) {
ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
}
+ if (decl->annotations) {
+ ce->info.user.annotations = zend_array_dup(decl->annotations);
+ }
if (extends_ast) {
if (!zend_is_const_default_class_ref(extends_ast)) {
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index 0081192..015ca90 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -178,6 +178,7 @@ void startup_scanner(void)
{
CG(parse_error) = 0;
CG(doc_comment) = NULL;
+ CG(annotations) = NULL;
zend_stack_init(&SCNG(state_stack), sizeof(int));
zend_ptr_stack_init(&SCNG(heredoc_label_stack));
}
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index c1e3adb..2f4a669 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -66,6 +66,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->function_name = NULL;
op_array->filename = zend_get_compiled_filename();
op_array->doc_comment = NULL;
+ op_array->annotations = NULL;
op_array->arg_info = NULL;
op_array->num_args = 0;
@@ -269,6 +270,10 @@ ZEND_API void destroy_zend_class(zval *zv)
if (ce->info.user.doc_comment) {
zend_string_release(ce->info.user.doc_comment);
}
+ if (ce->info.user.annotations) {
+ zend_hash_destroy(ce->info.user.annotations);
+ FREE_HASHTABLE(ce->info.user.annotations);
+ }
_destroy_zend_class_traits_info(ce);
@@ -357,6 +362,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
if (op_array->doc_comment) {
zend_string_release(op_array->doc_comment);
}
+ if (op_array->annotations) {
+ zend_hash_destroy(op_array->annotations);
+ FREE_HASHTABLE(op_array->annotations);
+ }
if (op_array->brk_cont_array) {
efree(op_array->brk_cont_array);
}
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 1f16c4d..8fe52f3 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -1837,6 +1837,25 @@ ZEND_METHOD(reflection_function, getDocComment)
}
/* }}} */
+/* {{{ proto public mixed ReflectionFunction::getAnnotations()
+ Returns the annotations for this function */
+ZEND_METHOD(reflection_function, getAnnotations)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(fptr);
+ if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.annotations) {
+ ZVAL_ARR(return_value, zend_array_dup(fptr->op_array.annotations));
+ return;
+ }
+ RETURN_NULL();
+}
+/* }}} */
+
/* {{{ proto public array ReflectionFunction::getStaticVariables()
Returns an associative array containing this function's static variables and their values */
ZEND_METHOD(reflection_function, getStaticVariables)
@@ -5741,6 +5760,7 @@ static const zend_function_entry reflection_function_abstract_functions[] = {
ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_function, getAnnotations, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getExtensionName, arginfo_reflection__void, 0)
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 5e986d45..2f9d280 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -199,6 +199,9 @@ again:
struc = Z_REFVAL_P(struc);
goto again;
break;
+ case IS_CONSTANT_AST:
+ php_printf("%sAST\n", COMMON);
+ break;
default:
php_printf("%sUNKNOWN:0\n", COMMON);
break;
@@ -361,6 +364,9 @@ again:
}
struc = Z_REFVAL_P(struc);
goto again;
+ case IS_CONSTANT_AST:
+ php_printf("%sAST\n", COMMON);
+ break;
default:
php_printf("%sUNKNOWN:0\n", COMMON);
break;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment