@@ -362,6 +362,7 @@ void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */
362
362
FC (current_namespace ) = NULL ;
363
363
FC (in_namespace ) = 0 ;
364
364
FC (has_bracketed_namespaces ) = 0 ;
365
+ FC (namespace_id ) = 0 ;
365
366
FC (declarables ).ticks = 0 ;
366
367
zend_hash_init (& FC (seen_symbols ), 8 , NULL , NULL , 0 );
367
368
}
@@ -835,6 +836,29 @@ uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
835
836
}
836
837
/* }}} */
837
838
839
+ zend_string * zend_concat6 (char * str1 , size_t str1_len , char * str2 , size_t str2_len , char * str3 , size_t str3_len , char * str4 , size_t str4_len , char * str5 , size_t str5_len , char * str6 , size_t str6_len ) /* {{{ */
840
+ {
841
+ size_t len = str1_len + str2_len + str3_len + str4_len + str5_len + str6_len ;
842
+ zend_string * res = zend_string_alloc (len , 0 );
843
+
844
+ char * ptr = ZSTR_VAL (res );
845
+ memcpy (ptr , str1 , str1_len );
846
+ ptr += str1_len ;
847
+ memcpy (ptr , str2 , str2_len );
848
+ ptr += str2_len ;
849
+ memcpy (ptr , str3 , str3_len );
850
+ ptr += str3_len ;
851
+ memcpy (ptr , str4 , str4_len );
852
+ ptr += str4_len ;
853
+ memcpy (ptr , str5 , str4_len );
854
+ ptr += str5_len ;
855
+ memcpy (ptr , str6 , str6_len );
856
+ ptr [str6_len ] = '\0' ;
857
+
858
+ return res ;
859
+ }
860
+ /* }}} */
861
+
838
862
zend_string * zend_concat3 (char * str1 , size_t str1_len , char * str2 , size_t str2_len , char * str3 , size_t str3_len ) /* {{{ */
839
863
{
840
864
size_t len = str1_len + str2_len + str3_len ;
@@ -847,11 +871,27 @@ zend_string *zend_concat3(char *str1, size_t str1_len, char *str2, size_t str2_l
847
871
848
872
return res ;
849
873
}
874
+ /* }}} */
850
875
851
876
zend_string * zend_concat_names (char * name1 , size_t name1_len , char * name2 , size_t name2_len ) {
852
877
return zend_concat3 (name1 , name1_len , "\\" , 1 , name2 , name2_len );
853
878
}
854
879
880
+ // Start with 0 byte to make this form easy to detect
881
+ zend_string * zend_prefix_with_file (zend_string * name ) {
882
+ zend_string * filename = CG (compiled_filename );
883
+ zend_string * namespace_id_str = zend_long_to_str (FC (namespace_id ));
884
+ zend_string * result = zend_concat6 (
885
+ "\0" , 1 ,
886
+ ZSTR_VAL (filename ), ZSTR_LEN (filename ),
887
+ "@" , 1 ,
888
+ ZSTR_VAL (namespace_id_str ), ZSTR_LEN (namespace_id_str ),
889
+ "\\" , 1 ,
890
+ ZSTR_VAL (name ), ZSTR_LEN (name ));
891
+ zend_string_release_ex (namespace_id_str , 0 );
892
+ return result ;
893
+ }
894
+
855
895
zend_string * zend_prefix_with_ns (zend_string * name ) {
856
896
if (FC (current_namespace )) {
857
897
zend_string * ns = FC (current_namespace );
@@ -6947,6 +6987,61 @@ void zend_compile_const_decl(zend_ast *ast) /* {{{ */
6947
6987
}
6948
6988
/* }}}*/
6949
6989
6990
+ void zend_compile_static_const_elem (zend_ast * const_ast ) { /* {{{ */
6991
+ zend_ast * name_ast = const_ast -> child [0 ];
6992
+ zend_ast * value_ast = const_ast -> child [1 ];
6993
+ zend_string * unqualified_name = zend_ast_get_str (name_ast );
6994
+
6995
+ zend_string * name ;
6996
+ znode name_node , value_node ;
6997
+ zval * value_zv = & value_node .u .constant ;
6998
+
6999
+ value_node .op_type = IS_CONST ;
7000
+
7001
+ if (zend_get_special_const (ZSTR_VAL (unqualified_name ), ZSTR_LEN (unqualified_name ))) {
7002
+ zend_error_noreturn (E_COMPILE_ERROR ,
7003
+ "Cannot redeclare static constant '%s'" , ZSTR_VAL (unqualified_name ));
7004
+ }
7005
+
7006
+ // "static const" lasts for the life of a namespace block.
7007
+ name = zend_prefix_with_file (unqualified_name );
7008
+ name = zend_new_interned_string (name );
7009
+
7010
+ if (!zend_hash_add_ptr (zend_get_import_ht (ZEND_SYMBOL_CONST ), unqualified_name , name )) {
7011
+ zend_error_noreturn (E_COMPILE_ERROR , "Cannot declare static const %s because "
7012
+ "the name is already in use" , ZSTR_VAL (unqualified_name ));
7013
+ }
7014
+
7015
+ if (0 ) {
7016
+ // FIXME implement
7017
+ // 0. Check if it can be evaluated at compile time.
7018
+ // 1. JMPNZ if defined(CONST_NAME)
7019
+ // 2. Call define(x, op1)
7020
+ // 3. End pointer
7021
+ } else {
7022
+ zend_const_expr_to_zval (value_zv , value_ast );
7023
+ zend_string_addref (name );
7024
+
7025
+ name_node .op_type = IS_CONST ;
7026
+ ZVAL_STR (& name_node .u .constant , name );
7027
+
7028
+ zend_emit_op (NULL , ZEND_DECLARE_CONST , & name_node , & value_node );
7029
+
7030
+ zend_register_seen_symbol (name , ZEND_SYMBOL_CONST );
7031
+ }
7032
+ }
7033
+ /* }}} */
7034
+
7035
+ void zend_compile_static_const_decl (zend_ast * ast ) /* {{{ */
7036
+ {
7037
+ zend_ast_list * list = zend_ast_get_list (ast );
7038
+ uint32_t i ;
7039
+ for (i = 0 ; i < list -> children ; ++ i ) {
7040
+ zend_compile_static_const_elem (list -> child [i ]);
7041
+ }
7042
+ }
7043
+ /* }}}*/
7044
+
6950
7045
void zend_compile_namespace (zend_ast * ast ) /* {{{ */
6951
7046
{
6952
7047
zend_ast * name_ast = ast -> child [0 ];
@@ -7011,6 +7106,7 @@ void zend_compile_namespace(zend_ast *ast) /* {{{ */
7011
7106
if (with_bracket ) {
7012
7107
FC (has_bracketed_namespaces ) = 1 ;
7013
7108
}
7109
+ FC (namespace_id )++ ;
7014
7110
7015
7111
if (stmt_ast ) {
7016
7112
zend_compile_top_stmt (stmt_ast );
@@ -8706,6 +8802,9 @@ void zend_compile_stmt(zend_ast *ast) /* {{{ */
8706
8802
case ZEND_AST_CONST_DECL :
8707
8803
zend_compile_const_decl (ast );
8708
8804
break ;
8805
+ case ZEND_AST_STATIC_CONST_DECL :
8806
+ zend_compile_static_const_decl (ast );
8807
+ break ;
8709
8808
case ZEND_AST_NAMESPACE :
8710
8809
zend_compile_namespace (ast );
8711
8810
break ;
0 commit comments