1999-04-07 18:10:10 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2014-01-03 03:08:10 +00:00
| Copyright ( c ) 1998 - 2014 Zend Technologies Ltd . ( http : //www.zend.com) |
1999-04-07 18:10:10 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2001-12-11 15:16:21 +00:00
| This source file is subject to version 2.00 of the Zend license , |
2013-01-28 02:02:51 +00:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2001-12-11 15:16:21 +00:00
| http : //www.zend.com/license/2_00.txt. |
1999-07-16 14:58:16 +00:00
| 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 . |
1999-04-07 18:10:10 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Andi Gutmans < andi @ zend . com > |
| Zeev Suraski < zeev @ zend . com > |
2014-07-27 11:25:32 +00:00
| Nikita Popov < nikic @ php . net > |
1999-04-07 18:10:10 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2003-02-01 01:49:15 +00:00
/* $Id$ */
1999-07-16 14:58:16 +00:00
2004-12-30 15:18:24 +00:00
# include <zend_language_parser.h>
1999-04-07 18:10:10 +00:00
# include "zend.h"
# include "zend_compile.h"
2003-04-10 17:02:31 +00:00
# include "zend_constants.h"
1999-04-07 18:10:10 +00:00
# include "zend_llist.h"
# include "zend_API.h"
2007-02-24 02:17:47 +00:00
# include "zend_exceptions.h"
2013-10-17 07:43:52 +00:00
# include "zend_virtual_cwd.h"
2008-06-29 08:21:35 +00:00
# include "zend_multibyte.h"
2011-01-19 21:40:15 +00:00
# include "zend_language_scanner.h"
2008-06-29 08:21:35 +00:00
2010-04-20 10:57:45 +00:00
# define CONSTANT_EX(op_array, op) \
2014-04-17 11:40:45 +00:00
( op_array ) - > literals [ op ]
2010-04-20 10:57:45 +00:00
# define CONSTANT(op) \
CONSTANT_EX ( CG ( active_op_array ) , op )
# define SET_NODE(target, src) do { \
target # # _type = ( src ) - > op_type ; \
if ( ( src ) - > op_type = = IS_CONST ) { \
2010-09-15 07:38:52 +00:00
target . constant = zend_add_literal ( CG ( active_op_array ) , & ( src ) - > u . constant TSRMLS_CC ) ; \
2010-04-20 10:57:45 +00:00
} else { \
target = ( src ) - > u . op ; \
} \
} while ( 0 )
# define GET_NODE(target, src) do { \
( target ) - > op_type = src # # _type ; \
if ( ( target ) - > op_type = = IS_CONST ) { \
( target ) - > u . constant = CONSTANT ( src . constant ) ; \
} else { \
( target ) - > u . op = src ; \
} \
} while ( 0 )
2014-08-25 19:21:16 +00:00
static inline void zend_alloc_cache_slot ( uint32_t literal TSRMLS_DC ) {
2014-08-15 15:10:06 +00:00
zend_op_array * op_array = CG ( active_op_array ) ;
Z_CACHE_SLOT ( op_array - > literals [ literal ] ) = op_array - > last_cache_slot + + ;
}
2010-05-24 14:11:39 +00:00
# define POLYMORPHIC_CACHE_SLOT_SIZE 2
2014-08-25 19:21:16 +00:00
static inline void zend_alloc_polymorphic_cache_slot ( uint32_t literal TSRMLS_DC ) {
2014-08-15 15:10:06 +00:00
zend_op_array * op_array = CG ( active_op_array ) ;
Z_CACHE_SLOT ( op_array - > literals [ literal ] ) = op_array - > last_cache_slot ;
op_array - > last_cache_slot + = POLYMORPHIC_CACHE_SLOT_SIZE ;
}
2010-05-24 14:11:39 +00:00
2001-07-28 10:51:54 +00:00
ZEND_API zend_op_array * ( * zend_compile_file ) ( zend_file_handle * file_handle , int type TSRMLS_DC ) ;
2006-06-13 12:57:48 +00:00
ZEND_API zend_op_array * ( * zend_compile_string ) ( zval * source_string , char * filename TSRMLS_DC ) ;
1999-04-07 18:10:10 +00:00
# ifndef ZTS
ZEND_API zend_compiler_globals compiler_globals ;
ZEND_API zend_executor_globals executor_globals ;
# endif
2014-07-05 12:12:20 +00:00
static zend_property_info * zend_duplicate_property_info ( zend_property_info * property_info TSRMLS_DC ) /* { { { */
2003-08-23 19:37:39 +00:00
{
2014-06-17 22:47:01 +00:00
zend_property_info * new_property_info ;
new_property_info = zend_arena_alloc ( & CG ( arena ) , sizeof ( zend_property_info ) ) ;
2014-05-26 17:29:35 +00:00
memcpy ( new_property_info , property_info , sizeof ( zend_property_info ) ) ;
2014-08-25 17:24:55 +00:00
zend_string_addref ( new_property_info - > name ) ;
2014-05-26 17:29:35 +00:00
if ( new_property_info - > doc_comment ) {
2014-08-25 17:24:55 +00:00
zend_string_addref ( new_property_info - > doc_comment ) ;
2005-04-24 17:32:05 +00:00
}
2014-05-26 17:29:35 +00:00
return new_property_info ;
2003-08-23 19:37:39 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2003-08-23 19:37:39 +00:00
2014-05-26 17:29:35 +00:00
static zend_property_info * zend_duplicate_property_info_internal ( zend_property_info * property_info ) /* { { { */
2003-08-23 19:37:39 +00:00
{
2014-05-26 17:29:35 +00:00
zend_property_info * new_property_info = pemalloc ( sizeof ( zend_property_info ) , 1 ) ;
memcpy ( new_property_info , property_info , sizeof ( zend_property_info ) ) ;
2014-08-25 17:24:55 +00:00
zend_string_addref ( new_property_info - > name ) ;
2014-05-26 17:29:35 +00:00
return new_property_info ;
2014-02-17 07:50:32 +00:00
}
/* }}} */
static void zend_destroy_property_info ( zval * zv ) /* { { { */
2003-08-23 19:37:39 +00:00
{
2014-02-17 07:50:32 +00:00
zend_property_info * property_info = Z_PTR_P ( zv ) ;
2014-08-25 17:24:55 +00:00
zend_string_release ( property_info - > name ) ;
2005-04-19 22:04:59 +00:00
if ( property_info - > doc_comment ) {
2014-08-25 17:24:55 +00:00
zend_string_release ( property_info - > doc_comment ) ;
2005-04-19 22:04:59 +00:00
}
2003-08-23 19:37:39 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2003-08-23 19:37:39 +00:00
2014-02-17 07:50:32 +00:00
static void zend_destroy_property_info_internal ( zval * zv ) /* { { { */
2003-08-23 19:37:39 +00:00
{
2014-02-17 07:50:32 +00:00
zend_property_info * property_info = Z_PTR_P ( zv ) ;
2014-08-25 17:24:55 +00:00
zend_string_release ( property_info - > name ) ;
2014-02-17 13:59:18 +00:00
free ( property_info ) ;
2003-08-23 19:37:39 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2003-08-23 19:37:39 +00:00
2014-08-29 05:05:58 +00:00
static zend_string * zend_new_interned_string_safe ( zend_string * str TSRMLS_DC ) /* { { { */ {
2014-07-24 19:35:57 +00:00
zend_string * interned_str ;
2014-08-25 19:21:16 +00:00
zend_string_addref ( str ) ;
2014-07-24 19:35:57 +00:00
interned_str = zend_new_interned_string ( str TSRMLS_CC ) ;
if ( str ! = interned_str ) {
return interned_str ;
} else {
2014-08-25 19:21:16 +00:00
zend_string_release ( str ) ;
2014-07-24 19:35:57 +00:00
return str ;
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-24 19:35:57 +00:00
2014-08-29 05:05:58 +00:00
static zend_string * zend_build_runtime_definition_key ( zend_string * name , unsigned char * lex_pos TSRMLS_DC ) /* { { { */
{
2014-07-29 18:01:11 +00:00
zend_string * result ;
2004-01-11 19:27:13 +00:00
char char_pos_buf [ 32 ] ;
2014-07-29 18:01:11 +00:00
size_t char_pos_len = zend_sprintf ( char_pos_buf , " %p " , lex_pos ) ;
1999-09-02 21:06:05 +00:00
2014-07-29 18:01:11 +00:00
const char * filename ;
2000-08-09 19:22:35 +00:00
if ( CG ( active_op_array ) - > filename ) {
2014-02-10 06:04:30 +00:00
filename = CG ( active_op_array ) - > filename - > val ;
1999-09-02 21:06:05 +00:00
} else {
filename = " - " ;
}
2004-01-11 19:27:13 +00:00
/* NULL, name length, filename length, last accepting char position length */
2014-08-25 19:21:16 +00:00
result = zend_string_alloc ( 1 + name - > len + strlen ( filename ) + char_pos_len , 0 ) ;
2010-11-24 05:41:23 +00:00
2014-07-29 18:01:11 +00:00
result - > val [ 0 ] = ' \0 ' ;
sprintf ( result - > val + 1 , " %s%s%s " , name - > val , filename , char_pos_buf ) ;
return result ;
1999-09-02 21:06:05 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-09-02 21:06:05 +00:00
2009-07-27 14:11:53 +00:00
static void init_compiler_declarables ( TSRMLS_D ) /* { { { */
2000-01-24 19:00:30 +00:00
{
2014-08-25 17:24:55 +00:00
ZVAL_LONG ( & CG ( declarables ) . ticks , 0 ) ;
2000-01-24 19:00:30 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2000-01-24 19:00:30 +00:00
2010-09-15 07:38:52 +00:00
void zend_init_compiler_context ( TSRMLS_D ) /* { { { */
{
2014-08-25 21:45:02 +00:00
CG ( context ) . opcodes_size = INITIAL_OP_ARRAY_SIZE ;
2010-09-15 07:38:52 +00:00
CG ( context ) . vars_size = 0 ;
CG ( context ) . literals_size = 0 ;
CG ( context ) . current_brk_cont = - 1 ;
CG ( context ) . backpatch_count = 0 ;
2012-12-12 22:48:51 +00:00
CG ( context ) . in_finally = 0 ;
2010-09-15 07:38:52 +00:00
CG ( context ) . labels = NULL ;
}
/* }}} */
2000-01-24 19:00:30 +00:00
2009-07-27 14:11:53 +00:00
void zend_init_compiler_data_structures ( TSRMLS_D ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-29 19:47:10 +00:00
zend_stack_init ( & CG ( loop_var_stack ) , sizeof ( znode ) ) ;
2014-08-15 15:10:06 +00:00
zend_stack_init ( & CG ( delayed_oplines_stack ) , sizeof ( zend_op ) ) ;
1999-04-07 18:10:10 +00:00
CG ( active_class_entry ) = NULL ;
2000-02-04 14:45:58 +00:00
CG ( in_compilation ) = 0 ;
2003-01-05 16:09:59 +00:00
CG ( start_lineno ) = 0 ;
2014-07-28 20:38:26 +00:00
CG ( current_namespace ) = NULL ;
2008-11-25 09:56:32 +00:00
CG ( in_namespace ) = 0 ;
CG ( has_bracketed_namespaces ) = 0 ;
2007-09-28 19:52:53 +00:00
CG ( current_import ) = NULL ;
2013-07-16 18:39:33 +00:00
CG ( current_import_function ) = NULL ;
2013-07-23 18:21:48 +00:00
CG ( current_import_const ) = NULL ;
2014-04-21 14:25:34 +00:00
zend_hash_init ( & CG ( const_filenames ) , 8 , NULL , NULL , 0 ) ;
2001-07-28 10:51:54 +00:00
init_compiler_declarables ( TSRMLS_C ) ;
2014-04-30 18:28:02 +00:00
zend_stack_init ( & CG ( context_stack ) , sizeof ( CG ( context ) ) ) ;
2008-06-29 08:21:35 +00:00
2009-11-16 22:52:00 +00:00
CG ( encoding_declared ) = 0 ;
2008-03-16 21:06:55 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2008-03-16 21:06:55 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API void file_handle_dtor ( zend_file_handle * fh ) /* { { { */
2008-03-16 21:06:55 +00:00
{
TSRMLS_FETCH ( ) ;
2003-08-11 05:24:42 +00:00
2008-03-16 21:06:55 +00:00
zend_file_handle_dtor ( fh TSRMLS_CC ) ;
2001-05-06 19:30:31 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2001-05-06 19:30:31 +00:00
2009-07-27 14:11:53 +00:00
void init_compiler ( TSRMLS_D ) /* { { { */
2001-05-06 19:30:31 +00:00
{
2014-06-17 22:47:01 +00:00
CG ( arena ) = zend_arena_create ( 64 * 1024 ) ;
2006-05-02 15:49:26 +00:00
CG ( active_op_array ) = NULL ;
2012-11-14 13:45:10 +00:00
memset ( & CG ( context ) , 0 , sizeof ( CG ( context ) ) ) ;
2001-07-28 10:51:54 +00:00
zend_init_compiler_data_structures ( TSRMLS_C ) ;
2001-07-27 10:10:39 +00:00
zend_init_rsrc_list ( TSRMLS_C ) ;
2014-04-21 14:25:34 +00:00
zend_hash_init ( & CG ( filenames_table ) , 8 , NULL , free_string_zval , 0 ) ;
2008-03-16 21:06:55 +00:00
zend_llist_init ( & CG ( open_files ) , sizeof ( zend_file_handle ) , ( void ( * ) ( void * ) ) file_handle_dtor , 0 ) ;
2001-05-06 19:30:31 +00:00
CG ( unclean_shutdown ) = 0 ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2009-07-27 14:11:53 +00:00
void shutdown_compiler ( TSRMLS_D ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-29 19:47:10 +00:00
zend_stack_destroy ( & CG ( loop_var_stack ) ) ;
2014-08-15 15:10:06 +00:00
zend_stack_destroy ( & CG ( delayed_oplines_stack ) ) ;
2000-08-19 17:50:42 +00:00
zend_hash_destroy ( & CG ( filenames_table ) ) ;
2013-08-24 21:53:43 +00:00
zend_hash_destroy ( & CG ( const_filenames ) ) ;
2010-09-15 07:38:52 +00:00
zend_stack_destroy ( & CG ( context_stack ) ) ;
2014-06-17 22:47:01 +00:00
zend_arena_destroy ( CG ( arena ) ) ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-02-10 06:04:30 +00:00
ZEND_API zend_string * zend_set_compiled_filename ( zend_string * new_compiled_filename TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-02-10 06:04:30 +00:00
zend_string * p ;
1999-04-07 18:10:10 +00:00
2014-02-10 06:04:30 +00:00
p = zend_hash_find_ptr ( & CG ( filenames_table ) , new_compiled_filename ) ;
if ( p ! = NULL ) {
CG ( compiled_filename ) = p ;
return p ;
2000-08-19 17:50:42 +00:00
}
2014-08-25 17:24:55 +00:00
p = zend_string_copy ( new_compiled_filename ) ;
2014-02-10 06:04:30 +00:00
zend_hash_update_ptr ( & CG ( filenames_table ) , new_compiled_filename , p ) ;
1999-04-07 18:10:10 +00:00
CG ( compiled_filename ) = p ;
1999-08-02 18:40:10 +00:00
return p ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-02-10 06:04:30 +00:00
ZEND_API void zend_restore_compiled_filename ( zend_string * original_compiled_filename TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
CG ( compiled_filename ) = original_compiled_filename ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-02-10 06:04:30 +00:00
ZEND_API zend_string * zend_get_compiled_filename ( TSRMLS_D ) /* { { { */
2000-02-04 14:45:58 +00:00
{
return CG ( compiled_filename ) ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
2000-02-04 14:45:58 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API int zend_get_compiled_lineno ( TSRMLS_D ) /* { { { */
2000-02-04 14:45:58 +00:00
{
return CG ( zend_lineno ) ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
2000-02-04 14:45:58 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API zend_bool zend_is_compiling ( TSRMLS_D ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2000-02-04 14:45:58 +00:00
return CG ( in_compilation ) ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-25 17:28:33 +00:00
static uint32_t get_temporary_variable ( zend_op_array * op_array ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-25 17:28:33 +00:00
return ( uint32_t ) op_array - > T + + ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-02-10 06:04:30 +00:00
static int lookup_cv ( zend_op_array * op_array , zend_string * name TSRMLS_DC ) /* { { { */ {
2004-10-04 19:54:35 +00:00
int i = 0 ;
2014-08-25 17:24:55 +00:00
zend_ulong hash_value = zend_string_hash_val ( name ) ;
2004-10-04 19:54:35 +00:00
while ( i < op_array - > last_var ) {
2014-02-10 06:04:30 +00:00
if ( op_array - > vars [ i ] - > val = = name - > val | |
( op_array - > vars [ i ] - > h = = hash_value & &
op_array - > vars [ i ] - > len = = name - > len & &
memcmp ( op_array - > vars [ i ] - > val , name - > val , name - > len ) = = 0 ) ) {
2014-08-25 17:24:55 +00:00
zend_string_release ( name ) ;
2014-07-01 02:36:19 +00:00
return ( int ) ( zend_intptr_t ) EX_VAR_NUM_2 ( NULL , i ) ;
2004-10-04 19:54:35 +00:00
}
i + + ;
}
i = op_array - > last_var ;
op_array - > last_var + + ;
2010-09-15 07:38:52 +00:00
if ( op_array - > last_var > CG ( context ) . vars_size ) {
CG ( context ) . vars_size + = 16 ; /* FIXME */
2014-02-10 06:04:30 +00:00
op_array - > vars = erealloc ( op_array - > vars , CG ( context ) . vars_size * sizeof ( zend_string * ) ) ;
2004-10-04 19:54:35 +00:00
}
2014-02-10 06:04:30 +00:00
op_array - > vars [ i ] = zend_new_interned_string ( name TSRMLS_CC ) ;
2014-07-01 02:36:19 +00:00
return ( int ) ( zend_intptr_t ) EX_VAR_NUM_2 ( NULL , i ) ;
2004-10-04 19:54:35 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2004-10-04 19:54:35 +00:00
2010-04-20 10:57:45 +00:00
void zend_del_literal ( zend_op_array * op_array , int n ) /* { { { */
{
zval_dtor ( & CONSTANT_EX ( op_array , n ) ) ;
if ( n + 1 = = op_array - > last_literal ) {
op_array - > last_literal - - ;
} else {
2014-02-10 06:04:30 +00:00
ZVAL_UNDEF ( & CONSTANT_EX ( op_array , n ) ) ;
2010-04-20 10:57:45 +00:00
}
}
/* }}} */
1999-04-07 18:10:10 +00:00
2011-08-15 09:54:06 +00:00
/* Common part of zend_add_literal and zend_append_individual_literal */
2014-02-17 21:41:23 +00:00
static inline void zend_insert_literal ( zend_op_array * op_array , zval * zv , int literal_position TSRMLS_DC ) /* { { { */
2011-08-15 09:54:06 +00:00
{
if ( Z_TYPE_P ( zv ) = = IS_STRING | | Z_TYPE_P ( zv ) = = IS_CONSTANT ) {
2014-08-25 17:24:55 +00:00
zend_string_hash_val ( Z_STR_P ( zv ) ) ;
2014-02-17 21:41:23 +00:00
Z_STR_P ( zv ) = zend_new_interned_string ( Z_STR_P ( zv ) TSRMLS_CC ) ;
2014-04-03 11:26:23 +00:00
if ( IS_INTERNED ( Z_STR_P ( zv ) ) ) {
Z_TYPE_FLAGS_P ( zv ) & = ~ ( IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE ) ;
}
2011-08-15 09:54:06 +00:00
}
2014-02-10 06:04:30 +00:00
ZVAL_COPY_VALUE ( & CONSTANT_EX ( op_array , literal_position ) , zv ) ;
2014-04-17 11:40:45 +00:00
Z_CACHE_SLOT ( op_array - > literals [ literal_position ] ) = - 1 ;
2011-08-15 09:54:06 +00:00
}
/* }}} */
/* Is used while compiling a function, using the context to keep track
of an approximate size to avoid to relocate to often .
Literals are truncated to actual size in the second compiler pass ( pass_two ( ) ) . */
2014-04-22 14:52:59 +00:00
int zend_add_literal ( zend_op_array * op_array , zval * zv TSRMLS_DC ) /* { { { */
2010-04-20 10:57:45 +00:00
{
int i = op_array - > last_literal ;
op_array - > last_literal + + ;
2010-09-15 07:38:52 +00:00
if ( i > = CG ( context ) . literals_size ) {
2011-08-15 09:54:06 +00:00
while ( i > = CG ( context ) . literals_size ) {
CG ( context ) . literals_size + = 16 ; /* FIXME */
}
2014-04-17 11:40:45 +00:00
op_array - > literals = ( zval * ) erealloc ( op_array - > literals , CG ( context ) . literals_size * sizeof ( zval ) ) ;
2010-04-20 10:57:45 +00:00
}
2011-08-15 09:54:06 +00:00
zend_insert_literal ( op_array , zv , i TSRMLS_CC ) ;
return i ;
}
/* }}} */
2010-04-20 11:05:54 +00:00
2014-04-22 14:52:59 +00:00
static int zend_add_func_name_literal ( zend_op_array * op_array , zval * zv TSRMLS_DC ) /* { { { */
2010-04-21 14:58:33 +00:00
{
int ret ;
2014-02-10 06:04:30 +00:00
zend_string * lc_name ;
2010-04-21 14:58:33 +00:00
zval c ;
2013-01-28 02:02:51 +00:00
if ( op_array - > last_literal > 0 & &
2014-04-17 11:40:45 +00:00
& op_array - > literals [ op_array - > last_literal - 1 ] = = zv & &
Z_CACHE_SLOT ( op_array - > literals [ op_array - > last_literal - 1 ] ) = = - 1 ) {
2010-04-21 14:58:33 +00:00
/* we already have function name as last literal (do nothing) */
ret = op_array - > last_literal - 1 ;
} else {
2010-09-15 07:38:52 +00:00
ret = zend_add_literal ( op_array , zv TSRMLS_CC ) ;
2010-04-21 14:58:33 +00:00
}
2013-01-28 02:02:51 +00:00
2014-08-25 17:24:55 +00:00
lc_name = zend_string_alloc ( Z_STRLEN_P ( zv ) , 0 ) ;
zend_str_tolower_copy ( lc_name - > val , Z_STRVAL_P ( zv ) , Z_STRLEN_P ( zv ) ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NEW_STR ( & c , lc_name ) ;
2014-02-10 06:04:30 +00:00
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
2010-04-21 14:58:33 +00:00
return ret ;
}
/* }}} */
2014-04-22 14:52:59 +00:00
static int zend_add_ns_func_name_literal ( zend_op_array * op_array , zval * zv TSRMLS_DC ) /* { { { */
2010-04-27 12:09:13 +00:00
{
int ret ;
2014-02-10 06:04:30 +00:00
zend_string * lc_name ;
2011-09-13 13:29:35 +00:00
const char * ns_separator ;
2010-04-27 12:09:13 +00:00
int lc_len ;
zval c ;
2013-01-28 02:02:51 +00:00
if ( op_array - > last_literal > 0 & &
2014-04-17 11:40:45 +00:00
& op_array - > literals [ op_array - > last_literal - 1 ] = = zv & &
Z_CACHE_SLOT ( op_array - > literals [ op_array - > last_literal - 1 ] ) = = - 1 ) {
2010-04-27 12:09:13 +00:00
/* we already have function name as last literal (do nothing) */
ret = op_array - > last_literal - 1 ;
} else {
2010-09-15 07:38:52 +00:00
ret = zend_add_literal ( op_array , zv TSRMLS_CC ) ;
2010-04-27 12:09:13 +00:00
}
2014-08-25 17:24:55 +00:00
lc_name = zend_string_alloc ( Z_STRLEN_P ( zv ) , 0 ) ;
zend_str_tolower_copy ( lc_name - > val , Z_STRVAL_P ( zv ) , Z_STRLEN_P ( zv ) ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NEW_STR ( & c , lc_name ) ;
2014-02-10 06:04:30 +00:00
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
2010-04-27 12:09:13 +00:00
2014-08-25 17:24:55 +00:00
ns_separator = ( const char * ) zend_memrchr ( Z_STRVAL_P ( zv ) , ' \\ ' , Z_STRLEN_P ( zv ) ) ;
2013-08-22 01:24:59 +00:00
2013-08-23 21:39:42 +00:00
if ( ns_separator ! = NULL ) {
2013-08-22 01:24:59 +00:00
ns_separator + = 1 ;
2014-08-25 17:24:55 +00:00
lc_len = Z_STRLEN_P ( zv ) - ( ns_separator - Z_STRVAL_P ( zv ) ) ;
lc_name = zend_string_alloc ( lc_len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lc_name - > val , ns_separator , lc_len ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NEW_STR ( & c , lc_name ) ;
2014-02-10 06:04:30 +00:00
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
2013-08-22 01:24:59 +00:00
}
2010-04-27 12:09:13 +00:00
return ret ;
}
/* }}} */
2010-04-21 14:58:33 +00:00
2014-08-29 05:05:58 +00:00
static int zend_add_class_name_literal ( zend_op_array * op_array , zend_string * name TSRMLS_DC ) /* { { { */ {
2010-04-21 14:58:33 +00:00
int ret ;
2014-02-10 06:04:30 +00:00
zend_string * lc_name ;
2010-04-21 14:58:33 +00:00
2014-07-19 21:30:07 +00:00
zval zv ;
ZVAL_STR ( & zv , name ) ;
2010-04-21 14:58:33 +00:00
2014-07-19 21:30:07 +00:00
ret = zend_add_literal ( op_array , & zv TSRMLS_CC ) ;
2014-08-19 10:01:54 +00:00
name = Z_STR ( zv ) ; /* Load new name string in case it was interned */
2014-07-19 21:30:07 +00:00
2014-08-25 19:21:16 +00:00
lc_name = zend_string_alloc ( name - > len , 0 ) ;
2014-07-19 21:39:51 +00:00
zend_str_tolower_copy ( lc_name - > val , name - > val , name - > len ) ;
2010-04-21 14:58:33 +00:00
2014-07-19 21:30:07 +00:00
ZVAL_NEW_STR ( & zv , lc_name ) ;
zend_add_literal ( CG ( active_op_array ) , & zv TSRMLS_CC ) ;
2010-04-21 14:58:33 +00:00
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( ret TSRMLS_CC ) ;
2010-05-24 14:11:39 +00:00
2010-04-21 14:58:33 +00:00
return ret ;
}
/* }}} */
2014-04-22 14:52:59 +00:00
static int zend_add_const_name_literal ( zend_op_array * op_array , zval * zv , int unqualified TSRMLS_DC ) /* { { { */
2010-04-22 15:03:17 +00:00
{
2014-02-10 06:04:30 +00:00
int ret ;
char * name ;
zend_string * tmp_name ;
2011-09-13 13:29:35 +00:00
const char * ns_separator ;
2010-04-22 15:03:17 +00:00
int name_len , ns_len ;
zval c ;
2013-01-28 02:02:51 +00:00
if ( op_array - > last_literal > 0 & &
2014-04-17 11:40:45 +00:00
& op_array - > literals [ op_array - > last_literal - 1 ] = = zv & &
Z_CACHE_SLOT ( op_array - > literals [ op_array - > last_literal - 1 ] ) = = - 1 ) {
2010-04-22 15:03:17 +00:00
/* we already have function name as last literal (do nothing) */
ret = op_array - > last_literal - 1 ;
} else {
2010-09-15 07:38:52 +00:00
ret = zend_add_literal ( op_array , zv TSRMLS_CC ) ;
2010-04-22 15:03:17 +00:00
}
2013-01-28 02:02:51 +00:00
/* skip leading '\\' */
2010-04-22 15:03:17 +00:00
if ( Z_STRVAL_P ( zv ) [ 0 ] = = ' \\ ' ) {
2014-08-25 17:24:55 +00:00
name_len = Z_STRLEN_P ( zv ) - 1 ;
2010-04-22 15:03:17 +00:00
name = Z_STRVAL_P ( zv ) + 1 ;
} else {
2014-08-25 17:24:55 +00:00
name_len = Z_STRLEN_P ( zv ) ;
2010-04-22 15:03:17 +00:00
name = Z_STRVAL_P ( zv ) ;
}
ns_separator = zend_memrchr ( name , ' \\ ' , name_len ) ;
if ( ns_separator ) {
ns_len = ns_separator - name ;
} else {
ns_len = 0 ;
}
if ( ns_len ) {
/* lowercased namespace name & original constant name */
2014-08-25 17:24:55 +00:00
tmp_name = zend_string_init ( name , name_len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower ( tmp_name - > val , ns_len ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NEW_STR ( & c , tmp_name ) ;
2014-02-10 06:04:30 +00:00
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
2010-04-22 15:03:17 +00:00
/* lowercased namespace name & lowercased constant name */
2014-08-25 17:24:55 +00:00
tmp_name = zend_string_alloc ( name_len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( tmp_name - > val , name , name_len ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NEW_STR ( & c , tmp_name ) ;
2014-02-10 06:04:30 +00:00
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
2010-04-22 15:03:17 +00:00
}
if ( ns_len ) {
if ( ! unqualified ) {
return ret ;
}
ns_len + + ;
name + = ns_len ;
name_len - = ns_len ;
}
/* original constant name */
2014-08-25 17:24:55 +00:00
tmp_name = zend_string_init ( name , name_len , 0 ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NEW_STR ( & c , tmp_name ) ;
2014-02-10 06:04:30 +00:00
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
2010-04-22 15:03:17 +00:00
/* lowercased constant name */
2014-08-25 17:24:55 +00:00
tmp_name = zend_string_alloc ( name_len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( tmp_name - > val , name , name_len ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NEW_STR ( & c , tmp_name ) ;
2014-02-10 06:04:30 +00:00
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
2010-04-22 15:03:17 +00:00
return ret ;
}
/* }}} */
2014-02-10 06:04:30 +00:00
# define LITERAL_STR(op, str) do { \
2010-04-20 10:57:45 +00:00
zval _c ; \
2014-02-10 06:04:30 +00:00
ZVAL_STR ( & _c , str ) ; \
op . constant = zend_add_literal ( CG ( active_op_array ) , & _c TSRMLS_CC ) ; \
} while ( 0 )
2014-07-28 13:26:30 +00:00
# define MAKE_NOP(opline) do { \
opline - > opcode = ZEND_NOP ; \
memset ( & opline - > result , 0 , sizeof ( opline - > result ) ) ; \
memset ( & opline - > op1 , 0 , sizeof ( opline - > op1 ) ) ; \
memset ( & opline - > op2 , 0 , sizeof ( opline - > op2 ) ) ; \
opline - > result_type = opline - > op1_type = opline - > op2_type = IS_UNUSED ; \
} while ( 0 )
2010-04-20 10:57:45 +00:00
2014-07-22 13:50:23 +00:00
void zend_stop_lexing ( TSRMLS_D ) {
LANG_SCNG ( yy_cursor ) = LANG_SCNG ( yy_limit ) ;
}
2010-04-21 14:58:33 +00:00
2014-07-30 16:27:41 +00:00
static inline void zend_begin_loop ( TSRMLS_D ) /* { { { */
2010-08-25 09:14:36 +00:00
{
1999-04-07 18:10:10 +00:00
zend_brk_cont_element * brk_cont_element ;
int parent ;
2010-08-25 09:14:36 +00:00
2010-09-15 07:38:52 +00:00
parent = CG ( context ) . current_brk_cont ;
CG ( context ) . current_brk_cont = CG ( active_op_array ) - > last_brk_cont ;
1999-04-07 18:10:10 +00:00
brk_cont_element = get_next_brk_cont_element ( CG ( active_op_array ) ) ;
2006-09-19 21:36:54 +00:00
brk_cont_element - > start = get_next_op_number ( CG ( active_op_array ) ) ;
1999-04-07 18:10:10 +00:00
brk_cont_element - > parent = parent ;
2010-08-25 09:14:36 +00:00
}
/* }}} */
2014-07-30 16:27:41 +00:00
static inline void zend_end_loop ( int cont_addr , int has_loop_var TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2008-02-20 12:05:57 +00:00
if ( ! has_loop_var ) {
/* The start fileld is used to free temporary variables in case of exceptions.
* We won ' t try to free something of we don ' t have loop variable .
*/
2010-09-15 07:38:52 +00:00
CG ( active_op_array ) - > brk_cont_array [ CG ( context ) . current_brk_cont ] . start = - 1 ;
2008-02-20 12:05:57 +00:00
}
2010-09-15 07:38:52 +00:00
CG ( active_op_array ) - > brk_cont_array [ CG ( context ) . current_brk_cont ] . cont = cont_addr ;
CG ( active_op_array ) - > brk_cont_array [ CG ( context ) . current_brk_cont ] . brk = get_next_op_number ( CG ( active_op_array ) ) ;
CG ( context ) . current_brk_cont = CG ( active_op_array ) - > brk_cont_array [ CG ( context ) . current_brk_cont ] . parent ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2009-07-27 14:11:53 +00:00
void zend_do_free ( znode * op1 TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
if ( op1 - > op_type = = IS_TMP_VAR ) {
2001-07-28 10:51:54 +00:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
1999-12-20 20:01:19 +00:00
opline - > opcode = ZEND_FREE ;
2010-04-20 10:57:45 +00:00
SET_NODE ( opline - > op1 , op1 ) ;
1999-12-20 20:01:19 +00:00
SET_UNUSED ( opline - > op2 ) ;
1999-07-24 11:24:19 +00:00
} else if ( op1 - > op_type = = IS_VAR ) {
1999-04-07 18:10:10 +00:00
zend_op * opline = & CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] ;
2002-03-10 13:42:37 +00:00
2003-01-27 15:13:01 +00:00
while ( opline - > opcode = = ZEND_END_SILENCE | | opline - > opcode = = ZEND_EXT_FCALL_END | | opline - > opcode = = ZEND_OP_DATA ) {
1999-12-20 20:01:19 +00:00
opline - - ;
}
2010-04-20 10:57:45 +00:00
if ( opline - > result_type = = IS_VAR
& & opline - > result . var = = op1 - > u . op . var ) {
2010-07-16 13:38:09 +00:00
if ( opline - > opcode = = ZEND_FETCH_R | |
opline - > opcode = = ZEND_FETCH_DIM_R | |
2011-10-18 19:42:42 +00:00
opline - > opcode = = ZEND_FETCH_OBJ_R | |
opline - > opcode = = ZEND_QM_ASSIGN_VAR ) {
2010-07-16 13:38:09 +00:00
/* It's very rare and useless case. It's better to use
additional FREE opcode and simplify the FETCH handlers
their selves */
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_FREE ;
SET_NODE ( opline - > op1 , op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
} else {
opline - > result_type | = EXT_TYPE_UNUSED ;
}
1999-04-07 18:10:10 +00:00
} else {
while ( opline > CG ( active_op_array ) - > opcodes ) {
2005-06-10 07:56:40 +00:00
if ( opline - > opcode = = ZEND_FETCH_DIM_R
2010-04-20 10:57:45 +00:00
& & opline - > op1_type = = IS_VAR
& & opline - > op1 . var = = op1 - > u . op . var ) {
2000-02-02 16:47:43 +00:00
/* This should the end of a list() construct
* Mark its result as unused
*/
opline - > extended_value = ZEND_FETCH_STANDARD ;
break ;
2010-04-20 10:57:45 +00:00
} else if ( opline - > result_type = = IS_VAR
& & opline - > result . var = = op1 - > u . op . var ) {
2005-06-10 07:56:40 +00:00
if ( opline - > opcode = = ZEND_NEW ) {
2010-04-20 10:57:45 +00:00
opline - > result_type | = EXT_TYPE_UNUSED ;
2014-07-22 14:55:34 +00:00
opline = & CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] ;
while ( opline - > opcode ! = ZEND_DO_FCALL | | opline - > op1 . num ! = ZEND_CALL_CTOR ) {
opline - - ;
}
opline - > op1 . num | = ZEND_CALL_CTOR_RESULT_UNUSED ;
2005-06-10 07:56:40 +00:00
}
2000-02-02 16:47:43 +00:00
break ;
1999-04-07 18:10:10 +00:00
}
opline - - ;
}
}
2000-12-18 13:28:32 +00:00
} else if ( op1 - > op_type = = IS_CONST ) {
2014-08-17 19:45:29 +00:00
/* Destroy value without using GC: When opcache moves arrays into SHM it will
* free the zend_array structure , so references to it from outside the op array
* become invalid . GC would cause such a reference in the root buffer . */
zval * zv = & op1 - > u . constant ;
if ( Z_REFCOUNTED_P ( zv ) & & ! Z_DELREF_P ( zv ) ) {
_zval_dtor_func_for_ptr ( Z_COUNTED_P ( zv ) ZEND_FILE_LINE_CC ) ;
}
2006-05-09 23:53:23 +00:00
}
2002-03-10 13:42:37 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
uint32_t zend_add_member_modifier ( uint32_t flags , uint32_t new_flag ) /* { { { */
{
2014-08-25 19:21:16 +00:00
uint32_t new_flags = flags | new_flag ;
2014-07-27 10:17:36 +00:00
if ( ( flags & ZEND_ACC_PPP_MASK ) & & ( new_flag & ZEND_ACC_PPP_MASK ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Multiple access type modifiers are not allowed " ) ;
2002-12-06 17:09:44 +00:00
}
2014-07-27 10:17:36 +00:00
if ( ( flags & ZEND_ACC_ABSTRACT ) & & ( new_flag & ZEND_ACC_ABSTRACT ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Multiple abstract modifiers are not allowed " ) ;
2007-11-13 16:52:14 +00:00
}
2014-07-27 10:17:36 +00:00
if ( ( flags & ZEND_ACC_STATIC ) & & ( new_flag & ZEND_ACC_STATIC ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Multiple static modifiers are not allowed " ) ;
2007-11-13 16:52:14 +00:00
}
2014-07-27 10:17:36 +00:00
if ( ( flags & ZEND_ACC_FINAL ) & & ( new_flag & ZEND_ACC_FINAL ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Multiple final modifiers are not allowed " ) ;
2007-11-13 16:52:14 +00:00
}
2014-07-27 10:17:36 +00:00
if ( ( new_flags & ZEND_ACC_ABSTRACT ) & & ( new_flags & ZEND_ACC_FINAL ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use the final modifier on an abstract class member " ) ;
2003-03-01 14:57:49 +00:00
}
2014-07-27 10:17:36 +00:00
return new_flags ;
2002-12-06 17:09:44 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2006-05-09 23:53:23 +00:00
2014-08-29 05:05:58 +00:00
zend_string * zend_concat3 ( char * str1 , size_t str1_len , char * str2 , size_t str2_len , char * str3 , size_t str3_len ) /* { { { */
{
2014-07-16 21:23:25 +00:00
size_t len = str1_len + str2_len + str3_len ;
2014-08-25 19:21:16 +00:00
zend_string * res = zend_string_alloc ( len , 0 ) ;
2005-06-08 15:01:35 +00:00
2014-07-16 21:23:25 +00:00
memcpy ( res - > val , str1 , str1_len ) ;
memcpy ( res - > val + str1_len , str2 , str2_len ) ;
memcpy ( res - > val + str1_len + str2_len , str3 , str3_len ) ;
2014-06-28 20:27:06 +00:00
res - > val [ len ] = ' \0 ' ;
2005-06-08 15:01:35 +00:00
2014-06-28 20:27:06 +00:00
return res ;
1999-04-07 18:10:10 +00:00
}
2014-07-16 21:23:25 +00:00
zend_string * zend_concat_names ( char * name1 , size_t name1_len , char * name2 , size_t name2_len ) {
return zend_concat3 ( name1 , name1_len , " \\ " , 1 , name2 , name2_len ) ;
}
2004-10-04 19:54:35 +00:00
2014-07-22 11:30:26 +00:00
zend_string * zend_prefix_with_ns ( zend_string * name TSRMLS_DC ) {
2014-07-28 20:38:26 +00:00
if ( CG ( current_namespace ) ) {
zend_string * ns = CG ( current_namespace ) ;
2014-07-22 11:30:26 +00:00
return zend_concat_names ( ns - > val , ns - > len , name - > val , name - > len ) ;
1999-09-20 15:44:30 +00:00
} else {
2014-08-25 19:21:16 +00:00
return zend_string_copy ( name ) ;
1999-09-20 15:44:30 +00:00
}
2014-07-22 11:30:26 +00:00
}
1999-09-20 15:44:30 +00:00
2014-07-04 22:11:00 +00:00
void * zend_hash_find_ptr_lc ( HashTable * ht , char * str , size_t len ) {
void * result ;
2014-08-25 19:21:16 +00:00
zend_string * lcname = zend_string_alloc ( len , 0 ) ;
2014-07-04 22:11:00 +00:00
zend_str_tolower_copy ( lcname - > val , str , len ) ;
result = zend_hash_find_ptr ( ht , lcname ) ;
2014-08-25 19:21:16 +00:00
zend_string_free ( lcname ) ;
2014-07-04 22:11:00 +00:00
return result ;
}
2001-08-08 17:18:16 +00:00
2014-06-28 20:27:06 +00:00
zend_string * zend_resolve_non_class_name (
2014-08-25 19:21:16 +00:00
zend_string * name , uint32_t type , zend_bool * is_fully_qualified ,
2014-06-28 20:27:06 +00:00
zend_bool case_sensitive , HashTable * current_import_sub TSRMLS_DC
) {
char * compound ;
2014-07-22 11:25:47 +00:00
* is_fully_qualified = 0 ;
2008-11-04 15:58:55 +00:00
2014-06-28 20:27:06 +00:00
if ( name - > val [ 0 ] = = ' \\ ' ) {
2014-07-04 22:11:00 +00:00
/* Remove \ prefix (only relevant if this is a string rather than a label) */
2014-08-25 19:21:16 +00:00
return zend_string_init ( name - > val + 1 , name - > len - 1 , 0 ) ;
2001-08-08 17:18:16 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-22 11:25:47 +00:00
if ( type = = ZEND_NAME_FQ ) {
* is_fully_qualified = 1 ;
2014-08-25 19:21:16 +00:00
return zend_string_copy ( name ) ;
1999-04-07 18:10:10 +00:00
}
2014-07-22 11:25:47 +00:00
if ( type = = ZEND_NAME_RELATIVE ) {
* is_fully_qualified = 1 ;
2014-07-22 11:30:26 +00:00
return zend_prefix_with_ns ( name TSRMLS_CC ) ;
2014-07-22 11:25:47 +00:00
}
1999-09-20 14:45:36 +00:00
2013-07-23 19:08:49 +00:00
if ( current_import_sub ) {
2014-07-04 22:11:00 +00:00
/* If an unqualified name is a function/const alias, replace it. */
zend_string * import_name ;
2013-08-25 14:21:51 +00:00
if ( case_sensitive ) {
2014-07-04 22:11:00 +00:00
import_name = zend_hash_find_ptr ( current_import_sub , name ) ;
2010-05-06 10:27:35 +00:00
} else {
2014-07-04 22:11:00 +00:00
import_name = zend_hash_find_ptr_lc ( current_import_sub , name - > val , name - > len ) ;
2010-05-06 10:27:35 +00:00
}
2004-10-04 19:54:35 +00:00
2014-07-04 22:11:00 +00:00
if ( import_name ) {
2014-06-28 20:27:06 +00:00
* is_fully_qualified = 1 ;
2014-08-25 19:21:16 +00:00
return zend_string_copy ( import_name ) ;
2013-07-16 18:39:33 +00:00
}
2014-06-28 20:27:06 +00:00
}
2004-10-04 19:54:35 +00:00
2014-06-28 20:27:06 +00:00
compound = memchr ( name - > val , ' \\ ' , name - > len ) ;
if ( compound ) {
* is_fully_qualified = 1 ;
2013-07-16 18:39:33 +00:00
}
2008-11-11 19:45:29 +00:00
if ( compound & & CG ( current_import ) ) {
2014-07-04 22:11:00 +00:00
/* If the first part of a qualified name is an alias, substitute it. */
2014-06-28 20:27:06 +00:00
size_t len = compound - name - > val ;
2014-07-04 22:11:00 +00:00
zend_string * import_name = zend_hash_find_ptr_lc ( CG ( current_import ) , name - > val , len ) ;
2014-06-28 20:27:06 +00:00
2014-07-04 22:11:00 +00:00
if ( import_name ) {
2014-06-28 20:27:06 +00:00
return zend_concat_names (
2014-07-04 22:11:00 +00:00
import_name - > val , import_name - > len , name - > val + len + 1 , name - > len - len - 1 ) ;
2004-10-04 19:54:35 +00:00
}
}
2008-11-04 15:58:55 +00:00
2014-07-22 11:30:26 +00:00
return zend_prefix_with_ns ( name TSRMLS_CC ) ;
2001-11-25 08:49:09 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
zend_string * zend_resolve_function_name ( zend_string * name , uint32_t type , zend_bool * is_fully_qualified TSRMLS_DC ) /* { { { */
{
2014-06-28 20:27:06 +00:00
return zend_resolve_non_class_name (
2014-07-22 11:25:47 +00:00
name , type , is_fully_qualified , 0 , CG ( current_import_function ) TSRMLS_CC ) ;
2013-07-23 19:08:49 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
zend_string * zend_resolve_const_name ( zend_string * name , uint32_t type , zend_bool * is_fully_qualified TSRMLS_DC ) /* { { { */ {
2014-06-28 20:27:06 +00:00
return zend_resolve_non_class_name (
2014-07-22 11:25:47 +00:00
name , type , is_fully_qualified , 1 , CG ( current_import_const ) TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
zend_string * zend_resolve_class_name ( zend_string * name , uint32_t type TSRMLS_DC ) /* { { { */
{
2007-09-28 19:52:53 +00:00
char * compound ;
2010-04-20 10:57:45 +00:00
2014-07-22 11:25:47 +00:00
if ( type = = ZEND_NAME_RELATIVE ) {
2014-07-22 11:30:26 +00:00
return zend_prefix_with_ns ( name TSRMLS_CC ) ;
2014-07-22 11:25:47 +00:00
}
if ( type = = ZEND_NAME_FQ | | name - > val [ 0 ] = = ' \\ ' ) {
2014-07-04 21:45:20 +00:00
/* Remove \ prefix (only relevant if this is a string rather than a label) */
if ( name - > val [ 0 ] = = ' \\ ' ) {
2014-08-25 19:21:16 +00:00
name = zend_string_init ( name - > val + 1 , name - > len - 1 , 0 ) ;
2013-01-28 02:02:51 +00:00
} else {
2014-08-25 19:21:16 +00:00
zend_string_addref ( name ) ;
2014-07-04 21:45:20 +00:00
}
/* Ensure that \self, \parent and \static are not used */
2014-07-28 13:39:43 +00:00
if ( ZEND_FETCH_CLASS_DEFAULT ! = zend_get_class_fetch_type ( name ) ) {
2014-07-04 21:45:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " ' \\ %s' is an invalid class name " , name - > val ) ;
2010-04-20 10:57:45 +00:00
}
2014-07-04 21:45:20 +00:00
return name ;
2010-04-20 10:57:45 +00:00
}
2013-01-28 02:02:51 +00:00
2014-07-04 21:45:20 +00:00
if ( CG ( current_import ) ) {
compound = memchr ( name - > val , ' \\ ' , name - > len ) ;
if ( compound ) {
/* If the first part of a qualified name is an alias, substitute it. */
size_t len = compound - name - > val ;
2014-07-04 22:11:00 +00:00
zend_string * import_name = zend_hash_find_ptr_lc ( CG ( current_import ) , name - > val , len ) ;
2014-07-04 21:45:20 +00:00
2014-07-04 22:11:00 +00:00
if ( import_name ) {
2014-07-04 21:45:20 +00:00
return zend_concat_names (
2014-07-04 22:11:00 +00:00
import_name - > val , import_name - > len , name - > val + len + 1 , name - > len - len - 1 ) ;
2007-12-03 14:15:43 +00:00
}
2014-07-04 21:45:20 +00:00
} else {
/* If an unqualified name is an alias, replace it. */
2014-07-04 22:11:00 +00:00
zend_string * import_name
= zend_hash_find_ptr_lc ( CG ( current_import ) , name - > val , name - > len ) ;
2014-07-04 21:45:20 +00:00
2014-07-04 22:11:00 +00:00
if ( import_name ) {
2014-08-25 19:21:16 +00:00
return zend_string_copy ( import_name ) ;
2007-09-28 19:52:53 +00:00
}
}
2014-07-04 21:45:20 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-04 21:45:20 +00:00
/* If not fully qualified and not an alias, prepend the current namespace */
2014-07-22 11:30:26 +00:00
return zend_prefix_with_ns ( name TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
zend_string * zend_resolve_class_name_ast ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( ast ) ;
2014-07-22 11:25:47 +00:00
return zend_resolve_class_name ( name , ast - > attr TSRMLS_CC ) ;
2000-01-29 10:16:04 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2000-01-29 10:16:04 +00:00
2014-02-19 10:35:28 +00:00
static void ptr_dtor ( zval * zv ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-02-18 21:12:05 +00:00
efree ( Z_PTR_P ( zv ) ) ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static void str_dtor ( zval * zv ) /* { { { */ {
2014-08-25 19:21:16 +00:00
zend_string_release ( Z_STR_P ( zv ) ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2008-03-28 14:35:01 +00:00
void zend_resolve_goto_label ( zend_op_array * op_array , zend_op * opline , int pass2 TSRMLS_DC ) /* { { { */
2002-11-20 18:00:23 +00:00
{
2008-03-28 14:35:01 +00:00
zend_label * dest ;
2014-08-25 19:21:16 +00:00
zend_long current , distance ;
2010-04-20 10:57:45 +00:00
zval * label ;
2003-03-05 11:14:44 +00:00
2010-04-20 10:57:45 +00:00
if ( pass2 ) {
label = opline - > op2 . zv ;
2003-03-05 11:14:44 +00:00
} else {
2010-04-20 10:57:45 +00:00
label = & CONSTANT_EX ( op_array , opline - > op2 . constant ) ;
2003-03-05 11:14:44 +00:00
}
2010-09-15 07:38:52 +00:00
if ( CG ( context ) . labels = = NULL | |
2014-02-10 06:04:30 +00:00
( dest = zend_hash_find_ptr ( CG ( context ) . labels , Z_STR_P ( label ) ) ) = = NULL ) {
2003-03-05 11:14:44 +00:00
2011-01-19 17:17:52 +00:00
if ( pass2 ) {
CG ( in_compilation ) = 1 ;
CG ( active_op_array ) = op_array ;
CG ( zend_lineno ) = opline - > lineno ;
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " 'goto' to undefined label '%s' " , Z_STRVAL_P ( label ) ) ;
2003-02-11 09:48:37 +00:00
} else {
2008-03-28 14:35:01 +00:00
/* Label is not defined. Delay to pass 2. */
return ;
2003-02-11 09:48:37 +00:00
}
}
2002-11-20 18:00:23 +00:00
2010-04-20 10:57:45 +00:00
opline - > op1 . opline_num = dest - > opline_num ;
zval_dtor ( label ) ;
2014-04-03 11:26:23 +00:00
ZVAL_NULL ( label ) ;
2004-02-04 13:56:41 +00:00
2008-03-28 14:35:01 +00:00
/* Check that we are not moving into loop or switch */
current = opline - > extended_value ;
for ( distance = 0 ; current ! = dest - > brk_cont ; distance + + ) {
if ( current = = - 1 ) {
2011-01-19 17:17:52 +00:00
if ( pass2 ) {
CG ( in_compilation ) = 1 ;
CG ( active_op_array ) = op_array ;
CG ( zend_lineno ) = opline - > lineno ;
2005-06-08 15:01:35 +00:00
}
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " 'goto' into loop or switch statement is disallowed " ) ;
2005-06-08 15:01:35 +00:00
}
2008-03-28 14:35:01 +00:00
current = op_array - > brk_cont_array [ current ] . parent ;
2002-03-10 13:42:37 +00:00
}
2005-06-08 15:01:35 +00:00
2008-03-28 14:35:01 +00:00
if ( distance = = 0 ) {
/* Nothing to break out of, optimize to ZEND_JMP */
opline - > opcode = ZEND_JMP ;
2005-05-05 17:37:25 +00:00
opline - > extended_value = 0 ;
2008-03-28 14:35:01 +00:00
SET_UNUSED ( opline - > op2 ) ;
1999-04-07 18:10:10 +00:00
} else {
2008-03-28 14:35:01 +00:00
/* Set real break distance */
2010-04-20 10:57:45 +00:00
ZVAL_LONG ( label , distance ) ;
1999-04-07 18:10:10 +00:00
}
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2013-03-27 20:03:40 +00:00
void zend_release_labels ( int temporary TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2010-09-15 07:38:52 +00:00
if ( CG ( context ) . labels ) {
zend_hash_destroy ( CG ( context ) . labels ) ;
FREE_HASHTABLE ( CG ( context ) . labels ) ;
2013-03-27 20:03:40 +00:00
CG ( context ) . labels = NULL ;
2008-03-28 14:35:01 +00:00
}
2013-03-27 20:03:40 +00:00
if ( ! temporary & & ! zend_stack_is_empty ( & CG ( context_stack ) ) ) {
2014-04-30 18:48:02 +00:00
zend_compiler_context * ctx = zend_stack_top ( & CG ( context_stack ) ) ;
2010-09-15 07:38:52 +00:00
CG ( context ) = * ctx ;
zend_stack_del_top ( & CG ( context_stack ) ) ;
2008-03-28 14:35:01 +00:00
}
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-06-07 11:06:53 +00:00
static zend_bool zend_is_call ( zend_ast * ast ) ;
1999-04-07 18:10:10 +00:00
2014-08-29 19:47:10 +00:00
static int generate_free_loop_var ( znode * var TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-29 19:47:10 +00:00
switch ( var - > op_type ) {
case IS_UNUSED :
/* Stack separator on function boundary, stop applying */
return 1 ;
case IS_VAR :
case IS_TMP_VAR :
{
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2005-06-08 15:01:35 +00:00
2014-08-29 19:47:10 +00:00
opline - > opcode = var - > op_type = = IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE ;
SET_NODE ( opline - > op1 , var ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2002-03-10 13:42:37 +00:00
}
2005-06-08 15:01:35 +00:00
1999-09-09 14:15:17 +00:00
return 0 ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-25 19:21:16 +00:00
static uint32_t zend_add_try_element ( uint32_t try_op TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-07-12 11:50:58 +00:00
zend_op_array * op_array = CG ( active_op_array ) ;
2014-08-25 19:21:16 +00:00
uint32_t try_catch_offset = op_array - > last_try_catch + + ;
2014-07-12 11:50:58 +00:00
zend_try_catch_element * elem ;
1999-04-07 18:10:10 +00:00
2014-07-12 11:50:58 +00:00
op_array - > try_catch_array = safe_erealloc (
op_array - > try_catch_array , sizeof ( zend_try_catch_element ) , op_array - > last_try_catch , 0 ) ;
1999-04-07 18:10:10 +00:00
2014-07-12 11:50:58 +00:00
elem = & op_array - > try_catch_array [ try_catch_offset ] ;
elem - > try_op = try_op ;
elem - > catch_op = 0 ;
elem - > finally_op = 0 ;
elem - > finally_end = 0 ;
2004-07-20 08:58:18 +00:00
2004-02-03 12:17:09 +00:00
return try_catch_offset ;
2001-12-16 19:45:49 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API void function_add_ref ( zend_function * function ) /* { { { */
1999-04-07 18:10:10 +00:00
{
1999-07-08 16:55:27 +00:00
if ( function - > type = = ZEND_USER_FUNCTION ) {
1999-12-23 19:23:36 +00:00
zend_op_array * op_array = & function - > op_array ;
1999-04-07 18:10:10 +00:00
1999-12-23 19:23:36 +00:00
( * op_array - > refcount ) + + ;
if ( op_array - > static_variables ) {
HashTable * static_variables = op_array - > static_variables ;
2002-03-15 15:09:46 +00:00
1999-12-27 19:07:33 +00:00
ALLOC_HASHTABLE ( op_array - > static_variables ) ;
2014-05-23 16:37:53 +00:00
zend_array_dup ( op_array - > static_variables , static_variables ) ;
2005-07-19 07:33:00 +00:00
}
2010-05-24 14:11:39 +00:00
op_array - > run_time_cache = NULL ;
2014-04-09 19:40:01 +00:00
} else if ( function - > type = = ZEND_INTERNAL_FUNCTION ) {
if ( function - > common . function_name ) {
2014-08-25 19:21:16 +00:00
zend_string_addref ( function - > common . function_name ) ;
2007-10-23 09:55:11 +00:00
}
1999-04-07 18:10:10 +00:00
}
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-07-22 14:55:34 +00:00
static void do_inherit_parent_constructor ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2011-12-05 09:20:12 +00:00
zend_function * function , * new_function ;
1999-04-07 18:10:10 +00:00
2003-05-08 15:04:43 +00:00
if ( ! ce - > parent ) {
2007-05-18 13:12:05 +00:00
return ;
}
2008-07-26 15:30:28 +00:00
2003-09-03 20:26:01 +00:00
/* You cannot change create_object */
ce - > create_object = ce - > parent - > create_object ;
1999-04-07 18:10:10 +00:00
2003-09-03 20:26:01 +00:00
/* Inherit special functions if needed */
2003-10-18 18:43:31 +00:00
if ( ! ce - > get_iterator ) {
ce - > get_iterator = ce - > parent - > get_iterator ;
1999-04-07 18:10:10 +00:00
}
2003-10-18 18:43:31 +00:00
if ( ! ce - > iterator_funcs . funcs ) {
ce - > iterator_funcs . funcs = ce - > parent - > iterator_funcs . funcs ;
}
2003-08-17 12:16:10 +00:00
if ( ! ce - > __get ) {
ce - > __get = ce - > parent - > __get ;
}
if ( ! ce - > __set ) {
ce - > __set = ce - > parent - > __set ;
}
2005-07-07 16:07:09 +00:00
if ( ! ce - > __unset ) {
ce - > __unset = ce - > parent - > __unset ;
}
if ( ! ce - > __isset ) {
ce - > __isset = ce - > parent - > __isset ;
}
2003-08-17 12:16:10 +00:00
if ( ! ce - > __call ) {
ce - > __call = ce - > parent - > __call ;
}
2007-09-29 08:52:40 +00:00
if ( ! ce - > __callstatic ) {
ce - > __callstatic = ce - > parent - > __callstatic ;
}
2006-05-09 23:53:23 +00:00
if ( ! ce - > __tostring ) {
ce - > __tostring = ce - > parent - > __tostring ;
}
2003-09-03 20:26:01 +00:00
if ( ! ce - > clone ) {
ce - > clone = ce - > parent - > clone ;
}
2005-02-23 11:15:51 +00:00
if ( ! ce - > serialize ) {
ce - > serialize = ce - > parent - > serialize ;
}
if ( ! ce - > unserialize ) {
ce - > unserialize = ce - > parent - > unserialize ;
}
2003-08-17 12:16:10 +00:00
if ( ! ce - > destructor ) {
ce - > destructor = ce - > parent - > destructor ;
}
2014-02-20 01:07:34 +00:00
if ( ! ce - > __debugInfo ) {
ce - > __debugInfo = ce - > parent - > __debugInfo ;
}
2003-09-03 21:21:18 +00:00
if ( ce - > constructor ) {
2005-12-17 15:51:52 +00:00
if ( ce - > parent - > constructor & & ce - > parent - > constructor - > common . fn_flags & ZEND_ACC_FINAL ) {
zend_error ( E_ERROR , " Cannot override final %s::%s() with %s::%s() " ,
2014-02-10 06:04:30 +00:00
ce - > parent - > name - > val , ce - > parent - > constructor - > common . function_name - > val ,
ce - > name - > val , ce - > constructor - > common . function_name - > val
2005-12-17 15:51:52 +00:00
) ;
1999-12-20 20:01:19 +00:00
}
2003-09-03 21:21:18 +00:00
return ;
2002-06-23 15:46:58 +00:00
}
2006-05-09 23:53:23 +00:00
2014-02-10 06:04:30 +00:00
if ( ( function = zend_hash_str_find_ptr ( & ce - > parent - > function_table , ZEND_CONSTRUCTOR_FUNC_NAME , sizeof ( ZEND_CONSTRUCTOR_FUNC_NAME ) - 1 ) ) ! = NULL ) {
2003-09-03 21:21:18 +00:00
/* inherit parent's constructor */
2014-02-17 13:59:18 +00:00
if ( function - > type = = ZEND_INTERNAL_FUNCTION ) {
new_function = pemalloc ( sizeof ( zend_internal_function ) , 1 ) ;
memcpy ( new_function , function , sizeof ( zend_internal_function ) ) ;
1999-04-07 18:10:10 +00:00
} else {
2014-07-22 14:55:34 +00:00
new_function = zend_arena_alloc ( & CG ( arena ) , sizeof ( zend_op_array ) ) ;
2014-02-17 13:59:18 +00:00
memcpy ( new_function , function , sizeof ( zend_op_array ) ) ;
}
zend_hash_str_update_ptr ( & ce - > function_table , ZEND_CONSTRUCTOR_FUNC_NAME , sizeof ( ZEND_CONSTRUCTOR_FUNC_NAME ) - 1 , new_function ) ;
2011-12-05 09:20:12 +00:00
function_add_ref ( new_function ) ;
2003-09-03 21:21:18 +00:00
} else {
2004-03-16 15:22:44 +00:00
/* Don't inherit the old style constructor if we already have the new style constructor */
2014-02-10 06:04:30 +00:00
zend_string * lc_class_name ;
zend_string * lc_parent_class_name ;
2014-08-25 19:21:16 +00:00
lc_class_name = zend_string_alloc ( ce - > name - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lc_class_name - > val , ce - > name - > val , ce - > name - > len ) ;
if ( ! zend_hash_exists ( & ce - > function_table , lc_class_name ) ) {
2014-08-25 19:21:16 +00:00
lc_parent_class_name = zend_string_alloc ( ce - > parent - > name - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lc_parent_class_name - > val , ce - > parent - > name - > val , ce - > parent - > name - > len ) ;
if ( ! zend_hash_exists ( & ce - > function_table , lc_parent_class_name ) & &
( function = zend_hash_find_ptr ( & ce - > parent - > function_table , lc_parent_class_name ) ) ! = NULL ) {
2004-08-26 22:25:55 +00:00
if ( function - > common . fn_flags & ZEND_ACC_CTOR ) {
/* inherit parent's constructor */
2014-02-17 13:59:18 +00:00
new_function = pemalloc ( sizeof ( zend_function ) , function - > type = = ZEND_INTERNAL_FUNCTION ) ;
memcpy ( new_function , function , sizeof ( zend_function ) ) ;
zend_hash_update_ptr ( & ce - > function_table , lc_parent_class_name , new_function ) ;
2011-12-05 09:20:12 +00:00
function_add_ref ( new_function ) ;
1999-04-07 18:10:10 +00:00
}
}
2014-08-25 19:21:16 +00:00
zend_string_release ( lc_parent_class_name ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-25 19:21:16 +00:00
zend_string_free ( lc_class_name ) ;
2006-05-09 23:53:23 +00:00
}
2003-09-03 21:21:18 +00:00
ce - > constructor = ce - > parent - > constructor ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-25 19:21:16 +00:00
char * zend_visibility_string ( uint32_t fn_flags ) /* { { { */
2002-12-06 17:09:44 +00:00
{
if ( fn_flags & ZEND_ACC_PRIVATE ) {
return " private " ;
2007-11-13 16:52:14 +00:00
}
2002-12-06 17:09:44 +00:00
if ( fn_flags & ZEND_ACC_PROTECTED ) {
return " protected " ;
2007-11-13 16:52:14 +00:00
}
2002-12-06 17:09:44 +00:00
if ( fn_flags & ZEND_ACC_PUBLIC ) {
return " public " ;
2003-03-01 14:57:49 +00:00
}
2002-12-06 17:09:44 +00:00
return " " ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
2002-12-06 17:09:44 +00:00
2014-07-22 14:55:34 +00:00
static zend_function * do_inherit_method ( zend_function * old_function TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-02-17 13:59:18 +00:00
zend_function * new_function ;
2003-03-05 11:14:44 +00:00
2014-02-17 13:59:18 +00:00
if ( old_function - > type = = ZEND_INTERNAL_FUNCTION ) {
new_function = pemalloc ( sizeof ( zend_internal_function ) , 1 ) ;
memcpy ( new_function , old_function , sizeof ( zend_internal_function ) ) ;
2003-03-05 11:14:44 +00:00
} else {
2014-07-22 14:55:34 +00:00
new_function = zend_arena_alloc ( & CG ( arena ) , sizeof ( zend_op_array ) ) ;
2014-02-17 13:59:18 +00:00
memcpy ( new_function , old_function , sizeof ( zend_op_array ) ) ;
2003-03-05 11:14:44 +00:00
}
2002-12-06 17:09:44 +00:00
/* The class entry of the derived function intentionally remains the same
* as that of the parent class . That allows us to know in which context
* we ' re running , and handle private method calls properly .
*/
2014-02-17 13:59:18 +00:00
function_add_ref ( new_function ) ;
2014-05-26 17:29:35 +00:00
return new_function ;
2002-12-06 17:09:44 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2002-12-06 17:09:44 +00:00
2011-06-13 17:52:23 +00:00
static zend_bool zend_do_perform_implementation_check ( const zend_function * fe , const zend_function * proto TSRMLS_DC ) /* { { { */
2003-03-29 11:19:38 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t i , num_args ;
2003-03-29 11:19:38 +00:00
2010-06-26 22:05:13 +00:00
/* If it's a user function then arg_info == NULL means we don't have any parameters but
* we still need to do the arg number checks . We are only willing to ignore this for internal
* functions because extensions don ' t always define arg_info .
*/
2004-02-29 18:25:50 +00:00
if ( ! proto | | ( ! proto - > common . arg_info & & proto - > common . type ! = ZEND_USER_FUNCTION ) ) {
2003-03-29 11:19:38 +00:00
return 1 ;
2006-05-09 23:53:23 +00:00
}
1999-04-07 18:10:10 +00:00
2010-06-26 22:05:13 +00:00
/* Checks for constructors only if they are declared in an interface,
* or explicitly marked as abstract
*/
if ( ( fe - > common . fn_flags & ZEND_ACC_CTOR )
& & ( ( proto - > common . scope - > ce_flags & ZEND_ACC_INTERFACE ) = = 0
& & ( proto - > common . fn_flags & ZEND_ACC_ABSTRACT ) = = 0 ) ) {
2004-04-21 08:44:37 +00:00
return 1 ;
}
1999-04-07 18:10:10 +00:00
2012-08-28 12:06:18 +00:00
/* If both methods are private do not enforce a signature */
if ( ( fe - > common . fn_flags & ZEND_ACC_PRIVATE ) & & ( proto - > common . fn_flags & ZEND_ACC_PRIVATE ) ) {
return 1 ;
}
1999-12-15 20:15:32 +00:00
2004-02-25 09:25:37 +00:00
/* check number of arguments */
2008-03-01 13:53:32 +00:00
if ( proto - > common . required_num_args < fe - > common . required_num_args
2004-02-25 09:25:37 +00:00
| | proto - > common . num_args > fe - > common . num_args ) {
return 0 ;
2010-09-15 07:38:52 +00:00
}
1999-04-07 18:10:10 +00:00
2010-11-03 15:40:24 +00:00
/* by-ref constraints on return values are covariant */
if ( ( proto - > common . fn_flags & ZEND_ACC_RETURN_REFERENCE )
& & ! ( fe - > common . fn_flags & ZEND_ACC_RETURN_REFERENCE ) ) {
2005-06-16 14:56:13 +00:00
return 0 ;
2004-02-12 13:49:55 +00:00
}
2002-03-01 14:04:51 +00:00
2013-09-26 16:39:17 +00:00
if ( ( proto - > common . fn_flags & ZEND_ACC_VARIADIC )
& & ! ( fe - > common . fn_flags & ZEND_ACC_VARIADIC ) ) {
return 0 ;
}
2003-03-19 21:17:47 +00:00
2013-09-26 16:39:17 +00:00
/* For variadic functions any additional (optional) arguments that were added must be
* checked against the signature of the variadic argument , so in this case we have to
* go through all the parameters of the function and not just those present in the
* prototype . */
num_args = proto - > common . num_args ;
2014-08-30 18:45:10 +00:00
if ( ( proto - > common . fn_flags & ZEND_ACC_VARIADIC )
2013-09-26 16:39:17 +00:00
& & fe - > common . num_args > proto - > common . num_args ) {
num_args = fe - > common . num_args ;
}
2003-02-12 16:28:34 +00:00
2013-09-26 16:39:17 +00:00
for ( i = 0 ; i < num_args ; i + + ) {
zend_arg_info * fe_arg_info = & fe - > common . arg_info [ i ] ;
2010-09-15 07:38:52 +00:00
2013-09-26 16:39:17 +00:00
zend_arg_info * proto_arg_info ;
if ( i < proto - > common . num_args ) {
proto_arg_info = & proto - > common . arg_info [ i ] ;
} else {
proto_arg_info = & proto - > common . arg_info [ proto - > common . num_args - 1 ] ;
2002-12-06 17:09:44 +00:00
}
2002-11-10 22:02:28 +00:00
2013-09-26 16:39:17 +00:00
if ( ZEND_LOG_XOR ( fe_arg_info - > class_name , proto_arg_info - > class_name ) ) {
2003-08-04 07:53:09 +00:00
/* Only one has a type hint and the other one doesn't */
return 0 ;
2003-02-12 16:28:34 +00:00
}
2013-09-26 16:39:17 +00:00
if ( fe_arg_info - > class_name ) {
2014-02-10 06:04:30 +00:00
zend_string * fe_class_name , * proto_class_name ;
2014-02-18 03:13:00 +00:00
2014-02-21 15:02:24 +00:00
if ( ! strcasecmp ( fe_arg_info - > class_name , " parent " ) & & proto - > common . scope ) {
2014-08-25 19:21:16 +00:00
fe_class_name = zend_string_copy ( proto - > common . scope - > name ) ;
2014-02-21 15:02:24 +00:00
} else if ( ! strcasecmp ( fe_arg_info - > class_name , " self " ) & & fe - > common . scope ) {
2014-08-25 19:21:16 +00:00
fe_class_name = zend_string_copy ( fe - > common . scope - > name ) ;
2012-03-02 03:32:12 +00:00
} else {
2014-08-25 19:21:16 +00:00
fe_class_name = zend_string_init (
2014-02-21 15:02:24 +00:00
fe_arg_info - > class_name ,
fe_arg_info - > class_name_len , 0 ) ;
2008-06-03 14:07:15 +00:00
}
2004-08-26 22:25:55 +00:00
2014-02-21 15:02:24 +00:00
if ( ! strcasecmp ( proto_arg_info - > class_name , " parent " ) & & proto - > common . scope & & proto - > common . scope - > parent ) {
2014-08-25 19:21:16 +00:00
proto_class_name = zend_string_copy ( proto - > common . scope - > parent - > name ) ;
2014-02-21 15:02:24 +00:00
} else if ( ! strcasecmp ( proto_arg_info - > class_name , " self " ) & & proto - > common . scope ) {
2014-08-25 19:21:16 +00:00
proto_class_name = zend_string_copy ( proto - > common . scope - > name ) ;
2012-03-02 03:32:12 +00:00
} else {
2014-08-25 19:21:16 +00:00
proto_class_name = zend_string_init (
2014-02-21 15:02:24 +00:00
proto_arg_info - > class_name ,
proto_arg_info - > class_name_len , 0 ) ;
2004-03-04 10:02:59 +00:00
}
2003-09-17 10:14:12 +00:00
2014-02-10 06:04:30 +00:00
if ( strcasecmp ( fe_class_name - > val , proto_class_name - > val ) ! = 0 ) {
2012-03-02 03:32:12 +00:00
const char * colon ;
2007-09-28 19:52:53 +00:00
2012-03-02 03:32:12 +00:00
if ( fe - > common . type ! = ZEND_USER_FUNCTION ) {
2014-08-25 19:21:16 +00:00
zend_string_release ( proto_class_name ) ;
zend_string_release ( fe_class_name ) ;
2011-06-12 21:10:31 +00:00
return 0 ;
2014-02-10 06:04:30 +00:00
} else if ( strchr ( proto_class_name - > val , ' \\ ' ) ! = NULL | |
( colon = zend_memrchr ( fe_class_name - > val , ' \\ ' , fe_class_name - > len ) ) = = NULL | |
strcasecmp ( colon + 1 , proto_class_name - > val ) ! = 0 ) {
zend_class_entry * fe_ce , * proto_ce ;
2013-08-23 21:39:42 +00:00
2014-02-10 06:04:30 +00:00
fe_ce = zend_lookup_class ( fe_class_name TSRMLS_CC ) ;
proto_ce = zend_lookup_class ( proto_class_name TSRMLS_CC ) ;
2013-08-23 21:39:42 +00:00
2012-03-02 03:32:12 +00:00
/* Check for class alias */
2014-02-10 06:04:30 +00:00
if ( ! fe_ce | | ! proto_ce | |
fe_ce - > type = = ZEND_INTERNAL_CLASS | |
proto_ce - > type = = ZEND_INTERNAL_CLASS | |
fe_ce ! = proto_ce ) {
2014-08-25 19:21:16 +00:00
zend_string_release ( proto_class_name ) ;
zend_string_release ( fe_class_name ) ;
2012-03-02 03:32:12 +00:00
return 0 ;
}
2011-06-12 21:10:31 +00:00
}
2013-08-23 21:39:42 +00:00
}
2014-08-25 19:21:16 +00:00
zend_string_release ( proto_class_name ) ;
zend_string_release ( fe_class_name ) ;
2013-01-28 02:02:51 +00:00
}
2013-09-26 16:39:17 +00:00
if ( fe_arg_info - > type_hint ! = proto_arg_info - > type_hint ) {
2010-05-20 19:18:35 +00:00
/* Incompatible type hint */
2005-05-26 13:46:17 +00:00
return 0 ;
2013-08-23 21:39:42 +00:00
}
2010-11-03 15:40:24 +00:00
/* by-ref constraints on arguments are invariant */
2013-09-26 16:39:17 +00:00
if ( fe_arg_info - > pass_by_reference ! = proto_arg_info - > pass_by_reference ) {
2003-03-29 11:19:38 +00:00
return 0 ;
}
1999-04-07 18:10:10 +00:00
}
ntroduce infrastructure for supplying information about arguments,
including:
- Whether or not to pass by ref (replaces the old arg_types, with arg_info)
- Argument name (for future use, maybe introspection)
- Class/Interface name (for type hints)
- If a class/interface name is available, whether to allow a null instance
Both user and builtin functions share the same data structures.
To declare a builtin function that expects its first arg to be an instance
of class 'Person', its second argument as a regular arg, and its third by
reference, use:
ZEND_BEGIN_ARG_INFO(my_func_arg_info, 0)
ZEND_ARG_OBJ_INFO(0, someone, Person, 1)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
and use my_func_arg_info as the arg_info parameter to the ZEND_FE() family
of macros.
The first arg to each ZEND_ARG_*() macro is whether or not to pass by ref.
The boolean arg to ZEND_BEGIN_ARG_INFO() tells the engine whether to treat
the arguments for which there's no explicit information as pass by reference
or not.
The boolean argument to ZEND_ARG_OBJ_INFO() (4th arg) is whether or not to allownull values.
2003-08-03 17:40:44 +00:00
return 1 ;
2003-03-29 11:19:38 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2011-09-23 15:08:11 +00:00
# define REALLOC_BUF_IF_EXCEED(buf, offset, length, size) \
if ( UNEXPECTED ( offset - buf + size > = length ) ) { \
length + = size + 1 ; \
buf = erealloc ( buf , length ) ; \
1999-04-07 18:10:10 +00:00
}
2006-05-09 23:53:23 +00:00
2014-07-22 14:55:34 +00:00
static char * zend_get_function_declaration ( zend_function * fptr TSRMLS_DC ) /* { { { */
2011-09-23 15:08:11 +00:00
{
char * offset , * buf ;
2014-08-25 19:21:16 +00:00
uint32_t length = 1024 ;
1999-09-09 14:15:17 +00:00
2011-09-23 15:08:11 +00:00
offset = buf = ( char * ) emalloc ( length * sizeof ( char ) ) ;
if ( fptr - > op_array . fn_flags & ZEND_ACC_RETURN_REFERENCE ) {
* ( offset + + ) = ' & ' ;
* ( offset + + ) = ' ' ;
2012-05-19 12:21:49 +00:00
}
1999-09-09 14:15:17 +00:00
2011-09-23 15:08:11 +00:00
if ( fptr - > common . scope ) {
2014-02-10 06:04:30 +00:00
memcpy ( offset , fptr - > common . scope - > name - > val , fptr - > common . scope - > name - > len ) ;
offset + = fptr - > common . scope - > name - > len ;
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' : ' ;
* ( offset + + ) = ' : ' ;
1999-09-09 14:15:17 +00:00
}
2003-04-02 16:51:49 +00:00
2011-09-23 15:08:11 +00:00
{
2014-02-10 06:04:30 +00:00
size_t name_len = fptr - > common . function_name - > len ;
2011-09-23 15:08:11 +00:00
REALLOC_BUF_IF_EXCEED ( buf , offset , length , name_len ) ;
2014-02-10 06:04:30 +00:00
memcpy ( offset , fptr - > common . function_name - > val , name_len ) ;
2011-09-23 15:08:11 +00:00
offset + = name_len ;
2003-04-02 16:51:49 +00:00
}
2008-07-14 09:49:03 +00:00
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' ( ' ;
if ( fptr - > common . arg_info ) {
2014-08-25 19:21:16 +00:00
uint32_t i , required ;
2011-09-23 15:08:11 +00:00
zend_arg_info * arg_info = fptr - > common . arg_info ;
2008-07-14 09:49:03 +00:00
2011-09-23 15:08:11 +00:00
required = fptr - > common . required_num_args ;
for ( i = 0 ; i < fptr - > common . num_args ; ) {
if ( arg_info - > class_name ) {
2014-02-21 15:02:24 +00:00
const char * class_name ;
2014-08-25 19:21:16 +00:00
uint32_t class_name_len ;
2014-02-21 15:02:24 +00:00
if ( ! strcasecmp ( arg_info - > class_name , " self " ) & & fptr - > common . scope ) {
class_name = fptr - > common . scope - > name - > val ;
class_name_len = fptr - > common . scope - > name - > len ;
} else if ( ! strcasecmp ( arg_info - > class_name , " parent " ) & & fptr - > common . scope - > parent ) {
class_name = fptr - > common . scope - > parent - > name - > val ;
class_name_len = fptr - > common . scope - > parent - > name - > len ;
2012-03-02 03:32:12 +00:00
} else {
class_name = arg_info - > class_name ;
2014-02-21 15:02:24 +00:00
class_name_len = arg_info - > class_name_len ;
2012-03-02 03:32:12 +00:00
}
2014-02-21 15:02:24 +00:00
REALLOC_BUF_IF_EXCEED ( buf , offset , length , class_name_len ) ;
memcpy ( offset , class_name , class_name_len ) ;
offset + = class_name_len ;
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' ' ;
} else if ( arg_info - > type_hint ) {
2014-08-25 19:21:16 +00:00
uint32_t type_name_len ;
2011-09-23 15:08:11 +00:00
char * type_name = zend_get_type_by_const ( arg_info - > type_hint ) ;
type_name_len = strlen ( type_name ) ;
REALLOC_BUF_IF_EXCEED ( buf , offset , length , type_name_len ) ;
memcpy ( offset , type_name , type_name_len ) ;
offset + = type_name_len ;
* ( offset + + ) = ' ' ;
}
2008-07-14 09:49:03 +00:00
2011-09-23 15:08:11 +00:00
if ( arg_info - > pass_by_reference ) {
* ( offset + + ) = ' & ' ;
}
2008-07-14 09:49:03 +00:00
2013-09-26 16:39:17 +00:00
if ( arg_info - > is_variadic ) {
* ( offset + + ) = ' . ' ;
* ( offset + + ) = ' . ' ;
* ( offset + + ) = ' . ' ;
}
2004-02-03 12:17:09 +00:00
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' $ ' ;
2004-02-03 12:17:09 +00:00
2011-09-23 15:08:11 +00:00
if ( arg_info - > name ) {
REALLOC_BUF_IF_EXCEED ( buf , offset , length , arg_info - > name_len ) ;
memcpy ( offset , arg_info - > name , arg_info - > name_len ) ;
offset + = arg_info - > name_len ;
} else {
2014-08-25 19:21:16 +00:00
uint32_t idx = i ;
2011-09-23 15:08:11 +00:00
memcpy ( offset , " param " , 5 ) ;
offset + = 5 ;
do {
* ( offset + + ) = ( char ) ( idx % 10 ) + ' 0 ' ;
idx / = 10 ;
} while ( idx > 0 ) ;
}
2013-09-26 16:39:17 +00:00
if ( i > = required & & ! arg_info - > is_variadic ) {
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' ' ;
* ( offset + + ) = ' = ' ;
* ( offset + + ) = ' ' ;
if ( fptr - > type = = ZEND_USER_FUNCTION ) {
zend_op * precv = NULL ;
{
2014-08-25 19:21:16 +00:00
uint32_t idx = i ;
2011-09-23 15:08:11 +00:00
zend_op * op = ( ( zend_op_array * ) fptr ) - > opcodes ;
zend_op * end = op + ( ( zend_op_array * ) fptr ) - > last ;
2004-08-02 08:27:57 +00:00
2011-09-23 15:08:11 +00:00
+ + idx ;
while ( op < end ) {
if ( ( op - > opcode = = ZEND_RECV | | op - > opcode = = ZEND_RECV_INIT )
2014-08-26 09:23:25 +00:00
& & op - > op1 . num = = ( zend_ulong ) idx )
2011-09-23 15:08:11 +00:00
{
precv = op ;
}
+ + op ;
}
}
if ( precv & & precv - > opcode = = ZEND_RECV_INIT & & precv - > op2_type ! = IS_UNUSED ) {
2014-07-22 14:55:34 +00:00
zval * zv = precv - > op2 . zv ;
2004-02-03 12:17:09 +00:00
2014-07-22 14:55:34 +00:00
if ( Z_TYPE_P ( zv ) = = IS_CONSTANT ) {
REALLOC_BUF_IF_EXCEED ( buf , offset , length , Z_STRLEN_P ( zv ) ) ;
memcpy ( offset , Z_STRVAL_P ( zv ) , Z_STRLEN_P ( zv ) ) ;
offset + = Z_STRLEN_P ( zv ) ;
} else if ( Z_TYPE_P ( zv ) = = IS_FALSE ) {
2014-04-30 14:32:42 +00:00
memcpy ( offset , " false " , 5 ) ;
offset + = 5 ;
2014-07-22 14:55:34 +00:00
} else if ( Z_TYPE_P ( zv ) = = IS_TRUE ) {
2014-04-30 14:32:42 +00:00
memcpy ( offset , " true " , 4 ) ;
offset + = 4 ;
2014-07-22 14:55:34 +00:00
} else if ( Z_TYPE_P ( zv ) = = IS_NULL ) {
2011-09-23 15:08:11 +00:00
memcpy ( offset , " NULL " , 4 ) ;
offset + = 4 ;
2014-07-22 14:55:34 +00:00
} else if ( Z_TYPE_P ( zv ) = = IS_STRING ) {
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' \' ' ;
2014-07-22 14:55:34 +00:00
REALLOC_BUF_IF_EXCEED ( buf , offset , length , MIN ( Z_STRLEN_P ( zv ) , 10 ) ) ;
memcpy ( offset , Z_STRVAL_P ( zv ) , MIN ( Z_STRLEN_P ( zv ) , 10 ) ) ;
offset + = MIN ( Z_STRLEN_P ( zv ) , 10 ) ;
if ( Z_STRLEN_P ( zv ) > 10 ) {
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' . ' ;
* ( offset + + ) = ' . ' ;
* ( offset + + ) = ' . ' ;
}
* ( offset + + ) = ' \' ' ;
2014-07-22 14:55:34 +00:00
} else if ( Z_TYPE_P ( zv ) = = IS_ARRAY ) {
2011-10-31 03:47:11 +00:00
memcpy ( offset , " Array " , 5 ) ;
offset + = 5 ;
2014-07-22 14:55:34 +00:00
} else if ( Z_TYPE_P ( zv ) = = IS_CONSTANT_AST ) {
memcpy ( offset , " <expression> " , 12 ) ;
offset + = 12 ;
2011-09-23 15:08:11 +00:00
} else {
2014-07-22 14:55:34 +00:00
zend_string * str = zval_get_string ( zv ) ;
2014-04-21 15:51:15 +00:00
REALLOC_BUF_IF_EXCEED ( buf , offset , length , str - > len ) ;
memcpy ( offset , str - > val , str - > len ) ;
offset + = str - > len ;
2014-08-25 19:21:16 +00:00
zend_string_release ( str ) ;
2011-09-23 15:08:11 +00:00
}
}
} else {
memcpy ( offset , " NULL " , 4 ) ;
offset + = 4 ;
}
}
2004-02-02 12:28:19 +00:00
2011-09-23 15:08:11 +00:00
if ( + + i < fptr - > common . num_args ) {
* ( offset + + ) = ' , ' ;
* ( offset + + ) = ' ' ;
}
arg_info + + ;
2011-10-31 03:47:11 +00:00
REALLOC_BUF_IF_EXCEED ( buf , offset , length , 32 ) ;
2013-01-28 02:02:51 +00:00
}
2004-02-02 12:28:19 +00:00
}
2011-09-23 15:08:11 +00:00
* ( offset + + ) = ' ) ' ;
* offset = ' \0 ' ;
2004-02-02 12:28:19 +00:00
2011-09-23 15:08:11 +00:00
return buf ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2011-09-23 15:08:11 +00:00
static void do_inheritance_check_on_method ( zend_function * child , zend_function * parent TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t child_flags ;
uint32_t parent_flags = parent - > common . fn_flags ;
1999-04-07 18:10:10 +00:00
2011-11-19 13:36:03 +00:00
if ( ( parent - > common . scope - > ce_flags & ZEND_ACC_INTERFACE ) = = 0
& & parent - > common . fn_flags & ZEND_ACC_ABSTRACT
2004-01-28 22:27:39 +00:00
& & parent - > common . scope ! = ( child - > common . prototype ? child - > common . prototype - > common . scope : child - > common . scope )
2004-01-28 10:25:45 +00:00
& & child - > common . fn_flags & ( ZEND_ACC_ABSTRACT | ZEND_ACC_IMPLEMENTED_ABSTRACT ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Can't inherit abstract function %s::%s() (previously declared abstract in %s) " ,
2014-02-21 13:35:19 +00:00
parent - > common . scope - > name - > val ,
child - > common . function_name - > val ,
child - > common . prototype ? child - > common . prototype - > common . scope - > name - > val : child - > common . scope - > name - > val ) ;
2007-05-04 06:18:53 +00:00
}
2003-02-24 12:05:58 +00:00
if ( parent_flags & ZEND_ACC_FINAL ) {
2014-02-21 13:27:53 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot override final method %s::%s() " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name - > val ) ;
2013-09-26 16:39:17 +00:00
}
2003-02-04 12:12:34 +00:00
child_flags = child - > common . fn_flags ;
2002-11-23 20:44:12 +00:00
/* You cannot change from static to non static and vice versa.
*/
2002-12-06 17:09:44 +00:00
if ( ( child_flags & ZEND_ACC_STATIC ) ! = ( parent_flags & ZEND_ACC_STATIC ) ) {
if ( child - > common . fn_flags & ZEND_ACC_STATIC ) {
2014-02-21 13:35:19 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot make non static method %s::%s() static in class %s " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name - > val , ZEND_FN_SCOPE_NAME ( child ) ) ;
2002-11-23 20:44:12 +00:00
} else {
2014-02-21 13:35:19 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot make static method %s::%s() non static in class %s " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name - > val , ZEND_FN_SCOPE_NAME ( child ) ) ;
2013-09-26 16:39:17 +00:00
}
2002-11-23 20:44:12 +00:00
}
2013-09-26 16:39:17 +00:00
2003-02-23 13:58:48 +00:00
/* Disallow making an inherited method abstract. */
2002-12-07 21:46:12 +00:00
if ( ( child_flags & ZEND_ACC_ABSTRACT ) & & ! ( parent_flags & ZEND_ACC_ABSTRACT ) ) {
2014-02-21 13:35:19 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot make non abstract method %s::%s() abstract in class %s " , ZEND_FN_SCOPE_NAME ( parent ) , child - > common . function_name - > val , ZEND_FN_SCOPE_NAME ( child ) ) ;
2013-09-26 16:39:17 +00:00
}
2003-01-02 13:58:08 +00:00
if ( parent_flags & ZEND_ACC_CHANGED ) {
child - > common . fn_flags | = ZEND_ACC_CHANGED ;
2000-02-01 16:02:38 +00:00
} else {
2003-01-02 13:58:08 +00:00
/* Prevent derived classes from restricting access that was available in parent classes
*/
if ( ( child_flags & ZEND_ACC_PPP_MASK ) > ( parent_flags & ZEND_ACC_PPP_MASK ) ) {
2014-02-21 13:35:19 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Access level to %s::%s() must be %s (as in class %s)%s " , ZEND_FN_SCOPE_NAME ( child ) , child - > common . function_name - > val , zend_visibility_string ( parent_flags ) , ZEND_FN_SCOPE_NAME ( parent ) , ( parent_flags & ZEND_ACC_PUBLIC ) ? " " : " or weaker " ) ;
2006-05-11 21:07:39 +00:00
} else if ( ( ( child_flags & ZEND_ACC_PPP_MASK ) < ( parent_flags & ZEND_ACC_PPP_MASK ) )
2003-01-02 13:58:08 +00:00
& & ( ( parent_flags & ZEND_ACC_PPP_MASK ) & ZEND_ACC_PRIVATE ) ) {
child - > common . fn_flags | = ZEND_ACC_CHANGED ;
2005-05-26 13:46:17 +00:00
}
2003-03-06 14:31:17 +00:00
}
2014-04-04 10:36:34 +00:00
2006-09-12 11:01:16 +00:00
if ( parent_flags & ZEND_ACC_PRIVATE ) {
2013-01-28 02:02:51 +00:00
child - > common . prototype = NULL ;
2006-09-12 11:01:16 +00:00
} else if ( parent_flags & ZEND_ACC_ABSTRACT ) {
2004-02-29 18:25:50 +00:00
child - > common . fn_flags | = ZEND_ACC_IMPLEMENTED_ABSTRACT ;
2004-04-21 08:44:37 +00:00
child - > common . prototype = parent ;
2006-05-30 23:10:28 +00:00
} else if ( ! ( parent - > common . fn_flags & ZEND_ACC_CTOR ) | | ( parent - > common . prototype & & ( parent - > common . prototype - > common . scope - > ce_flags & ZEND_ACC_INTERFACE ) ) ) {
2006-05-29 20:06:43 +00:00
/* ctors only have a prototype if it comes from an interface */
child - > common . prototype = parent - > common . prototype ? parent - > common . prototype : parent ;
2003-03-29 11:19:38 +00:00
}
2006-05-30 23:10:28 +00:00
if ( child - > common . prototype & & ( child - > common . prototype - > common . fn_flags & ZEND_ACC_ABSTRACT ) ) {
2011-06-13 17:52:23 +00:00
if ( ! zend_do_perform_implementation_check ( child , child - > common . prototype TSRMLS_CC ) ) {
2014-02-21 13:35:19 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Declaration of %s::%s() must be compatible with %s " , ZEND_FN_SCOPE_NAME ( child ) , child - > common . function_name - > val , zend_get_function_declaration ( child - > common . prototype TSRMLS_CC ) ) ;
2004-04-21 08:44:37 +00:00
}
2014-02-10 06:04:30 +00:00
} else if ( EG ( error_reporting ) & E_STRICT | | Z_TYPE ( EG ( user_error_handler ) ) ! = IS_UNDEF ) { /* Check E_STRICT (or custom error handler) before the check so that we save some time */
2011-06-13 17:52:23 +00:00
if ( ! zend_do_perform_implementation_check ( child , parent TSRMLS_CC ) ) {
2013-06-10 13:26:11 +00:00
char * method_prototype = zend_get_function_declaration ( parent TSRMLS_CC ) ;
2014-02-10 06:04:30 +00:00
zend_error ( E_STRICT , " Declaration of %s::%s() should be compatible with %s " , ZEND_FN_SCOPE_NAME ( child ) , child - > common . function_name - > val , method_prototype ) ;
2011-09-23 15:08:11 +00:00
efree ( method_prototype ) ;
2004-02-29 18:25:50 +00:00
}
2014-04-04 10:36:34 +00:00
}
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-05-26 17:29:35 +00:00
static zend_bool do_inherit_method_check ( HashTable * child_function_table , zend_function * parent , zend_string * key , zend_class_entry * child_ce ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t parent_flags = parent - > common . fn_flags ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
zend_function * child ;
TSRMLS_FETCH ( ) ;
2007-09-28 19:52:53 +00:00
2014-05-26 17:29:35 +00:00
if ( ( child = zend_hash_find_ptr ( child_function_table , key ) ) = = NULL ) {
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
if ( parent_flags & ( ZEND_ACC_ABSTRACT ) ) {
child_ce - > ce_flags | = ZEND_ACC_IMPLICIT_ABSTRACT_CLASS ;
}
return 1 ; /* method doesn't exist in child, copy from parent */
2013-01-28 02:02:51 +00:00
}
2008-11-11 19:45:29 +00:00
2010-04-22 23:16:15 +00:00
do_inheritance_check_on_method ( child , parent TSRMLS_CC ) ;
2014-06-30 11:43:45 +00:00
1999-07-29 12:24:58 +00:00
return 0 ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-07-22 14:55:34 +00:00
static zend_bool do_inherit_property_access_check ( HashTable * target_ht , zend_property_info * parent_info , zend_string * key , zend_class_entry * ce TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2003-02-04 12:12:34 +00:00
zend_property_info * child_info ;
zend_class_entry * parent_ce = ce - > parent ;
2002-01-04 08:07:39 +00:00
2005-06-09 17:20:44 +00:00
if ( parent_info - > flags & ( ZEND_ACC_PRIVATE | ZEND_ACC_SHADOW ) ) {
2014-05-26 17:29:35 +00:00
if ( ( child_info = zend_hash_find_ptr ( & ce - > properties_info , key ) ) ! = NULL ) {
2003-09-08 23:25:57 +00:00
child_info - > flags | = ZEND_ACC_CHANGED ;
2010-04-27 12:17:32 +00:00
} else {
2005-06-09 17:20:44 +00:00
if ( ce - > type & ZEND_INTERNAL_CLASS ) {
2014-05-26 17:29:35 +00:00
child_info = zend_duplicate_property_info_internal ( parent_info ) ;
2005-06-09 17:20:44 +00:00
} else {
2014-07-22 14:55:34 +00:00
child_info = zend_duplicate_property_info ( parent_info TSRMLS_CC ) ;
2005-06-09 17:20:44 +00:00
}
2014-05-26 17:29:35 +00:00
zend_hash_update_ptr ( & ce - > properties_info , key , child_info ) ;
2005-06-09 17:20:44 +00:00
child_info - > flags & = ~ ZEND_ACC_PRIVATE ; /* it's not private anymore */
child_info - > flags | = ZEND_ACC_SHADOW ; /* but it's a shadow of private */
2010-04-27 12:17:32 +00:00
}
2003-02-04 12:12:34 +00:00
return 0 ; /* don't copy access information to child */
2003-12-17 14:45:59 +00:00
}
2001-08-08 15:07:11 +00:00
2014-05-26 17:29:35 +00:00
if ( ( child_info = zend_hash_find_ptr ( & ce - > properties_info , key ) ) ! = NULL ) {
2003-09-03 19:28:46 +00:00
if ( ( parent_info - > flags & ZEND_ACC_STATIC ) ! = ( child_info - > flags & ZEND_ACC_STATIC ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redeclare %s%s::$%s as %s%s::$%s " ,
2014-05-26 17:29:35 +00:00
( parent_info - > flags & ZEND_ACC_STATIC ) ? " static " : " non static " , parent_ce - > name - > val , key - > val ,
( child_info - > flags & ZEND_ACC_STATIC ) ? " static " : " non static " , ce - > name - > val , key - > val ) ;
2006-05-09 23:53:23 +00:00
2003-09-03 19:28:46 +00:00
}
2004-02-02 12:28:19 +00:00
2005-06-09 17:20:44 +00:00
if ( parent_info - > flags & ZEND_ACC_CHANGED ) {
child_info - > flags | = ZEND_ACC_CHANGED ;
}
2006-05-11 21:07:39 +00:00
2003-02-04 12:12:34 +00:00
if ( ( child_info - > flags & ZEND_ACC_PPP_MASK ) > ( parent_info - > flags & ZEND_ACC_PPP_MASK ) ) {
2014-05-26 17:29:35 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Access level to %s::$%s must be %s (as in class %s)%s " , ce - > name - > val , key - > val , zend_visibility_string ( parent_info - > flags ) , parent_ce - > name - > val , ( parent_info - > flags & ZEND_ACC_PUBLIC ) ? " " : " or weaker " ) ;
2010-05-24 14:11:39 +00:00
} else if ( ( child_info - > flags & ZEND_ACC_STATIC ) = = 0 ) {
2012-12-10 12:29:51 +00:00
zval_ptr_dtor ( & ( ce - > default_properties_table [ parent_info - > offset ] ) ) ;
2010-05-24 14:11:39 +00:00
ce - > default_properties_table [ parent_info - > offset ] = ce - > default_properties_table [ child_info - > offset ] ;
2014-02-10 06:04:30 +00:00
ZVAL_UNDEF ( & ce - > default_properties_table [ child_info - > offset ] ) ;
2010-05-24 14:11:39 +00:00
child_info - > offset = parent_info - > offset ;
2003-02-04 12:12:34 +00:00
}
return 0 ; /* Don't copy from parent */
} else {
return 1 ; /* Copy from parent */
}
2004-02-02 12:28:19 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2004-02-02 12:28:19 +00:00
2009-07-27 14:11:53 +00:00
static inline void do_implement_interface ( zend_class_entry * ce , zend_class_entry * iface TSRMLS_DC ) /* { { { */
2001-08-08 15:07:11 +00:00
{
2003-12-06 19:02:12 +00:00
if ( ! ( ce - > ce_flags & ZEND_ACC_INTERFACE ) & & iface - > interface_gets_implemented & & iface - > interface_gets_implemented ( iface , ce TSRMLS_CC ) = = FAILURE ) {
2014-02-10 06:04:30 +00:00
zend_error ( E_CORE_ERROR , " Class %s could not implement interface %s " , ce - > name - > val , iface - > name - > val ) ;
2003-10-22 19:59:58 +00:00
}
2004-12-06 11:53:30 +00:00
if ( ce = = iface ) {
2014-02-10 06:04:30 +00:00
zend_error ( E_ERROR , " Interface %s cannot implement itself " , ce - > name - > val ) ;
2007-09-28 19:52:53 +00:00
}
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API void zend_do_inherit_interfaces ( zend_class_entry * ce , const zend_class_entry * iface TSRMLS_DC ) /* { { { */
2008-11-04 15:58:55 +00:00
{
2003-10-22 19:59:58 +00:00
/* expects interface to be contained in ce's interface list already */
2014-08-25 19:21:16 +00:00
uint32_t i , ce_num , if_num = iface - > num_interfaces ;
2003-10-22 19:59:58 +00:00
zend_class_entry * entry ;
2008-11-11 19:45:29 +00:00
2004-01-28 09:13:41 +00:00
if ( if_num = = 0 ) {
2008-11-11 19:45:29 +00:00
return ;
2008-11-04 15:58:55 +00:00
}
2004-01-28 09:13:41 +00:00
ce_num = ce - > num_interfaces ;
2008-11-04 15:58:55 +00:00
2004-01-28 09:13:41 +00:00
if ( ce - > type = = ZEND_INTERNAL_CLASS ) {
ce - > interfaces = ( zend_class_entry * * ) realloc ( ce - > interfaces , sizeof ( zend_class_entry * ) * ( ce_num + if_num ) ) ;
} else {
ce - > interfaces = ( zend_class_entry * * ) erealloc ( ce - > interfaces , sizeof ( zend_class_entry * ) * ( ce_num + if_num ) ) ;
2013-07-16 18:39:33 +00:00
}
2004-01-28 09:13:41 +00:00
/* Inherit the interfaces, only if they're not already inherited by the class */
while ( if_num - - ) {
entry = iface - > interfaces [ if_num ] ;
for ( i = 0 ; i < ce_num ; i + + ) {
if ( ce - > interfaces [ i ] = = entry ) {
break ;
2003-10-22 19:59:58 +00:00
}
}
2004-01-28 09:13:41 +00:00
if ( i = = ce_num ) {
ce - > interfaces [ ce - > num_interfaces + + ] = entry ;
2008-11-04 15:58:55 +00:00
}
}
2004-01-28 09:13:41 +00:00
/* and now call the implementing handlers */
while ( ce_num < ce - > num_interfaces ) {
do_implement_interface ( ce , ce - > interfaces [ ce_num + + ] TSRMLS_CC ) ;
2008-11-04 15:58:55 +00:00
}
}
2009-07-27 14:11:53 +00:00
/* }}} */
2008-11-04 15:58:55 +00:00
2010-08-11 09:38:41 +00:00
# ifdef ZTS
# define zval_property_ctor(parent_ce, ce) \
2014-04-09 13:51:28 +00:00
( ( ( parent_ce ) - > type ! = ( ce ) - > type ) ? ZVAL_COPY_CTOR : zval_add_ref )
2010-08-11 09:38:41 +00:00
# else
# define zval_property_ctor(parent_ce, ce) \
2014-02-10 06:04:30 +00:00
zval_add_ref
2010-08-11 09:38:41 +00:00
# endif
2013-07-23 19:08:49 +00:00
2014-07-22 14:55:34 +00:00
static void do_inherit_class_constant ( zend_string * name , zval * zv , zend_class_entry * ce , zend_class_entry * parent_ce TSRMLS_DC ) /* { { { */
2013-07-23 19:08:49 +00:00
{
2014-07-22 14:55:34 +00:00
if ( ! Z_ISREF_P ( zv ) ) {
if ( parent_ce - > type = = ZEND_INTERNAL_CLASS ) {
ZVAL_NEW_PERSISTENT_REF ( zv , zv ) ;
} else {
ZVAL_NEW_REF ( zv , zv ) ;
2014-04-14 09:24:43 +00:00
}
}
2014-07-22 14:55:34 +00:00
if ( Z_CONSTANT_P ( Z_REFVAL_P ( zv ) ) ) {
ce - > ce_flags & = ~ ZEND_ACC_CONSTANTS_UPDATED ;
}
if ( zend_hash_add ( & ce - > constants_table , name , zv ) ) {
Z_ADDREF_P ( zv ) ;
}
2013-07-23 19:08:49 +00:00
}
/* }}} */
2009-07-27 14:11:53 +00:00
ZEND_API void zend_do_inheritance ( zend_class_entry * ce , zend_class_entry * parent_ce TSRMLS_DC ) /* { { { */
2013-01-19 00:00:47 +00:00
{
2010-05-24 14:11:39 +00:00
zend_property_info * property_info ;
2014-05-26 17:29:35 +00:00
zend_function * func ;
zend_string * key ;
2014-07-22 14:55:34 +00:00
zval * zv ;
2013-01-19 00:00:47 +00:00
2003-03-05 11:14:44 +00:00
if ( ( ce - > ce_flags & ZEND_ACC_INTERFACE )
& & ! ( parent_ce - > ce_flags & ZEND_ACC_INTERFACE ) ) {
2014-02-21 14:23:56 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Interface %s may not inherit from class (%s) " , ce - > name - > val , parent_ce - > name - > val ) ;
2003-03-05 11:14:44 +00:00
}
2003-06-21 21:56:06 +00:00
if ( parent_ce - > ce_flags & ZEND_ACC_FINAL_CLASS ) {
2014-02-21 14:23:56 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Class %s may not inherit from final class (%s) " , ce - > name - > val , parent_ce - > name - > val ) ;
2013-01-19 00:00:47 +00:00
}
2003-02-04 12:12:34 +00:00
ce - > parent = parent_ce ;
2008-08-24 18:22:33 +00:00
/* Copy serialize/unserialize callbacks */
if ( ! ce - > serialize ) {
ce - > serialize = parent_ce - > serialize ;
}
if ( ! ce - > unserialize ) {
ce - > unserialize = parent_ce - > unserialize ;
}
2007-09-28 19:52:53 +00:00
2003-05-29 19:00:40 +00:00
/* Inherit interfaces */
2003-10-22 19:59:58 +00:00
zend_do_inherit_interfaces ( ce , parent_ce TSRMLS_CC ) ;
2000-06-09 14:40:14 +00:00
2003-02-04 12:12:34 +00:00
/* Inherit properties */
2010-05-24 14:11:39 +00:00
if ( parent_ce - > default_properties_count ) {
int i = ce - > default_properties_count + parent_ce - > default_properties_count ;
2014-02-17 07:50:32 +00:00
ce - > default_properties_table = perealloc ( ce - > default_properties_table , sizeof ( zval ) * i , ce - > type = = ZEND_INTERNAL_CLASS ) ;
2010-05-24 14:11:39 +00:00
if ( ce - > default_properties_count ) {
while ( i - - > parent_ce - > default_properties_count ) {
ce - > default_properties_table [ i ] = ce - > default_properties_table [ i - parent_ce - > default_properties_count ] ;
2008-11-04 15:58:55 +00:00
}
2010-05-24 14:11:39 +00:00
}
for ( i = 0 ; i < parent_ce - > default_properties_count ; i + + ) {
2010-08-11 09:38:41 +00:00
# ifdef ZTS
2014-04-09 13:51:28 +00:00
if ( parent_ce - > type ! = ce - > type ) {
ZVAL_DUP ( & ce - > default_properties_table [ i ] , & parent_ce - > default_properties_table [ i ] ) ;
2014-07-22 14:55:34 +00:00
if ( Z_OPT_CONSTANT ( ce - > default_properties_table [ i ] ) ) {
ce - > ce_flags & = ~ ZEND_ACC_CONSTANTS_UPDATED ;
2008-11-04 15:58:55 +00:00
}
2014-04-09 13:51:28 +00:00
continue ;
2007-12-03 14:15:43 +00:00
}
2014-04-09 13:51:28 +00:00
# endif
ZVAL_COPY ( & ce - > default_properties_table [ i ] , & parent_ce - > default_properties_table [ i ] ) ;
2014-07-22 14:55:34 +00:00
if ( Z_OPT_CONSTANT ( ce - > default_properties_table [ i ] ) ) {
ce - > ce_flags & = ~ ZEND_ACC_CONSTANTS_UPDATED ;
2007-09-28 19:52:53 +00:00
}
}
2010-05-24 14:11:39 +00:00
ce - > default_properties_count + = parent_ce - > default_properties_count ;
2007-09-28 19:52:53 +00:00
}
2001-10-29 17:19:02 +00:00
2005-09-01 10:05:32 +00:00
if ( parent_ce - > type ! = ce - > type ) {
/* User class extends internal class */
zend_update_class_constants ( parent_ce TSRMLS_CC ) ;
2010-05-24 14:11:39 +00:00
if ( parent_ce - > default_static_members_count ) {
int i = ce - > default_static_members_count + parent_ce - > default_static_members_count ;
2003-08-03 08:21:08 +00:00
2014-02-21 19:51:08 +00:00
ce - > default_static_members_table = erealloc ( ce - > default_static_members_table , sizeof ( zval ) * i ) ;
2010-05-24 14:11:39 +00:00
if ( ce - > default_static_members_count ) {
while ( i - - > parent_ce - > default_static_members_count ) {
ce - > default_static_members_table [ i ] = ce - > default_static_members_table [ i - parent_ce - > default_static_members_count ] ;
}
}
for ( i = 0 ; i < parent_ce - > default_static_members_count ; i + + ) {
2014-07-22 14:55:34 +00:00
ZVAL_MAKE_REF ( & CE_STATIC_MEMBERS ( parent_ce ) [ i ] ) ;
2010-05-24 14:11:39 +00:00
ce - > default_static_members_table [ i ] = CE_STATIC_MEMBERS ( parent_ce ) [ i ] ;
2014-02-10 06:04:30 +00:00
Z_ADDREF ( ce - > default_static_members_table [ i ] ) ;
2014-07-22 14:55:34 +00:00
if ( Z_CONSTANT_P ( Z_REFVAL ( ce - > default_static_members_table [ i ] ) ) ) {
ce - > ce_flags & = ~ ZEND_ACC_CONSTANTS_UPDATED ;
}
2010-05-24 14:11:39 +00:00
}
ce - > default_static_members_count + = parent_ce - > default_static_members_count ;
ce - > static_members_table = ce - > default_static_members_table ;
2003-03-05 13:25:33 +00:00
}
} else {
2010-05-24 14:11:39 +00:00
if ( parent_ce - > default_static_members_count ) {
int i = ce - > default_static_members_count + parent_ce - > default_static_members_count ;
2008-03-28 14:35:01 +00:00
2014-02-21 19:51:08 +00:00
ce - > default_static_members_table = perealloc ( ce - > default_static_members_table , sizeof ( zval ) * i , ce - > type = = ZEND_INTERNAL_CLASS ) ;
2010-05-24 14:11:39 +00:00
if ( ce - > default_static_members_count ) {
while ( i - - > parent_ce - > default_static_members_count ) {
ce - > default_static_members_table [ i ] = ce - > default_static_members_table [ i - parent_ce - > default_static_members_count ] ;
}
}
for ( i = 0 ; i < parent_ce - > default_static_members_count ; i + + ) {
2014-07-22 14:55:34 +00:00
ZVAL_MAKE_REF ( & parent_ce - > default_static_members_table [ i ] ) ;
2010-05-24 14:11:39 +00:00
ce - > default_static_members_table [ i ] = parent_ce - > default_static_members_table [ i ] ;
2014-02-10 06:04:30 +00:00
Z_ADDREF ( ce - > default_static_members_table [ i ] ) ;
2014-07-22 14:55:34 +00:00
if ( Z_CONSTANT_P ( Z_REFVAL ( ce - > default_static_members_table [ i ] ) ) ) {
ce - > ce_flags & = ~ ZEND_ACC_CONSTANTS_UPDATED ;
}
2010-05-24 14:11:39 +00:00
}
ce - > default_static_members_count + = parent_ce - > default_static_members_count ;
if ( ce - > type = = ZEND_USER_CLASS ) {
ce - > static_members_table = ce - > default_static_members_table ;
}
}
2008-03-28 14:35:01 +00:00
}
2014-04-18 15:18:11 +00:00
ZEND_HASH_FOREACH_PTR ( & ce - > properties_info , property_info ) {
2010-05-24 14:11:39 +00:00
if ( property_info - > ce = = ce ) {
if ( property_info - > flags & ZEND_ACC_STATIC ) {
property_info - > offset + = parent_ce - > default_static_members_count ;
} else {
property_info - > offset + = parent_ce - > default_properties_count ;
}
}
2014-04-18 15:18:11 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2008-03-28 14:35:01 +00:00
2014-05-26 17:29:35 +00:00
ZEND_HASH_FOREACH_STR_KEY_PTR ( & parent_ce - > properties_info , key , property_info ) {
2014-07-22 14:55:34 +00:00
if ( do_inherit_property_access_check ( & ce - > properties_info , property_info , key , ce TSRMLS_CC ) ) {
2014-05-26 17:29:35 +00:00
if ( ce - > type & ZEND_INTERNAL_CLASS ) {
property_info = zend_duplicate_property_info_internal ( property_info ) ;
} else {
2014-07-22 14:55:34 +00:00
property_info = zend_duplicate_property_info ( property_info TSRMLS_CC ) ;
2014-05-26 17:29:35 +00:00
}
zend_hash_add_new_ptr ( & ce - > properties_info , key , property_info ) ;
2008-03-28 14:35:01 +00:00
}
2014-05-26 17:29:35 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2008-03-28 14:35:01 +00:00
2014-07-22 14:55:34 +00:00
ZEND_HASH_FOREACH_STR_KEY_VAL ( & parent_ce - > constants_table , key , zv ) {
do_inherit_class_constant ( key , zv , ce , parent_ce TSRMLS_CC ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2008-03-28 14:35:01 +00:00
2014-05-26 17:29:35 +00:00
ZEND_HASH_FOREACH_STR_KEY_PTR ( & parent_ce - > function_table , key , func ) {
if ( do_inherit_method_check ( & ce - > function_table , func , key , ce ) ) {
2014-07-22 14:55:34 +00:00
zend_function * new_func = do_inherit_method ( func TSRMLS_CC ) ;
2014-05-26 17:29:35 +00:00
zend_hash_add_new_ptr ( & ce - > function_table , key , new_func ) ;
2008-03-28 14:35:01 +00:00
}
2014-05-26 17:29:35 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2008-03-28 14:35:01 +00:00
2014-07-22 14:55:34 +00:00
do_inherit_parent_constructor ( ce TSRMLS_CC ) ;
2008-03-28 14:35:01 +00:00
2006-05-11 21:07:39 +00:00
if ( ce - > ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS & & ce - > type = = ZEND_INTERNAL_CLASS ) {
ce - > ce_flags | = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS ;
2012-12-25 06:23:08 +00:00
} else if ( ! ( ce - > ce_flags & ( ZEND_ACC_IMPLEMENT_INTERFACES | ZEND_ACC_IMPLEMENT_TRAITS ) ) ) {
2008-03-12 09:46:42 +00:00
/* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
2006-05-11 21:07:39 +00:00
zend_verify_abstract_class ( ce TSRMLS_CC ) ;
2011-01-19 17:17:52 +00:00
}
2010-07-06 11:40:17 +00:00
ce - > ce_flags | = parent_ce - > ce_flags & ZEND_HAS_STATIC_IN_METHODS ;
2008-03-28 14:35:01 +00:00
}
/* }}} */
2014-07-22 14:55:34 +00:00
static zend_bool do_inherit_constant_check ( HashTable * child_constants_table , zval * parent_constant , zend_string * name , const zend_class_entry * iface ) /* { { { */
2008-03-28 14:35:01 +00:00
{
2014-02-10 06:04:30 +00:00
zval * old_constant ;
2008-03-28 14:35:01 +00:00
2014-07-22 14:55:34 +00:00
if ( ( old_constant = zend_hash_find ( child_constants_table , name ) ) ! = NULL ) {
2014-04-14 09:24:43 +00:00
if ( ! Z_ISREF_P ( old_constant ) | |
! Z_ISREF_P ( parent_constant ) | |
Z_REFVAL_P ( old_constant ) ! = Z_REFVAL_P ( parent_constant ) ) {
2014-07-22 14:55:34 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot inherit previously-inherited or override constant %s from interface %s " , name - > val , iface - > name - > val ) ;
2005-11-23 09:26:43 +00:00
}
2006-05-09 23:53:23 +00:00
return 0 ;
2008-03-28 14:35:01 +00:00
}
2004-01-28 11:53:52 +00:00
return 1 ;
2008-03-28 14:35:01 +00:00
}
/* }}} */
2001-11-30 16:29:47 +00:00
2014-07-22 14:55:34 +00:00
static void do_inherit_iface_constant ( zend_string * name , zval * zv , zend_class_entry * ce , zend_class_entry * iface TSRMLS_DC ) /* { { { */
2001-11-30 16:29:47 +00:00
{
2014-07-22 14:55:34 +00:00
if ( do_inherit_constant_check ( & ce - > constants_table , zv , name , iface ) ) {
ZVAL_MAKE_REF ( zv ) ;
2014-04-14 09:24:43 +00:00
Z_ADDREF_P ( zv ) ;
2014-07-22 14:55:34 +00:00
if ( Z_CONSTANT_P ( Z_REFVAL_P ( zv ) ) ) {
ce - > ce_flags & = ~ ZEND_ACC_CONSTANTS_UPDATED ;
1999-12-15 20:15:32 +00:00
}
2014-07-22 14:55:34 +00:00
zend_hash_update ( & ce - > constants_table , name , zv ) ;
2008-11-04 15:58:55 +00:00
}
2001-11-30 16:29:47 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2001-11-30 16:29:47 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API void zend_do_implement_interface ( zend_class_entry * ce , zend_class_entry * iface TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t i , ignore = 0 ;
uint32_t current_iface_num = ce - > num_interfaces ;
uint32_t parent_iface_num = ce - > parent ? ce - > parent - > num_interfaces : 0 ;
2014-05-26 17:29:35 +00:00
zend_function * func ;
zend_string * key ;
2014-07-22 14:55:34 +00:00
zval * zv ;
2004-09-16 00:40:38 +00:00
2006-06-07 09:21:06 +00:00
for ( i = 0 ; i < ce - > num_interfaces ; i + + ) {
if ( ce - > interfaces [ i ] = = NULL ) {
memmove ( ce - > interfaces + i , ce - > interfaces + i + 1 , sizeof ( zend_class_entry * ) * ( - - ce - > num_interfaces - i ) ) ;
i - - ;
} else if ( ce - > interfaces [ i ] = = iface ) {
if ( i < parent_iface_num ) {
ignore = 1 ;
} else {
2014-02-21 14:23:56 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Class %s cannot implement previously implemented interface %s " , ce - > name - > val , iface - > name - > val ) ;
2006-06-07 09:21:06 +00:00
}
}
2007-09-28 19:52:53 +00:00
}
2009-12-03 12:34:50 +00:00
if ( ignore ) {
/* Check for attempt to redeclare interface constants */
2014-07-22 14:55:34 +00:00
ZEND_HASH_FOREACH_STR_KEY_VAL ( & ce - > constants_table , key , zv ) {
do_inherit_constant_check ( & iface - > constants_table , zv , key , iface ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2010-04-21 14:58:33 +00:00
} else {
2006-06-07 09:21:06 +00:00
if ( ce - > num_interfaces > = current_iface_num ) {
if ( ce - > type = = ZEND_INTERNAL_CLASS ) {
ce - > interfaces = ( zend_class_entry * * ) realloc ( ce - > interfaces , sizeof ( zend_class_entry * ) * ( + + current_iface_num ) ) ;
} else {
ce - > interfaces = ( zend_class_entry * * ) erealloc ( ce - > interfaces , sizeof ( zend_class_entry * ) * ( + + current_iface_num ) ) ;
}
2010-05-24 14:11:39 +00:00
}
2006-06-07 09:21:06 +00:00
ce - > interfaces [ ce - > num_interfaces + + ] = iface ;
2007-09-28 19:52:53 +00:00
2014-07-22 14:55:34 +00:00
ZEND_HASH_FOREACH_STR_KEY_VAL ( & iface - > constants_table , key , zv ) {
do_inherit_iface_constant ( key , zv , ce , iface TSRMLS_CC ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2014-05-26 17:29:35 +00:00
ZEND_HASH_FOREACH_STR_KEY_PTR ( & iface - > function_table , key , func ) {
if ( do_inherit_method_check ( & ce - > function_table , func , key , ce ) ) {
2014-07-22 14:55:34 +00:00
zend_function * new_func = do_inherit_method ( func TSRMLS_CC ) ;
2014-05-26 17:29:35 +00:00
zend_hash_add_new_ptr ( & ce - > function_table , key , new_func ) ;
}
} ZEND_HASH_FOREACH_END ( ) ;
2013-01-28 02:02:51 +00:00
2006-06-07 09:21:06 +00:00
do_implement_interface ( ce , iface TSRMLS_CC ) ;
zend_do_inherit_interfaces ( ce , iface TSRMLS_CC ) ;
}
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
ZEND_API void zend_do_implement_trait ( zend_class_entry * ce , zend_class_entry * trait TSRMLS_DC ) /* { { { */
2014-07-10 20:32:18 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t i , ignore = 0 ;
uint32_t current_trait_num = ce - > num_traits ;
uint32_t parent_trait_num = ce - > parent ? ce - > parent - > num_traits : 0 ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
for ( i = 0 ; i < ce - > num_traits ; i + + ) {
if ( ce - > traits [ i ] = = NULL ) {
memmove ( ce - > traits + i , ce - > traits + i + 1 , sizeof ( zend_class_entry * ) * ( - - ce - > num_traits - i ) ) ;
i - - ;
} else if ( ce - > traits [ i ] = = trait ) {
if ( i < parent_trait_num ) {
ignore = 1 ;
}
2014-07-10 20:32:18 +00:00
}
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
if ( ! ignore ) {
if ( ce - > num_traits > = current_trait_num ) {
if ( ce - > type = = ZEND_INTERNAL_CLASS ) {
ce - > traits = ( zend_class_entry * * ) realloc ( ce - > traits , sizeof ( zend_class_entry * ) * ( + + current_trait_num ) ) ;
} else {
ce - > traits = ( zend_class_entry * * ) erealloc ( ce - > traits , sizeof ( zend_class_entry * ) * ( + + current_trait_num ) ) ;
}
}
ce - > traits [ ce - > num_traits + + ] = trait ;
}
2014-07-10 20:32:18 +00:00
}
/* }}} */
2012-03-04 18:26:11 +00:00
static zend_bool zend_traits_method_compatibility_check ( zend_function * fn , zend_function * other_fn TSRMLS_DC ) /* { { { */
2014-07-10 20:32:18 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t fn_flags = fn - > common . scope - > ce_flags ;
uint32_t other_flags = other_fn - > common . scope - > ce_flags ;
2013-01-28 02:02:51 +00:00
2012-03-04 18:26:11 +00:00
return zend_do_perform_implementation_check ( fn , other_fn TSRMLS_CC )
2013-03-19 08:48:23 +00:00
& & ( ( other_fn - > common . scope - > ce_flags & ZEND_ACC_INTERFACE ) | | zend_do_perform_implementation_check ( other_fn , fn TSRMLS_CC ) )
2013-01-28 02:02:51 +00:00
& & ( ( fn_flags & ( ZEND_ACC_FINAL | ZEND_ACC_STATIC ) ) = =
2012-12-25 06:23:08 +00:00
( other_flags & ( ZEND_ACC_FINAL | ZEND_ACC_STATIC ) ) ) ; /* equal final and static qualifier */
2014-07-10 20:32:18 +00:00
}
/* }}} */
2014-02-10 06:04:30 +00:00
static void zend_add_magic_methods ( zend_class_entry * ce , zend_string * mname , zend_function * fe TSRMLS_DC ) /* { { { */
2014-07-10 20:32:18 +00:00
{
2014-02-10 06:04:30 +00:00
if ( ! strncmp ( mname - > val , ZEND_CLONE_FUNC_NAME , mname - > len ) ) {
2011-11-02 21:12:13 +00:00
ce - > clone = fe ; fe - > common . fn_flags | = ZEND_ACC_CLONE ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_CONSTRUCTOR_FUNC_NAME , mname - > len ) ) {
2011-10-09 11:13:27 +00:00
if ( ce - > constructor ) {
2014-02-24 21:18:06 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " %s has colliding constructor definitions coming from traits " , ce - > name - > val ) ;
2014-07-10 20:32:18 +00:00
}
2013-01-28 02:02:51 +00:00
ce - > constructor = fe ; fe - > common . fn_flags | = ZEND_ACC_CTOR ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_DESTRUCTOR_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > destructor = fe ; fe - > common . fn_flags | = ZEND_ACC_DTOR ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_GET_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > __get = fe ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_SET_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > __set = fe ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_CALL_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > __call = fe ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_UNSET_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > __unset = fe ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_ISSET_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > __isset = fe ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_CALLSTATIC_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > __callstatic = fe ;
2014-02-10 06:04:30 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_TOSTRING_FUNC_NAME , mname - > len ) ) {
2011-11-18 13:56:41 +00:00
ce - > __tostring = fe ;
2014-04-25 20:32:51 +00:00
} else if ( ! strncmp ( mname - > val , ZEND_DEBUGINFO_FUNC_NAME , mname - > len ) ) {
2014-02-18 03:13:00 +00:00
ce - > __debugInfo = fe ;
2014-02-24 21:18:06 +00:00
} else if ( ce - > name - > len = = mname - > len ) {
2014-08-25 19:21:16 +00:00
zend_string * lowercase_name = zend_string_alloc ( ce - > name - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lowercase_name - > val , ce - > name - > val , ce - > name - > len ) ;
lowercase_name = zend_new_interned_string ( lowercase_name TSRMLS_CC ) ;
if ( ! memcmp ( mname - > val , lowercase_name - > val , mname - > len ) ) {
2011-10-09 11:13:27 +00:00
if ( ce - > constructor ) {
2014-02-24 21:18:06 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " %s has colliding constructor definitions coming from traits " , ce - > name - > val ) ;
2011-10-09 11:13:27 +00:00
}
ce - > constructor = fe ;
fe - > common . fn_flags | = ZEND_ACC_CTOR ;
}
2014-08-25 19:21:16 +00:00
zend_string_release ( lowercase_name ) ;
2014-07-10 20:32:18 +00:00
}
}
/* }}} */
2014-02-10 06:04:30 +00:00
static void zend_add_trait_method ( zend_class_entry * ce , const char * name , zend_string * key , zend_function * fn , HashTable * * overriden TSRMLS_DC ) /* { { { */
2014-07-11 14:52:27 +00:00
{
2012-12-25 06:23:08 +00:00
zend_function * existing_fn = NULL ;
2014-07-22 14:55:34 +00:00
zend_function * new_fn ;
2011-11-05 02:05:28 +00:00
2014-02-10 06:04:30 +00:00
if ( ( existing_fn = zend_hash_find_ptr ( & ce - > function_table , key ) ) ! = NULL ) {
2012-12-25 06:23:08 +00:00
if ( existing_fn - > common . scope = = ce ) {
/* members from the current class override trait methods */
/* use temporary *overriden HashTable to detect hidden conflict */
if ( * overriden ) {
2014-02-10 06:04:30 +00:00
if ( ( existing_fn = zend_hash_find_ptr ( * overriden , key ) ) ! = NULL ) {
2012-12-25 06:23:08 +00:00
if ( existing_fn - > common . fn_flags & ZEND_ACC_ABSTRACT ) {
2012-12-25 12:21:25 +00:00
/* Make sure the trait method is compatible with previosly declared abstract method */
2012-12-25 06:23:08 +00:00
if ( ! zend_traits_method_compatibility_check ( fn , existing_fn TSRMLS_CC ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Declaration of %s must be compatible with %s " ,
2012-12-25 06:23:08 +00:00
zend_get_function_declaration ( fn TSRMLS_CC ) ,
zend_get_function_declaration ( existing_fn TSRMLS_CC ) ) ;
}
} else if ( fn - > common . fn_flags & ZEND_ACC_ABSTRACT ) {
/* Make sure the abstract declaration is compatible with previous declaration */
if ( ! zend_traits_method_compatibility_check ( existing_fn , fn TSRMLS_CC ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Declaration of %s must be compatible with %s " ,
2012-12-25 06:23:08 +00:00
zend_get_function_declaration ( fn TSRMLS_CC ) ,
zend_get_function_declaration ( existing_fn TSRMLS_CC ) ) ;
}
return ;
2014-07-11 14:52:27 +00:00
}
}
2012-12-25 06:23:08 +00:00
} else {
ALLOC_HASHTABLE ( * overriden ) ;
2014-04-21 14:25:34 +00:00
zend_hash_init_ex ( * overriden , 8 , NULL , ptr_dtor , 0 , 0 ) ;
2011-08-15 11:16:18 +00:00
}
2014-02-10 06:04:30 +00:00
fn = zend_hash_update_mem ( * overriden , key , fn , sizeof ( zend_function ) ) ;
2012-12-25 06:23:08 +00:00
return ;
} else if ( existing_fn - > common . fn_flags & ZEND_ACC_ABSTRACT ) {
2012-12-25 12:21:25 +00:00
/* Make sure the trait method is compatible with previosly declared abstract method */
2012-12-25 06:23:08 +00:00
if ( ! zend_traits_method_compatibility_check ( fn , existing_fn TSRMLS_CC ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Declaration of %s must be compatible with %s " ,
2012-12-25 06:23:08 +00:00
zend_get_function_declaration ( fn TSRMLS_CC ) ,
zend_get_function_declaration ( existing_fn TSRMLS_CC ) ) ;
}
} else if ( fn - > common . fn_flags & ZEND_ACC_ABSTRACT ) {
/* Make sure the abstract declaration is compatible with previous declaration */
if ( ! zend_traits_method_compatibility_check ( existing_fn , fn TSRMLS_CC ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Declaration of %s must be compatible with %s " ,
2012-12-25 06:23:08 +00:00
zend_get_function_declaration ( fn TSRMLS_CC ) ,
zend_get_function_declaration ( existing_fn TSRMLS_CC ) ) ;
}
return ;
} else if ( ( existing_fn - > common . scope - > ce_flags & ZEND_ACC_TRAIT ) = = ZEND_ACC_TRAIT ) {
2013-10-19 21:22:20 +00:00
/* two traits can't define the same non-abstract method */
2012-12-25 06:23:08 +00:00
# if 1
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Trait method %s has not been applied, because there are collisions with other trait methods on %s " ,
2014-02-21 13:27:53 +00:00
name , ce - > name - > val ) ;
2013-10-19 21:22:20 +00:00
# else /* TODO: better error message */
zend_error_noreturn ( E_COMPILE_ERROR , " Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s " ,
2014-02-21 13:27:53 +00:00
fn - > common . scope - > name - > val , fn - > common . function_name - > val ,
ce - > name - > val , name ,
existing_fn - > common . scope - > name - > val , existing_fn - > common . function_name - > val ) ;
2012-12-25 06:23:08 +00:00
# endif
} else {
/* inherited members are overridden by members inserted by traits */
2013-06-10 21:20:18 +00:00
/* check whether the trait method fulfills the inheritance requirements */
2011-11-01 15:25:24 +00:00
do_inheritance_check_on_method ( fn , existing_fn TSRMLS_CC ) ;
2014-07-11 14:52:27 +00:00
}
2012-12-25 06:23:08 +00:00
}
2014-07-11 14:52:27 +00:00
2012-12-25 06:23:08 +00:00
function_add_ref ( fn ) ;
2014-07-22 14:55:34 +00:00
new_fn = zend_arena_alloc ( & CG ( arena ) , sizeof ( zend_op_array ) ) ;
memcpy ( new_fn , fn , sizeof ( zend_op_array ) ) ;
fn = zend_hash_update_ptr ( & ce - > function_table , key , new_fn ) ;
2014-02-10 06:04:30 +00:00
zend_add_magic_methods ( ce , key , fn TSRMLS_CC ) ;
2014-07-11 14:52:27 +00:00
}
/* }}} */
2014-07-22 14:55:34 +00:00
static void zend_fixup_trait_method ( zend_function * fn , zend_class_entry * ce ) /* { { { */
2014-07-14 06:33:11 +00:00
{
2012-12-25 06:23:08 +00:00
if ( ( fn - > common . scope - > ce_flags & ZEND_ACC_TRAIT ) = = ZEND_ACC_TRAIT ) {
2014-07-14 06:33:11 +00:00
2012-12-25 06:23:08 +00:00
fn - > common . scope = ce ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
if ( fn - > common . fn_flags & ZEND_ACC_ABSTRACT ) {
ce - > ce_flags | = ZEND_ACC_IMPLICIT_ABSTRACT_CLASS ;
}
2010-07-06 11:40:17 +00:00
if ( fn - > op_array . static_variables ) {
ce - > ce_flags | = ZEND_HAS_STATIC_IN_METHODS ;
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-07-14 06:33:11 +00:00
}
/* }}} */
2014-07-22 14:55:34 +00:00
static int zend_traits_copy_functions ( zend_string * fnname , zend_function * fn , zend_class_entry * ce , HashTable * * overriden , HashTable * exclude_table TSRMLS_DC ) /* { { { */
2014-07-14 11:43:11 +00:00
{
2012-12-25 06:23:08 +00:00
zend_trait_alias * alias , * * alias_ptr ;
2014-02-10 06:04:30 +00:00
zend_string * lcname ;
2012-12-25 06:23:08 +00:00
zend_function fn_copy ;
2014-07-14 11:43:11 +00:00
2010-11-18 17:59:04 +00:00
/* apply aliases which are qualified with a class name, there should not be any ambiguity */
2012-12-25 06:23:08 +00:00
if ( ce - > trait_aliases ) {
alias_ptr = ce - > trait_aliases ;
alias = * alias_ptr ;
while ( alias ) {
2011-07-08 19:52:21 +00:00
/* Scope unset or equal to the function we compare to, and the alias applies to fn */
2012-12-25 06:23:08 +00:00
if ( alias - > alias ! = NULL
& & ( ! alias - > trait_method - > ce | | fn - > common . scope = = alias - > trait_method - > ce )
2014-07-22 14:55:34 +00:00
& & alias - > trait_method - > method_name - > len = = fnname - > len
& & ( zend_binary_strcasecmp ( alias - > trait_method - > method_name - > val , alias - > trait_method - > method_name - > len , fnname - > val , fnname - > len ) = = 0 ) ) {
2011-07-09 12:06:11 +00:00
fn_copy = * fn ;
2014-07-14 11:43:11 +00:00
2011-07-09 12:06:11 +00:00
/* if it is 0, no modifieres has been changed */
2013-01-28 02:02:51 +00:00
if ( alias - > modifiers ) {
2012-12-25 06:23:08 +00:00
fn_copy . common . fn_flags = alias - > modifiers | ( fn - > common . fn_flags ^ ( fn - > common . fn_flags & ZEND_ACC_PPP_MASK ) ) ;
2011-07-09 12:06:11 +00:00
}
2014-07-14 11:43:11 +00:00
2014-08-25 19:21:16 +00:00
lcname = zend_string_alloc ( alias - > alias - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lcname - > val , alias - > alias - > val , alias - > alias - > len ) ;
zend_add_trait_method ( ce , alias - > alias - > val , lcname , & fn_copy , overriden TSRMLS_CC ) ;
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
2006-05-09 23:53:23 +00:00
2012-12-25 06:23:08 +00:00
/* Record the trait from which this alias was resolved. */
if ( ! alias - > trait_method - > ce ) {
alias - > trait_method - > ce = fn - > common . scope ;
2011-11-17 21:04:15 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2012-12-25 06:23:08 +00:00
alias_ptr + + ;
alias = * alias_ptr ;
2003-05-19 17:12:56 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2013-08-29 09:35:11 +00:00
2014-07-22 14:55:34 +00:00
if ( exclude_table = = NULL | | zend_hash_find ( exclude_table , fnname ) = = NULL ) {
2010-04-22 23:16:15 +00:00
/* is not in hashtable, thus, function is not to be excluded */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
fn_copy = * fn ;
2014-06-30 11:43:45 +00:00
2012-12-25 06:23:08 +00:00
/* apply aliases which have not alias name, just setting visibility */
if ( ce - > trait_aliases ) {
alias_ptr = ce - > trait_aliases ;
alias = * alias_ptr ;
while ( alias ) {
2011-07-08 19:52:21 +00:00
/* Scope unset or equal to the function we compare to, and the alias applies to fn */
2012-12-25 06:23:08 +00:00
if ( alias - > alias = = NULL & & alias - > modifiers ! = 0
& & ( ! alias - > trait_method - > ce | | fn - > common . scope = = alias - > trait_method - > ce )
2014-07-22 14:55:34 +00:00
& & ( alias - > trait_method - > method_name - > len = = fnname - > len )
& & ( zend_binary_strcasecmp ( alias - > trait_method - > method_name - > val , alias - > trait_method - > method_name - > len , fnname - > val , fnname - > len ) = = 0 ) ) {
2012-12-25 06:23:08 +00:00
fn_copy . common . fn_flags = alias - > modifiers | ( fn - > common . fn_flags ^ ( fn - > common . fn_flags & ZEND_ACC_PPP_MASK ) ) ;
2011-11-17 21:04:15 +00:00
/** Record the trait from which this alias was resolved. */
2012-12-25 06:23:08 +00:00
if ( ! alias - > trait_method - > ce ) {
alias - > trait_method - > ce = fn - > common . scope ;
2014-07-14 06:33:11 +00:00
}
2014-07-10 20:32:18 +00:00
}
2012-12-25 06:23:08 +00:00
alias_ptr + + ;
alias = * alias_ptr ;
2014-07-10 20:32:18 +00:00
}
2003-05-19 17:12:56 +00:00
}
2014-06-30 11:43:45 +00:00
2014-07-22 14:55:34 +00:00
zend_add_trait_method ( ce , fn - > common . function_name - > val , fnname , & fn_copy , overriden TSRMLS_CC ) ;
1999-06-08 18:33:31 +00:00
}
2006-05-09 23:53:23 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
return ZEND_HASH_APPLY_KEEP ;
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2012-12-25 06:23:08 +00:00
static void zend_check_trait_usage ( zend_class_entry * ce , zend_class_entry * trait TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t i ;
1999-12-15 20:15:32 +00:00
2013-02-21 10:18:41 +00:00
if ( ( trait - > ce_flags & ZEND_ACC_TRAIT ) ! = ZEND_ACC_TRAIT ) {
2014-02-24 21:18:06 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements " , trait - > name - > val ) ;
2014-07-11 14:52:27 +00:00
}
2012-12-25 06:23:08 +00:00
for ( i = 0 ; i < ce - > num_traits ; i + + ) {
if ( ce - > traits [ i ] = = trait ) {
return ;
2008-06-15 18:27:37 +00:00
}
2013-01-28 02:02:51 +00:00
}
2014-02-21 14:23:56 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Required Trait %s wasn't added to %s " , trait - > name - > val , ce - > name - > val ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2011-07-08 19:52:21 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2010-05-03 22:08:09 +00:00
static void zend_traits_init_trait_structures ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
{
size_t i , j = 0 ;
zend_trait_precedence * cur_precedence ;
zend_trait_method_reference * cur_method_ref ;
2014-02-10 06:04:30 +00:00
zend_string * lcname ;
2011-11-17 21:07:52 +00:00
zend_bool method_exists ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2010-04-22 23:16:15 +00:00
/* resolve class references */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
if ( ce - > trait_precedences ) {
i = 0 ;
while ( ( cur_precedence = ce - > trait_precedences [ i ] ) ) {
2011-11-17 21:04:15 +00:00
/** Resolve classes for all precedence operations. */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
if ( cur_precedence - > exclude_from_classes ) {
2011-11-17 21:04:15 +00:00
cur_method_ref = cur_precedence - > trait_method ;
2014-02-10 06:04:30 +00:00
if ( ! ( cur_precedence - > trait_method - > ce = zend_fetch_class ( cur_method_ref - > class_name ,
2012-10-08 14:59:52 +00:00
ZEND_FETCH_CLASS_TRAIT | ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC ) ) ) {
2014-05-06 04:45:33 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Could not find trait %s " , cur_method_ref - > class_name - > val ) ;
2012-10-08 14:59:52 +00:00
}
2012-12-25 06:23:08 +00:00
zend_check_trait_usage ( ce , cur_precedence - > trait_method - > ce TSRMLS_CC ) ;
2013-01-28 02:02:51 +00:00
2011-11-17 21:04:15 +00:00
/** Ensure that the prefered method is actually available. */
2014-08-25 19:21:16 +00:00
lcname = zend_string_alloc ( cur_method_ref - > method_name - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lcname - > val ,
cur_method_ref - > method_name - > val ,
cur_method_ref - > method_name - > len ) ;
2011-11-17 21:04:15 +00:00
method_exists = zend_hash_exists ( & cur_method_ref - > ce - > function_table ,
2014-02-10 06:04:30 +00:00
lcname ) ;
2014-08-25 19:21:16 +00:00
zend_string_free ( lcname ) ;
2011-11-17 21:04:15 +00:00
if ( ! method_exists ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
2011-11-17 21:04:15 +00:00
" A precedence rule was defined for %s::%s but this method does not exist " ,
2014-02-10 06:04:30 +00:00
cur_method_ref - > ce - > name - > val ,
cur_method_ref - > method_name - > val ) ;
2009-01-20 11:22:45 +00:00
}
1999-04-07 18:10:10 +00:00
2011-11-17 21:04:15 +00:00
/** With the other traits, we are more permissive.
We do not give errors for those . This allows to be more
2012-03-04 19:34:19 +00:00
defensive in such definitions .
2013-07-13 12:37:04 +00:00
However , we want to make sure that the insteadof declaration
2012-03-04 19:34:19 +00:00
is consistent in itself .
*/
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
j = 0 ;
2014-02-10 06:04:30 +00:00
while ( cur_precedence - > exclude_from_classes [ j ] . class_name ) {
zend_string * class_name = cur_precedence - > exclude_from_classes [ j ] . class_name ;
2000-11-27 18:46:23 +00:00
2014-02-10 06:04:30 +00:00
if ( ! ( cur_precedence - > exclude_from_classes [ j ] . ce = zend_fetch_class ( class_name , ZEND_FETCH_CLASS_TRAIT | ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC ) ) ) {
2014-02-24 21:18:06 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Could not find trait %s " , class_name - > val ) ;
2013-01-28 02:02:51 +00:00
}
2014-02-10 06:04:30 +00:00
zend_check_trait_usage ( ce , cur_precedence - > exclude_from_classes [ j ] . ce TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2012-03-04 19:34:19 +00:00
/* make sure that the trait method is not from a class mentioned in
exclude_from_classes , for consistency */
2014-02-10 06:04:30 +00:00
if ( cur_precedence - > trait_method - > ce = = cur_precedence - > exclude_from_classes [ i ] . ce ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
2013-01-28 02:02:51 +00:00
" Inconsistent insteadof definition. "
2012-03-04 19:34:19 +00:00
" The method %s is to be used from %s, but %s is also on the exclude list " ,
2014-02-10 06:04:30 +00:00
cur_method_ref - > method_name - > val ,
cur_precedence - > trait_method - > ce - > name - > val ,
cur_precedence - > trait_method - > ce - > name - > val ) ;
2012-03-04 19:34:19 +00:00
}
2013-01-28 02:02:51 +00:00
2014-08-25 19:21:16 +00:00
zend_string_release ( class_name ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
j + + ;
1999-06-06 17:35:42 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
i + + ;
1999-04-07 18:10:10 +00:00
}
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
if ( ce - > trait_aliases ) {
i = 0 ;
while ( ce - > trait_aliases [ i ] ) {
2011-11-17 21:04:15 +00:00
/** For all aliases with an explicit class name, resolve the class now. */
2011-07-09 12:06:11 +00:00
if ( ce - > trait_aliases [ i ] - > trait_method - > class_name ) {
cur_method_ref = ce - > trait_aliases [ i ] - > trait_method ;
2014-02-10 06:04:30 +00:00
if ( ! ( cur_method_ref - > ce = zend_fetch_class ( cur_method_ref - > class_name , ZEND_FETCH_CLASS_TRAIT | ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC ) ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Could not find trait %s " , cur_method_ref - > class_name - > val ) ;
2012-10-08 14:59:52 +00:00
}
2012-12-25 06:23:08 +00:00
zend_check_trait_usage ( ce , cur_method_ref - > ce TSRMLS_CC ) ;
2000-11-27 18:46:23 +00:00
2011-11-17 21:04:15 +00:00
/** And, ensure that the referenced method is resolvable, too. */
2014-08-25 19:21:16 +00:00
lcname = zend_string_alloc ( cur_method_ref - > method_name - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lcname - > val ,
cur_method_ref - > method_name - > val ,
cur_method_ref - > method_name - > len ) ;
2011-11-17 21:04:15 +00:00
method_exists = zend_hash_exists ( & cur_method_ref - > ce - > function_table ,
2014-02-10 06:04:30 +00:00
lcname ) ;
2014-08-25 19:21:16 +00:00
zend_string_free ( lcname ) ;
2011-11-17 21:04:15 +00:00
if ( ! method_exists ) {
2014-02-24 21:18:06 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " An alias was defined for %s::%s but this method does not exist " , cur_method_ref - > ce - > name - > val , cur_method_ref - > method_name - > val ) ;
2011-11-17 21:04:15 +00:00
}
2014-07-07 22:13:53 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
i + + ;
2000-11-27 18:46:23 +00:00
}
1999-09-21 20:00:01 +00:00
}
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2011-07-08 19:52:21 +00:00
static void zend_traits_compile_exclude_table ( HashTable * exclude_table , zend_trait_precedence * * precedences , zend_class_entry * trait ) /* { { { */
2013-08-29 09:35:11 +00:00
{
2011-06-20 01:36:23 +00:00
size_t i = 0 , j ;
2014-02-25 23:14:50 +00:00
2011-06-20 01:36:23 +00:00
if ( ! precedences ) {
return ;
}
while ( precedences [ i ] ) {
if ( precedences [ i ] - > exclude_from_classes ) {
j = 0 ;
2014-02-10 06:04:30 +00:00
while ( precedences [ i ] - > exclude_from_classes [ j ] . ce ) {
if ( precedences [ i ] - > exclude_from_classes [ j ] . ce = = trait ) {
2014-08-25 19:21:16 +00:00
zend_string * lcname = zend_string_alloc ( precedences [ i ] - > trait_method - > method_name - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy ( lcname - > val ,
precedences [ i ] - > trait_method - > method_name - > val ,
precedences [ i ] - > trait_method - > method_name - > len ) ;
if ( zend_hash_add_empty_element ( exclude_table , lcname ) = = NULL ) {
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
2014-02-24 21:18:06 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times " , precedences [ i ] - > trait_method - > method_name - > val , trait - > name - > val ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2011-06-20 01:36:23 +00:00
+ + j ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
}
2011-06-20 01:36:23 +00:00
+ + i ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2013-08-29 09:35:11 +00:00
}
/* }}} */
2010-12-20 00:52:40 +00:00
static void zend_do_traits_method_binding ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-08-25 19:21:16 +00:00
uint32_t i ;
2012-12-25 06:23:08 +00:00
HashTable * overriden = NULL ;
2014-07-22 14:55:34 +00:00
zend_string * key ;
zend_function * fn ;
2006-05-09 23:53:23 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
for ( i = 0 ; i < ce - > num_traits ; i + + ) {
2011-07-09 12:06:11 +00:00
if ( ce - > trait_precedences ) {
2012-12-25 06:23:08 +00:00
HashTable exclude_table ;
2006-05-09 23:53:23 +00:00
2011-07-09 12:06:11 +00:00
/* TODO: revisit this start size, may be its not optimal */
2014-04-21 14:25:34 +00:00
zend_hash_init_ex ( & exclude_table , 8 , NULL , NULL , 0 , 0 ) ;
1999-04-07 18:10:10 +00:00
2011-07-09 12:06:11 +00:00
zend_traits_compile_exclude_table ( & exclude_table , ce - > trait_precedences , ce - > traits [ i ] ) ;
2013-10-04 11:13:46 +00:00
2011-07-09 12:06:11 +00:00
/* copies functions, applies defined aliasing, and excludes unused trait methods */
2014-07-22 14:55:34 +00:00
ZEND_HASH_FOREACH_STR_KEY_PTR ( & ce - > traits [ i ] - > function_table , key , fn ) {
zend_traits_copy_functions ( key , fn , ce , & overriden , & exclude_table TSRMLS_CC ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2012-12-25 06:23:08 +00:00
2012-01-20 12:30:57 +00:00
zend_hash_destroy ( & exclude_table ) ;
2011-07-09 12:06:11 +00:00
} else {
2014-07-22 14:55:34 +00:00
ZEND_HASH_FOREACH_STR_KEY_PTR ( & ce - > traits [ i ] - > function_table , key , fn ) {
zend_traits_copy_functions ( key , fn , ce , & overriden , NULL TSRMLS_CC ) ;
} ZEND_HASH_FOREACH_END ( ) ;
2011-07-09 12:06:11 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2013-01-28 02:02:51 +00:00
2014-07-22 14:55:34 +00:00
ZEND_HASH_FOREACH_PTR ( & ce - > function_table , fn ) {
zend_fixup_trait_method ( fn , ce ) ;
} ZEND_HASH_FOREACH_END ( ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2012-12-25 06:23:08 +00:00
if ( overriden ) {
zend_hash_destroy ( overriden ) ;
FREE_HASHTABLE ( overriden ) ;
}
1999-07-24 11:43:21 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-07-24 11:43:21 +00:00
2014-02-10 06:04:30 +00:00
static zend_class_entry * find_first_definition ( zend_class_entry * ce , size_t current_trait , zend_string * prop_name , zend_class_entry * coliding_ce ) /* { { { */
1999-09-09 14:15:17 +00:00
{
2010-12-20 00:52:40 +00:00
size_t i ;
2004-03-05 13:04:21 +00:00
2012-12-25 06:23:08 +00:00
if ( coliding_ce = = ce ) {
for ( i = 0 ; i < current_trait ; i + + ) {
2014-02-10 06:04:30 +00:00
if ( zend_hash_exists ( & ce - > traits [ i ] - > properties_info , prop_name ) ) {
2012-12-25 06:23:08 +00:00
return ce - > traits [ i ] ;
}
2011-12-19 16:48:18 +00:00
}
2006-05-09 23:53:23 +00:00
}
1999-09-09 14:15:17 +00:00
2012-12-25 06:23:08 +00:00
return coliding_ce ;
1999-09-09 14:15:17 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-07-24 11:43:21 +00:00
2010-12-20 00:52:40 +00:00
static void zend_do_traits_property_binding ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
1999-07-24 11:43:21 +00:00
{
2010-12-20 00:52:40 +00:00
size_t i ;
zend_property_info * property_info ;
zend_property_info * coliding_prop ;
zval compare_result ;
2014-02-10 06:04:30 +00:00
zend_string * prop_name ;
2011-09-13 13:29:35 +00:00
const char * class_name_unused ;
2010-12-20 01:42:25 +00:00
zend_bool not_compatible ;
2010-12-20 00:52:40 +00:00
zval * prop_value ;
2014-08-25 19:21:16 +00:00
uint32_t flags ;
2014-02-24 21:18:06 +00:00
zend_string * doc_comment ;
2006-05-09 23:53:23 +00:00
2011-07-08 19:52:21 +00:00
/* In the following steps the properties are inserted into the property table
* for that , a very strict approach is applied :
* - check for compatibility , if not compatible with any property in class - > fatal
* - if compatible , then strict notice
*/
2010-12-20 00:52:40 +00:00
for ( i = 0 ; i < ce - > num_traits ; i + + ) {
2014-04-18 15:18:11 +00:00
ZEND_HASH_FOREACH_PTR ( & ce - > traits [ i ] - > properties_info , property_info ) {
2010-12-20 00:52:40 +00:00
/* first get the unmangeld name if necessary,
2011-07-08 19:52:21 +00:00
* then check whether the property is already there
*/
2012-12-25 06:23:08 +00:00
flags = property_info - > flags ;
if ( ( flags & ZEND_ACC_PPP_MASK ) = = ZEND_ACC_PUBLIC ) {
2014-08-25 19:21:16 +00:00
prop_name = zend_string_copy ( property_info - > name ) ;
2010-12-20 01:42:25 +00:00
} else {
2014-02-10 06:04:30 +00:00
const char * pname ;
int pname_len ;
2006-05-09 23:53:23 +00:00
2010-12-20 00:52:40 +00:00
/* for private and protected we need to unmangle the names */
2014-02-10 06:04:30 +00:00
zend_unmangle_property_name_ex ( property_info - > name - > val , property_info - > name - > len ,
& class_name_unused , & pname , & pname_len ) ;
2014-08-25 19:21:16 +00:00
prop_name = zend_string_init ( pname , pname_len , 0 ) ;
2010-12-20 00:52:40 +00:00
}
2001-07-19 15:53:38 +00:00
2010-12-20 00:52:40 +00:00
/* next: check for conflicts with current class */
2014-02-10 06:04:30 +00:00
if ( ( coliding_prop = zend_hash_find_ptr ( & ce - > properties_info , prop_name ) ) ! = NULL ) {
2013-01-28 02:02:51 +00:00
if ( coliding_prop - > flags & ZEND_ACC_SHADOW ) {
2014-02-10 06:04:30 +00:00
zend_hash_del ( & ce - > properties_info , prop_name ) ;
2012-12-25 06:23:08 +00:00
flags | = ZEND_ACC_CHANGED ;
2013-01-28 02:02:51 +00:00
} else {
2012-12-25 06:23:08 +00:00
if ( ( coliding_prop - > flags & ( ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC ) )
= = ( flags & ( ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC ) ) ) {
/* flags are identical, now the value needs to be checked */
if ( flags & ZEND_ACC_STATIC ) {
not_compatible = ( FAILURE = = compare_function ( & compare_result ,
2014-02-10 06:04:30 +00:00
& ce - > default_static_members_table [ coliding_prop - > offset ] ,
& ce - > traits [ i ] - > default_static_members_table [ property_info - > offset ] TSRMLS_CC ) )
2012-12-25 06:23:08 +00:00
| | ( Z_LVAL ( compare_result ) ! = 0 ) ;
2011-12-17 14:26:39 +00:00
} else {
2012-12-25 06:23:08 +00:00
not_compatible = ( FAILURE = = compare_function ( & compare_result ,
2014-02-10 06:04:30 +00:00
& ce - > default_properties_table [ coliding_prop - > offset ] ,
& ce - > traits [ i ] - > default_properties_table [ property_info - > offset ] TSRMLS_CC ) )
2012-12-25 06:23:08 +00:00
| | ( Z_LVAL ( compare_result ) ! = 0 ) ;
2011-12-17 14:26:39 +00:00
}
2011-12-19 16:48:18 +00:00
} else {
2012-12-25 06:23:08 +00:00
/* the flags are not identical, thus, we assume properties are not compatible */
not_compatible = 1 ;
2011-12-19 16:48:18 +00:00
}
2008-05-05 11:03:35 +00:00
2012-12-25 06:23:08 +00:00
if ( not_compatible ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
2012-01-20 12:30:57 +00:00
" %s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed " ,
2014-02-10 06:04:30 +00:00
find_first_definition ( ce , i , prop_name , coliding_prop - > ce ) - > name - > val ,
property_info - > ce - > name - > val ,
prop_name - > val ,
ce - > name - > val ) ;
2012-12-25 06:23:08 +00:00
} else {
2013-01-28 02:02:51 +00:00
zend_error ( E_STRICT ,
2012-01-20 12:30:57 +00:00
" %s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed " ,
2014-02-10 06:04:30 +00:00
find_first_definition ( ce , i , prop_name , coliding_prop - > ce ) - > name - > val ,
property_info - > ce - > name - > val ,
prop_name - > val ,
ce - > name - > val ) ;
2014-08-25 19:21:16 +00:00
zend_string_release ( prop_name ) ;
2012-12-25 06:23:08 +00:00
continue ;
}
2010-12-20 00:52:40 +00:00
}
}
1999-07-24 11:43:21 +00:00
2010-12-20 00:52:40 +00:00
/* property not found, so lets add it */
2012-12-25 06:23:08 +00:00
if ( flags & ZEND_ACC_STATIC ) {
2014-02-10 06:04:30 +00:00
prop_value = & ce - > traits [ i ] - > default_static_members_table [ property_info - > offset ] ;
2010-12-20 01:42:25 +00:00
} else {
2014-02-10 06:04:30 +00:00
prop_value = & ce - > traits [ i ] - > default_properties_table [ property_info - > offset ] ;
2010-12-20 00:52:40 +00:00
}
2014-02-21 16:35:40 +00:00
if ( Z_REFCOUNTED_P ( prop_value ) ) Z_ADDREF_P ( prop_value ) ;
2008-05-05 11:03:35 +00:00
2014-08-25 19:21:16 +00:00
doc_comment = property_info - > doc_comment ? zend_string_copy ( property_info - > doc_comment ) : NULL ;
2014-02-10 06:04:30 +00:00
zend_declare_property_ex ( ce , prop_name ,
2013-01-28 02:02:51 +00:00
prop_value , flags ,
2014-02-24 21:18:06 +00:00
doc_comment TSRMLS_CC ) ;
2014-08-25 19:21:16 +00:00
zend_string_release ( prop_name ) ;
2014-04-18 15:18:11 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2012-12-12 22:48:51 +00:00
}
2010-12-20 00:52:40 +00:00
}
2011-07-08 19:52:21 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2011-11-17 21:04:15 +00:00
static void zend_do_check_for_inconsistent_traits_aliasing ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
{
int i = 0 ;
2011-11-18 13:49:07 +00:00
zend_trait_alias * cur_alias ;
2014-02-10 06:04:30 +00:00
zend_string * lc_method_name ;
1999-07-24 11:43:21 +00:00
2011-11-17 21:04:15 +00:00
if ( ce - > trait_aliases ) {
while ( ce - > trait_aliases [ i ] ) {
2011-11-18 13:49:07 +00:00
cur_alias = ce - > trait_aliases [ i ] ;
2011-11-17 21:04:15 +00:00
/** The trait for this alias has not been resolved, this means, this
alias was not applied . Abort with an error . */
2011-11-18 13:49:07 +00:00
if ( ! cur_alias - > trait_method - > ce ) {
if ( cur_alias - > alias ) {
/** Plain old inconsistency/typo/bug */
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
2011-11-18 13:49:07 +00:00
" An alias (%s) was defined for method %s(), but this method does not exist " ,
2014-02-24 21:18:06 +00:00
cur_alias - > alias - > val ,
cur_alias - > trait_method - > method_name - > val ) ;
2011-11-18 13:56:41 +00:00
} else {
2011-11-18 13:49:07 +00:00
/** Here are two possible cases:
1 ) this is an attempt to modifiy the visibility
of a method introduce as part of another alias .
Since that seems to violate the DRY principle ,
we check against it and abort .
2 ) it is just a plain old inconsitency / typo / bug
as in the case where alias is set . */
2006-05-09 23:53:23 +00:00
2014-08-25 19:21:16 +00:00
lc_method_name = zend_string_alloc ( cur_alias - > trait_method - > method_name - > len , 0 ) ;
2014-02-10 06:04:30 +00:00
zend_str_tolower_copy (
lc_method_name - > val ,
cur_alias - > trait_method - > method_name - > val ,
cur_alias - > trait_method - > method_name - > len ) ;
2011-11-18 13:49:07 +00:00
if ( zend_hash_exists ( & ce - > function_table ,
2014-02-10 06:04:30 +00:00
lc_method_name ) ) {
2014-08-25 19:21:16 +00:00
zend_string_free ( lc_method_name ) ;
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
2011-11-18 13:49:07 +00:00
" The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error " ,
2014-02-10 06:04:30 +00:00
cur_alias - > trait_method - > method_name - > val ) ;
2011-11-18 13:56:41 +00:00
} else {
2014-08-25 19:21:16 +00:00
zend_string_free ( lc_method_name ) ;
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
2011-11-18 13:49:07 +00:00
" The modifiers of the trait method %s() are changed, but this method does not exist. Error " ,
2014-02-10 06:04:30 +00:00
cur_alias - > trait_method - > method_name - > val ) ;
2003-12-14 16:09:07 +00:00
2011-11-18 13:49:07 +00:00
}
}
2011-11-17 21:04:15 +00:00
}
i + + ;
2003-12-14 16:09:07 +00:00
}
}
1999-04-07 18:10:10 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2010-12-20 00:52:40 +00:00
ZEND_API void zend_do_bind_traits ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
2012-05-15 16:30:48 +00:00
{
2012-05-26 20:44:53 +00:00
2010-12-20 00:52:40 +00:00
if ( ce - > num_traits < = 0 ) {
return ;
2012-05-19 16:49:27 +00:00
}
2010-12-20 00:52:40 +00:00
/* complete initialization of trait strutures in ce */
zend_traits_init_trait_structures ( ce TSRMLS_CC ) ;
2012-07-21 19:05:46 +00:00
2010-12-20 00:52:40 +00:00
/* first care about all methods to be flattened into the class */
zend_do_traits_method_binding ( ce TSRMLS_CC ) ;
2012-05-26 20:44:53 +00:00
2011-11-17 21:04:15 +00:00
/* Aliases which have not been applied indicate typos/bugs. */
zend_do_check_for_inconsistent_traits_aliasing ( ce TSRMLS_CC ) ;
2012-05-29 15:53:11 +00:00
2010-12-20 00:52:40 +00:00
/* then flatten the properties into it, to, mostly to notfiy developer about problems */
zend_do_traits_property_binding ( ce TSRMLS_CC ) ;
2012-07-17 11:24:27 +00:00
2010-12-20 00:52:40 +00:00
/* verify that all abstract methods from traits have been implemented */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
zend_verify_abstract_class ( ce TSRMLS_CC ) ;
2012-05-30 00:44:06 +00:00
2010-04-22 23:16:15 +00:00
/* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
if ( ce - > ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS ) {
ce - > ce_flags - = ZEND_ACC_IMPLICIT_ABSTRACT_CLASS ;
2012-05-29 15:53:11 +00:00
}
2012-05-15 16:30:48 +00:00
}
/* }}} */
2014-08-27 22:44:06 +00:00
ZEND_API int do_bind_function ( const zend_op_array * op_array , const zend_op * opline , HashTable * function_table , zend_bool compile_time TSRMLS_DC ) /* { { { */
2004-02-03 12:17:09 +00:00
{
2014-02-17 13:59:18 +00:00
zend_function * function , * new_function ;
2010-04-20 10:57:45 +00:00
zval * op1 , * op2 ;
2004-02-03 12:17:09 +00:00
2010-04-20 10:57:45 +00:00
if ( compile_time ) {
op1 = & CONSTANT_EX ( op_array , opline - > op1 . constant ) ;
op2 = & CONSTANT_EX ( op_array , opline - > op2 . constant ) ;
} else {
op1 = opline - > op1 . zv ;
op2 = opline - > op2 . zv ;
}
2007-01-09 15:06:07 +00:00
2014-02-10 06:04:30 +00:00
function = zend_hash_find_ptr ( function_table , Z_STR_P ( op1 ) ) ;
2014-07-22 14:55:34 +00:00
new_function = zend_arena_alloc ( & CG ( arena ) , sizeof ( zend_op_array ) ) ;
2014-02-17 13:59:18 +00:00
memcpy ( new_function , function , sizeof ( zend_op_array ) ) ;
if ( zend_hash_add_ptr ( function_table , Z_STR_P ( op2 ) , new_function ) = = NULL ) {
2003-09-03 08:39:43 +00:00
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR ;
2009-04-08 13:17:09 +00:00
zend_function * old_function ;
2004-02-03 12:17:09 +00:00
2014-08-27 16:49:56 +00:00
efree_size ( new_function , sizeof ( zend_op_array ) ) ;
2014-02-10 06:04:30 +00:00
if ( ( old_function = zend_hash_find_ptr ( function_table , Z_STR_P ( op2 ) ) ) ! = NULL
2009-04-08 13:17:09 +00:00
& & old_function - > type = = ZEND_USER_FUNCTION
& & old_function - > op_array . last > 0 ) {
2002-09-24 19:05:53 +00:00
zend_error ( error_level , " Cannot redeclare %s() (previously declared in %s:%d) " ,
2014-02-10 06:04:30 +00:00
function - > common . function_name - > val ,
old_function - > op_array . filename - > val ,
2009-04-08 13:17:09 +00:00
old_function - > op_array . opcodes [ 0 ] . lineno ) ;
2002-09-24 19:05:53 +00:00
} else {
2014-02-10 06:04:30 +00:00
zend_error ( error_level , " Cannot redeclare %s() " , function - > common . function_name - > val ) ;
2002-09-24 19:05:53 +00:00
}
return FAILURE ;
2004-02-03 12:17:09 +00:00
} else {
2014-02-25 19:56:09 +00:00
( * function - > op_array . refcount ) + + ;
function - > op_array . static_variables = NULL ; /* NULL out the unbound function */
2002-09-24 19:05:53 +00:00
return SUCCESS ;
2004-02-03 12:17:09 +00:00
}
2001-08-30 15:26:30 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2001-08-30 15:26:30 +00:00
2010-04-20 10:57:45 +00:00
ZEND_API zend_class_entry * do_bind_class ( const zend_op_array * op_array , const zend_op * opline , HashTable * class_table , zend_bool compile_time TSRMLS_DC ) /* { { { */
2012-11-22 11:17:05 +00:00
{
2014-02-10 06:04:30 +00:00
zend_class_entry * ce ;
2010-04-20 10:57:45 +00:00
zval * op1 , * op2 ;
2012-12-12 22:48:51 +00:00
2010-04-20 10:57:45 +00:00
if ( compile_time ) {
op1 = & CONSTANT_EX ( op_array , opline - > op1 . constant ) ;
op2 = & CONSTANT_EX ( op_array , opline - > op2 . constant ) ;
} else {
op1 = opline - > op1 . zv ;
op2 = opline - > op2 . zv ;
}
2014-02-10 06:04:30 +00:00
if ( ( ce = zend_hash_find_ptr ( class_table , Z_STR_P ( op1 ) ) ) = = NULL ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Internal Zend error - Missing class information for %s " , Z_STRVAL_P ( op1 ) ) ;
2003-03-05 11:14:44 +00:00
return NULL ;
2002-09-24 19:05:53 +00:00
}
ce - > refcount + + ;
2014-02-10 06:04:30 +00:00
if ( zend_hash_add_ptr ( class_table , Z_STR_P ( op2 ) , ce ) = = NULL ) {
2002-09-24 19:05:53 +00:00
ce - > refcount - - ;
2004-02-04 16:30:15 +00:00
if ( ! compile_time ) {
/* If we're in compile time, in practice, it's quite possible
* that we ' ll never reach this class declaration at runtime ,
* so we shut up about it . This allows the if ( ! defined ( ' FOO ' ) ) { return ; }
* approach to work .
*/
2014-02-10 06:04:30 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redeclare class %s " , ce - > name - > val ) ;
2004-02-04 16:30:15 +00:00
}
2003-03-05 11:14:44 +00:00
return NULL ;
2002-09-24 19:05:53 +00:00
} else {
2012-12-25 06:23:08 +00:00
if ( ! ( ce - > ce_flags & ( ZEND_ACC_INTERFACE | ZEND_ACC_IMPLEMENT_INTERFACES | ZEND_ACC_IMPLEMENT_TRAITS ) ) ) {
2004-02-04 17:10:44 +00:00
zend_verify_abstract_class ( ce TSRMLS_CC ) ;
}
2003-03-05 11:14:44 +00:00
return ce ;
2002-09-24 19:05:53 +00:00
}
2012-11-22 11:17:05 +00:00
}
/* }}} */
2012-08-13 13:48:39 +00:00
2010-04-20 10:57:45 +00:00
ZEND_API zend_class_entry * do_bind_inherited_class ( const zend_op_array * op_array , const zend_op * opline , HashTable * class_table , zend_class_entry * parent_ce , zend_bool compile_time TSRMLS_DC ) /* { { { */
2001-08-30 15:26:30 +00:00
{
2014-02-10 06:04:30 +00:00
zend_class_entry * ce ;
2010-04-20 10:57:45 +00:00
zval * op1 , * op2 ;
2006-05-09 23:53:23 +00:00
2010-04-20 10:57:45 +00:00
if ( compile_time ) {
op1 = & CONSTANT_EX ( op_array , opline - > op1 . constant ) ;
op2 = & CONSTANT_EX ( op_array , opline - > op2 . constant ) ;
2010-04-20 11:16:39 +00:00
} else {
2010-04-20 10:57:45 +00:00
op1 = opline - > op1 . zv ;
op2 = opline - > op2 . zv ;
2007-09-28 19:52:53 +00:00
}
2014-02-10 06:04:30 +00:00
ce = zend_hash_find_ptr ( class_table , Z_STR_P ( op1 ) ) ;
2001-08-30 15:26:30 +00:00
2014-02-10 06:04:30 +00:00
if ( ! ce ) {
2004-02-04 16:30:15 +00:00
if ( ! compile_time ) {
/* If we're in compile time, in practice, it's quite possible
* that we ' ll never reach this class declaration at runtime ,
* so we shut up about it . This allows the if ( ! defined ( ' FOO ' ) ) { return ; }
* approach to work .
*/
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redeclare class %s " , Z_STRVAL_P ( op2 ) ) ;
2004-02-04 16:30:15 +00:00
}
2003-03-05 11:14:44 +00:00
return NULL ;
2002-09-24 19:05:53 +00:00
}
2007-01-09 15:06:07 +00:00
2004-08-26 22:59:25 +00:00
if ( parent_ce - > ce_flags & ZEND_ACC_INTERFACE ) {
2014-02-21 14:23:56 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Class %s cannot extend from interface %s " , ce - > name - > val , parent_ce - > name - > val ) ;
2010-05-07 11:09:35 +00:00
} else if ( ( parent_ce - > ce_flags & ZEND_ACC_TRAIT ) = = ZEND_ACC_TRAIT ) {
2014-02-21 14:23:56 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Class %s cannot extend from trait %s " , ce - > name - > val , parent_ce - > name - > val ) ;
2004-08-26 22:59:25 +00:00
}
2007-01-09 15:06:07 +00:00
2003-10-22 19:59:58 +00:00
zend_do_inheritance ( ce , parent_ce TSRMLS_CC ) ;
2007-01-09 15:06:07 +00:00
2002-09-24 19:32:01 +00:00
ce - > refcount + + ;
2012-08-13 13:48:39 +00:00
2002-09-24 19:05:53 +00:00
/* Register the derived class */
2014-02-10 06:04:30 +00:00
if ( zend_hash_add_ptr ( class_table , Z_STR_P ( op2 ) , ce ) = = NULL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redeclare class %s " , ce - > name - > val ) ;
2012-08-14 00:59:40 +00:00
}
2003-03-05 11:14:44 +00:00
return ce ;
2012-08-13 13:48:39 +00:00
}
/* }}} */
2009-07-27 14:11:53 +00:00
void zend_do_early_binding ( TSRMLS_D ) /* { { { */
2012-08-13 13:48:39 +00:00
{
1999-05-15 15:47:24 +00:00
zend_op * opline = & CG ( active_op_array ) - > opcodes [ CG ( active_op_array ) - > last - 1 ] ;
2004-02-04 16:30:15 +00:00
HashTable * table ;
1999-05-15 15:47:24 +00:00
2003-01-28 11:34:24 +00:00
while ( opline - > opcode = = ZEND_TICKS & & opline > CG ( active_op_array ) - > opcodes ) {
opline - - ;
2013-01-28 02:02:51 +00:00
}
2004-02-04 16:30:15 +00:00
switch ( opline - > opcode ) {
case ZEND_DECLARE_FUNCTION :
2014-07-22 14:55:34 +00:00
if ( do_bind_function ( CG ( active_op_array ) , opline , CG ( function_table ) , 1 TSRMLS_CC ) = = FAILURE ) {
2004-02-04 16:30:15 +00:00
return ;
}
table = CG ( function_table ) ;
break ;
2004-02-04 17:10:44 +00:00
case ZEND_DECLARE_CLASS :
2010-04-20 10:57:45 +00:00
if ( do_bind_class ( CG ( active_op_array ) , opline , CG ( class_table ) , 1 TSRMLS_CC ) = = NULL ) {
2008-03-18 08:36:30 +00:00
return ;
}
table = CG ( class_table ) ;
break ;
2004-02-04 17:10:44 +00:00
case ZEND_DECLARE_INHERITED_CLASS :
2008-03-18 08:36:30 +00:00
{
zend_op * fetch_class_opline = opline - 1 ;
2010-04-20 10:57:45 +00:00
zval * parent_name ;
2014-02-10 06:04:30 +00:00
zend_class_entry * ce ;
2012-08-13 13:48:39 +00:00
2010-04-20 10:57:45 +00:00
parent_name = & CONSTANT ( fetch_class_opline - > op2 . constant ) ;
2014-02-10 06:04:30 +00:00
if ( ( ( ce = zend_lookup_class ( Z_STR_P ( parent_name ) TSRMLS_CC ) ) = = NULL ) | |
2008-03-18 08:36:30 +00:00
( ( CG ( compiler_options ) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES ) & &
2014-02-10 06:04:30 +00:00
( ce - > type = = ZEND_INTERNAL_CLASS ) ) ) {
2008-03-18 08:36:30 +00:00
if ( CG ( compiler_options ) & ZEND_COMPILE_DELAYED_BINDING ) {
2014-08-25 19:21:16 +00:00
uint32_t * opline_num = & CG ( active_op_array ) - > early_binding ;
2013-01-28 02:02:51 +00:00
2008-03-18 08:36:30 +00:00
while ( * opline_num ! = - 1 ) {
2010-04-20 10:57:45 +00:00
opline_num = & CG ( active_op_array ) - > opcodes [ * opline_num ] . result . opline_num ;
2008-03-18 08:36:30 +00:00
}
* opline_num = opline - CG ( active_op_array ) - > opcodes ;
opline - > opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED ;
2010-04-20 10:57:45 +00:00
opline - > result_type = IS_UNUSED ;
opline - > result . opline_num = - 1 ;
2004-02-04 16:30:15 +00:00
}
return ;
}
2014-02-10 06:04:30 +00:00
if ( do_bind_inherited_class ( CG ( active_op_array ) , opline , CG ( class_table ) , ce , 1 TSRMLS_CC ) = = NULL ) {
2008-03-18 08:36:30 +00:00
return ;
2004-02-04 17:10:44 +00:00
}
2008-03-18 08:36:30 +00:00
/* clear unnecessary ZEND_FETCH_CLASS opcode */
2010-04-20 10:57:45 +00:00
zend_del_literal ( CG ( active_op_array ) , fetch_class_opline - > op2 . constant ) ;
2008-03-18 08:36:30 +00:00
MAKE_NOP ( fetch_class_opline ) ;
2012-12-12 22:48:51 +00:00
2008-03-18 08:36:30 +00:00
table = CG ( class_table ) ;
break ;
}
case ZEND_VERIFY_ABSTRACT_CLASS :
2004-02-04 18:24:44 +00:00
case ZEND_ADD_INTERFACE :
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
case ZEND_ADD_TRAIT :
case ZEND_BIND_TRAITS :
2004-02-04 18:24:44 +00:00
/* We currently don't early-bind classes that implement interfaces */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
/* Classes with traits are handled exactly the same, no early-bind here */
2004-02-04 18:24:44 +00:00
return ;
2004-02-04 16:30:15 +00:00
default :
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Invalid binding type " ) ;
2004-02-04 16:30:15 +00:00
return ;
2013-01-28 02:02:51 +00:00
}
2002-09-24 19:05:53 +00:00
2014-02-10 06:04:30 +00:00
zend_hash_del ( table , Z_STR ( CONSTANT ( opline - > op1 . constant ) ) ) ;
2010-04-20 10:57:45 +00:00
zend_del_literal ( CG ( active_op_array ) , opline - > op1 . constant ) ;
zend_del_literal ( CG ( active_op_array ) , opline - > op2 . constant ) ;
2008-03-18 08:36:30 +00:00
MAKE_NOP ( opline ) ;
2001-08-30 15:26:30 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2001-08-30 15:26:30 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API void zend_do_delayed_early_binding ( const zend_op_array * op_array TSRMLS_DC ) /* { { { */
2001-08-30 15:26:30 +00:00
{
2008-03-18 08:36:30 +00:00
if ( op_array - > early_binding ! = - 1 ) {
zend_bool orig_in_compilation = CG ( in_compilation ) ;
2014-08-25 19:21:16 +00:00
uint32_t opline_num = op_array - > early_binding ;
2014-02-10 06:04:30 +00:00
zend_class_entry * ce ;
2006-05-09 23:53:23 +00:00
2008-03-18 08:36:30 +00:00
CG ( in_compilation ) = 1 ;
while ( opline_num ! = - 1 ) {
2014-02-10 06:04:30 +00:00
if ( ( ce = zend_lookup_class ( Z_STR_P ( op_array - > opcodes [ opline_num - 1 ] . op2 . zv ) TSRMLS_CC ) ) ! = NULL ) {
do_bind_inherited_class ( op_array , & op_array - > opcodes [ opline_num ] , EG ( class_table ) , ce , 0 TSRMLS_CC ) ;
2008-03-18 08:36:30 +00:00
}
2010-04-20 10:57:45 +00:00
opline_num = op_array - > opcodes [ opline_num ] . result . opline_num ;
2008-03-18 08:36:30 +00:00
}
CG ( in_compilation ) = orig_in_compilation ;
}
2001-08-30 15:26:30 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2001-08-30 15:26:30 +00:00
2014-02-17 13:59:18 +00:00
ZEND_API zend_string * zend_mangle_property_name ( const char * src1 , int src1_length , const char * src2 , int src2_length , int internal ) /* { { { */
1999-07-08 16:55:27 +00:00
{
2014-02-17 13:59:18 +00:00
zend_string * prop_name ;
2002-07-15 18:09:56 +00:00
int prop_name_length ;
1999-12-23 19:23:36 +00:00
2002-07-15 18:09:56 +00:00
prop_name_length = 1 + src1_length + 1 + src2_length ;
2014-08-25 19:21:16 +00:00
prop_name = zend_string_alloc ( prop_name_length , internal ) ;
2014-02-17 13:59:18 +00:00
prop_name - > val [ 0 ] = ' \0 ' ;
memcpy ( prop_name - > val + 1 , src1 , src1_length + 1 ) ;
memcpy ( prop_name - > val + 1 + src1_length + 1 , src2 , src2_length + 1 ) ;
return prop_name ;
2002-02-21 11:50:44 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-12-23 19:23:36 +00:00
2009-07-27 14:11:53 +00:00
static int zend_strnlen ( const char * s , int maxlen ) /* { { { */
2005-09-16 17:05:09 +00:00
{
2006-07-24 17:58:32 +00:00
int len = 0 ;
while ( * s + + & & maxlen - - ) len + + ;
return len ;
1999-07-08 16:55:27 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-07-08 16:55:27 +00:00
2013-01-14 08:23:22 +00:00
ZEND_API int zend_unmangle_property_name_ex ( const char * mangled_property , int len , const char * * class_name , const char * * prop_name , int * prop_len ) /* { { { */
1999-07-27 20:34:31 +00:00
{
2006-07-24 17:58:32 +00:00
int class_name_len ;
2003-09-03 21:21:18 +00:00
2006-07-24 17:58:32 +00:00
* class_name = NULL ;
2005-02-23 11:15:51 +00:00
2003-06-08 18:53:58 +00:00
if ( mangled_property [ 0 ] ! = 0 ) {
* prop_name = mangled_property ;
2013-01-14 08:23:22 +00:00
if ( prop_len ) {
* prop_len = len ;
2005-12-17 15:51:52 +00:00
}
2006-07-24 17:58:32 +00:00
return SUCCESS ;
2002-06-23 15:46:58 +00:00
}
2006-07-24 22:36:21 +00:00
if ( len < 3 | | mangled_property [ 1 ] = = 0 ) {
2006-07-24 17:58:32 +00:00
zend_error ( E_NOTICE , " Illegal member variable name " ) ;
* prop_name = mangled_property ;
2013-01-14 08:23:22 +00:00
if ( prop_len ) {
* prop_len = len ;
2014-02-17 13:59:18 +00:00
}
2006-07-24 17:58:32 +00:00
return FAILURE ;
2003-06-08 18:53:58 +00:00
}
2014-02-10 06:04:30 +00:00
2013-01-14 08:23:22 +00:00
class_name_len = zend_strnlen ( mangled_property + 1 , - - len - 1 ) + 1 ;
2006-07-24 17:58:32 +00:00
if ( class_name_len > = len | | mangled_property [ class_name_len ] ! = 0 ) {
zend_error ( E_NOTICE , " Corrupt member variable name " ) ;
* prop_name = mangled_property ;
2013-01-14 08:23:22 +00:00
if ( prop_len ) {
* prop_len = len + 1 ;
2003-09-03 21:21:18 +00:00
}
2006-07-24 17:58:32 +00:00
return FAILURE ;
2003-09-03 21:21:18 +00:00
}
2013-01-14 08:23:22 +00:00
* class_name = mangled_property + 1 ;
* prop_name = ( * class_name ) + class_name_len ;
if ( prop_len ) {
* prop_len = len - class_name_len ;
}
2006-07-24 17:58:32 +00:00
return SUCCESS ;
1999-07-27 20:34:31 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-07-27 20:34:31 +00:00
2014-07-22 09:55:07 +00:00
static zend_constant * zend_get_ct_const ( zend_string * name , int all_internal_constants_substitution TSRMLS_DC ) /* { { { */
2002-12-06 17:09:44 +00:00
{
2006-03-15 09:04:36 +00:00
zend_constant * c = NULL ;
2014-02-10 06:04:30 +00:00
char * lookup_name ;
2006-03-15 09:04:36 +00:00
2014-07-22 09:55:07 +00:00
if ( name - > val [ 0 ] = = ' \\ ' ) {
c = zend_hash_str_find_ptr ( EG ( zend_constants ) , name - > val + 1 , name - > len - 1 ) ;
if ( ! c ) {
lookup_name = zend_str_tolower_dup ( name - > val + 1 , name - > len - 1 ) ;
c = zend_hash_str_find_ptr ( EG ( zend_constants ) , lookup_name , name - > len - 1 ) ;
2008-11-04 15:58:55 +00:00
efree ( lookup_name ) ;
2014-07-22 09:55:07 +00:00
if ( c & & ( c - > flags & CONST_CT_SUBST ) & & ! ( c - > flags & CONST_CS ) ) {
2008-07-28 14:12:19 +00:00
return c ;
2006-03-15 09:04:36 +00:00
}
2014-07-22 09:55:07 +00:00
return NULL ;
2006-03-15 09:04:36 +00:00
}
2014-07-22 09:55:07 +00:00
} else if ( ( c = zend_hash_find_ptr ( EG ( zend_constants ) , name ) ) = = NULL ) {
lookup_name = zend_str_tolower_dup ( name - > val , name - > len ) ;
c = zend_hash_str_find_ptr ( EG ( zend_constants ) , lookup_name , name - > len ) ;
2006-03-15 09:04:36 +00:00
efree ( lookup_name ) ;
2014-07-22 09:55:07 +00:00
if ( c & & ( c - > flags & CONST_CT_SUBST ) & & ! ( c - > flags & CONST_CS ) ) {
return c ;
}
2008-07-28 14:12:19 +00:00
return NULL ;
2002-12-06 17:09:44 +00:00
}
2014-07-22 09:55:07 +00:00
2007-09-28 19:52:53 +00:00
if ( c - > flags & CONST_CT_SUBST ) {
return c ;
2002-12-06 17:09:44 +00:00
}
2008-08-29 10:17:08 +00:00
if ( all_internal_constants_substitution & &
2008-07-31 14:27:43 +00:00
( c - > flags & CONST_PERSISTENT ) & &
2008-07-25 04:54:08 +00:00
! ( CG ( compiler_options ) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION ) & &
2014-04-03 23:55:27 +00:00
! Z_CONSTANT ( c - > value ) ) {
2008-07-25 04:54:08 +00:00
return c ;
2002-12-06 17:09:44 +00:00
}
2007-09-28 19:52:53 +00:00
return NULL ;
2002-12-06 17:09:44 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2002-12-06 17:09:44 +00:00
2008-08-29 10:17:08 +00:00
static int zend_constant_ct_subst ( znode * result , zval * const_name , int all_internal_constants_substitution TSRMLS_DC ) /* { { { */
2002-12-06 17:09:44 +00:00
{
2014-07-22 09:55:07 +00:00
zend_constant * c = zend_get_ct_const ( Z_STR_P ( const_name ) ,
all_internal_constants_substitution TSRMLS_CC ) ;
2014-02-17 13:59:18 +00:00
2007-09-28 19:52:53 +00:00
if ( c ) {
2006-03-15 09:04:36 +00:00
result - > op_type = IS_CONST ;
2014-08-26 09:06:19 +00:00
ZVAL_DUP ( & result - > u . constant , & c - > value ) ;
2006-03-15 09:04:36 +00:00
return 1 ;
2014-02-17 13:59:18 +00:00
}
2006-03-15 09:04:36 +00:00
return 0 ;
2002-12-06 17:09:44 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2002-12-06 17:09:44 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
void zend_init_list ( void * result , void * item TSRMLS_DC ) /* { { { */
2003-03-29 11:19:38 +00:00
{
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
void * * list = emalloc ( sizeof ( void * ) * 2 ) ;
2003-03-29 11:19:38 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
list [ 0 ] = item ;
list [ 1 ] = NULL ;
2003-03-29 11:19:38 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
* ( void * * ) result = list ;
}
/* }}} */
2004-04-21 08:44:37 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
void zend_add_to_list ( void * result , void * item TSRMLS_DC ) /* { { { */
{
void * * list = * ( void * * ) result ;
size_t n = 0 ;
2012-08-28 12:06:18 +00:00
2012-12-25 06:23:08 +00:00
if ( list ) {
while ( list [ n ] ) {
n + + ;
}
2004-02-25 09:25:37 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
list = erealloc ( list , sizeof ( void * ) * ( n + 2 ) ) ;
2004-02-12 13:49:55 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
list [ n ] = item ;
list [ n + 1 ] = NULL ;
2013-09-26 16:39:17 +00:00
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
* ( void * * ) result = list ;
}
/* }}} */
2013-09-26 16:39:17 +00:00
2009-07-27 14:11:53 +00:00
void zend_do_extended_info ( TSRMLS_D ) /* { { { */
1999-04-07 18:10:10 +00:00
{
zend_op * opline ;
2013-09-26 16:39:17 +00:00
2008-03-18 08:36:30 +00:00
if ( ! ( CG ( compiler_options ) & ZEND_COMPILE_EXTENDED_INFO ) ) {
1999-04-07 18:10:10 +00:00
return ;
}
2013-09-26 16:39:17 +00:00
2001-07-28 10:51:54 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2007-11-09 13:34:39 +00:00
1999-04-07 18:10:10 +00:00
opline - > opcode = ZEND_EXT_STMT ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
2012-03-02 03:32:12 +00:00
2009-07-27 14:11:53 +00:00
void zend_do_extended_fcall_begin ( TSRMLS_D ) /* { { { */
1999-04-07 18:10:10 +00:00
{
zend_op * opline ;
2012-03-02 03:32:12 +00:00
2008-03-18 08:36:30 +00:00
if ( ! ( CG ( compiler_options ) & ZEND_COMPILE_EXTENDED_INFO ) ) {
1999-04-07 18:10:10 +00:00
return ;
}
2012-03-02 03:32:12 +00:00
2001-07-28 10:51:54 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2012-03-02 03:32:12 +00:00
1999-04-07 18:10:10 +00:00
opline - > opcode = ZEND_EXT_FCALL_BEGIN ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
2012-03-02 03:32:12 +00:00
2009-07-27 14:11:53 +00:00
void zend_do_extended_fcall_end ( TSRMLS_D ) /* { { { */
1999-04-07 18:10:10 +00:00
{
zend_op * opline ;
2012-03-02 03:32:12 +00:00
2008-03-18 08:36:30 +00:00
if ( ! ( CG ( compiler_options ) & ZEND_COMPILE_EXTENDED_INFO ) ) {
1999-04-07 18:10:10 +00:00
return ;
}
2006-05-09 23:53:23 +00:00
2001-07-28 10:51:54 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
opline - > opcode = ZEND_EXT_FCALL_END ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-02-10 06:04:30 +00:00
zend_bool zend_is_auto_global ( zend_string * name TSRMLS_DC ) /* { { { */
2003-03-02 13:33:31 +00:00
{
zend_auto_global * auto_global ;
2014-02-10 06:04:30 +00:00
if ( ( auto_global = zend_hash_find_ptr ( CG ( auto_globals ) , name ) ) ! = NULL ) {
2003-03-02 13:33:31 +00:00
if ( auto_global - > armed ) {
2014-02-10 06:04:30 +00:00
auto_global - > armed = auto_global - > auto_global_callback ( auto_global - > name TSRMLS_CC ) ;
2013-01-28 02:02:51 +00:00
}
2003-03-02 13:33:31 +00:00
return 1 ;
}
return 0 ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
2003-03-02 13:33:31 +00:00
2014-02-10 06:04:30 +00:00
int zend_register_auto_global ( zend_string * name , zend_bool jit , zend_auto_global_callback auto_global_callback TSRMLS_DC ) /* { { { */
2001-08-08 17:18:16 +00:00
{
2003-03-02 10:04:53 +00:00
zend_auto_global auto_global ;
2014-04-10 11:50:25 +00:00
int retval ;
2003-03-02 10:04:53 +00:00
2014-02-10 06:04:30 +00:00
auto_global . name = zend_new_interned_string ( name TSRMLS_CC ) ;
2003-03-02 10:04:53 +00:00
auto_global . auto_global_callback = auto_global_callback ;
2010-07-08 14:05:11 +00:00
auto_global . jit = jit ;
2003-03-02 10:04:53 +00:00
2014-04-10 11:50:25 +00:00
retval = zend_hash_add_mem ( CG ( auto_globals ) , name , & auto_global , sizeof ( zend_auto_global ) ) ! = NULL ? SUCCESS : FAILURE ;
2014-08-25 19:21:16 +00:00
zend_string_release ( auto_global . name ) ;
2014-04-10 11:50:25 +00:00
return retval ;
2001-08-08 17:18:16 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2001-08-08 17:18:16 +00:00
2010-07-08 14:05:11 +00:00
ZEND_API void zend_activate_auto_globals ( TSRMLS_D ) /* { { { */
{
2014-07-22 14:55:34 +00:00
zend_auto_global * auto_global ;
ZEND_HASH_FOREACH_PTR ( CG ( auto_globals ) , auto_global ) {
if ( auto_global - > jit ) {
auto_global - > armed = 1 ;
} else if ( auto_global - > auto_global_callback ) {
auto_global - > armed = auto_global - > auto_global_callback ( auto_global - > name TSRMLS_CC ) ;
2002-11-23 20:44:12 +00:00
} else {
2014-07-22 14:55:34 +00:00
auto_global - > armed = 0 ;
2005-05-26 13:46:17 +00:00
}
2014-07-22 14:55:34 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2010-07-08 14:05:11 +00:00
}
/* }}} */
2010-11-03 15:40:24 +00:00
2014-07-27 10:45:38 +00:00
int zendlex ( zend_parser_stack_elem * elem TSRMLS_DC ) /* { { { */
1999-04-07 18:10:10 +00:00
{
2014-07-26 18:54:41 +00:00
zval zv ;
1999-04-07 18:10:10 +00:00
int retval ;
2001-08-06 14:36:46 +00:00
if ( CG ( increment_lineno ) ) {
CG ( zend_lineno ) + + ;
CG ( increment_lineno ) = 0 ;
}
2007-05-18 13:12:05 +00:00
again :
2014-07-26 18:54:41 +00:00
ZVAL_UNDEF ( & zv ) ;
retval = lex_scan ( & zv TSRMLS_CC ) ;
2002-11-30 11:20:25 +00:00
switch ( retval ) {
1999-04-22 23:08:42 +00:00
case T_COMMENT :
2003-04-02 16:13:12 +00:00
case T_DOC_COMMENT :
1999-04-22 23:08:42 +00:00
case T_OPEN_TAG :
1999-04-07 18:10:10 +00:00
case T_WHITESPACE :
2003-05-29 09:01:55 +00:00
goto again ;
1999-04-22 23:08:42 +00:00
case T_CLOSE_TAG :
2007-05-18 13:12:05 +00:00
if ( LANG_SCNG ( yy_text ) [ LANG_SCNG ( yy_leng ) - 1 ] ! = ' > ' ) {
2001-08-06 14:36:46 +00:00
CG ( increment_lineno ) = 1 ;
}
2008-11-25 09:56:32 +00:00
if ( CG ( has_bracketed_namespaces ) & & ! CG ( in_namespace ) ) {
2013-01-28 02:02:51 +00:00
goto again ;
2008-11-25 09:56:32 +00:00
}
1999-04-07 18:10:10 +00:00
retval = ' ; ' ; /* implicit ; */
break ;
1999-04-22 23:08:42 +00:00
case T_OPEN_TAG_WITH_ECHO :
retval = T_ECHO ;
1999-04-07 18:10:10 +00:00
break ;
}
2014-07-26 18:54:41 +00:00
if ( Z_TYPE ( zv ) ! = IS_UNDEF ) {
2014-07-27 10:45:38 +00:00
elem - > ast = zend_ast_create_zval ( & zv ) ;
2014-07-26 18:54:41 +00:00
}
2006-05-09 23:53:23 +00:00
1999-04-07 18:10:10 +00:00
return retval ;
}
2009-07-27 14:11:53 +00:00
/* }}} */
2003-02-01 01:49:15 +00:00
2009-07-27 14:11:53 +00:00
ZEND_API void zend_initialize_class_data ( zend_class_entry * ce , zend_bool nullify_handlers TSRMLS_DC ) /* { { { */
2003-02-10 16:11:24 +00:00
{
2003-02-10 16:46:05 +00:00
zend_bool persistent_hashes = ( ce - > type = = ZEND_INTERNAL_CLASS ) ? 1 : 0 ;
2003-11-13 06:40:34 +00:00
dtor_func_t zval_ptr_dtor_func = ( ( persistent_hashes ) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR ) ;
2003-02-10 16:46:05 +00:00
2003-02-10 16:11:24 +00:00
ce - > refcount = 1 ;
2014-07-22 14:55:34 +00:00
ce - > ce_flags = ZEND_ACC_CONSTANTS_UPDATED ;
2003-03-31 20:42:01 +00:00
2010-05-24 14:11:39 +00:00
ce - > default_properties_table = NULL ;
ce - > default_static_members_table = NULL ;
2014-04-21 14:25:34 +00:00
zend_hash_init_ex ( & ce - > properties_info , 8 , NULL , ( persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info ) , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ce - > constants_table , 8 , NULL , zval_ptr_dtor_func , persistent_hashes , 0 ) ;
zend_hash_init_ex ( & ce - > function_table , 8 , NULL , ZEND_FUNCTION_DTOR , persistent_hashes , 0 ) ;
2003-02-10 16:11:24 +00:00
2005-12-01 11:48:17 +00:00
if ( ce - > type = = ZEND_INTERNAL_CLASS ) {
# ifdef ZTS
int n = zend_hash_num_elements ( CG ( class_table ) ) ;
2010-05-24 17:07:52 +00:00
if ( CG ( static_members_table ) & & n > = CG ( last_static_member ) ) {
2005-12-01 11:48:17 +00:00
/* Support for run-time declaration: dl() */
CG ( last_static_member ) = n + 1 ;
2014-04-09 19:40:01 +00:00
CG ( static_members_table ) = realloc ( CG ( static_members_table ) , ( n + 1 ) * sizeof ( zval * ) ) ;
2010-05-24 17:07:52 +00:00
CG ( static_members_table ) [ n ] = NULL ;
2003-03-29 11:19:38 +00:00
}
2014-04-09 19:40:01 +00:00
ce - > static_members_table = ( zval * ) ( zend_intptr_t ) n ;
2005-12-01 11:48:17 +00:00
# else
2010-05-24 14:11:39 +00:00
ce - > static_members_table = NULL ;
2005-12-01 11:48:17 +00:00
# endif
} else {
2010-05-24 17:07:52 +00:00
ce - > static_members_table = ce - > default_static_members_table ;
2010-09-15 07:38:52 +00:00
ce - > info . user . doc_comment = NULL ;
2003-07-16 09:13:47 +00:00
}
2004-02-25 09:25:37 +00:00
2010-05-24 14:11:39 +00:00
ce - > default_properties_count = 0 ;
ce - > default_static_members_count = 0 ;
2003-02-10 16:11:24 +00:00
if ( nullify_handlers ) {
ce - > constructor = NULL ;
ce - > destructor = NULL ;
ce - > clone = NULL ;
ce - > __get = NULL ;
ce - > __set = NULL ;
2005-07-07 16:07:09 +00:00
ce - > __unset = NULL ;
ce - > __isset = NULL ;
2003-02-10 16:11:24 +00:00
ce - > __call = NULL ;
2007-09-29 08:52:40 +00:00
ce - > __callstatic = NULL ;
2006-05-09 23:53:23 +00:00
ce - > __tostring = NULL ;
2003-02-10 16:11:24 +00:00
ce - > create_object = NULL ;
2003-12-28 15:18:05 +00:00
ce - > get_iterator = NULL ;
ce - > iterator_funcs . funcs = NULL ;
ce - > interface_gets_implemented = NULL ;
2007-09-29 09:34:24 +00:00
ce - > get_static_method = NULL ;
2003-12-28 15:18:05 +00:00
ce - > parent = NULL ;
ce - > num_interfaces = 0 ;
ce - > interfaces = NULL ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
ce - > num_traits = 0 ;
ce - > traits = NULL ;
ce - > trait_aliases = NULL ;
ce - > trait_precedences = NULL ;
2005-02-23 11:15:51 +00:00
ce - > serialize = NULL ;
ce - > unserialize = NULL ;
2005-03-07 22:23:14 +00:00
ce - > serialize_func = NULL ;
ce - > unserialize_func = NULL ;
2014-02-20 01:07:34 +00:00
ce - > __debugInfo = NULL ;
2010-09-15 07:38:52 +00:00
if ( ce - > type = = ZEND_INTERNAL_CLASS ) {
ce - > info . internal . module = NULL ;
ce - > info . internal . builtin_functions = NULL ;
}
2003-02-10 16:11:24 +00:00
}
2003-03-29 11:19:38 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2003-03-29 11:19:38 +00:00
2014-08-29 05:05:58 +00:00
uint32_t zend_get_class_fetch_type ( zend_string * name ) /* { { { */
{
2014-08-29 05:19:14 +00:00
if ( zend_string_equals_literal_ci ( name , " self " ) ) {
2013-01-28 02:02:51 +00:00
return ZEND_FETCH_CLASS_SELF ;
2014-08-29 05:19:14 +00:00
} else if ( zend_string_equals_literal_ci ( name , " parent " ) ) {
2003-08-03 08:21:08 +00:00
return ZEND_FETCH_CLASS_PARENT ;
2014-08-29 05:19:14 +00:00
} else if ( zend_string_equals_literal_ci ( name , " static " ) ) {
2007-09-29 07:28:34 +00:00
return ZEND_FETCH_CLASS_STATIC ;
2003-08-03 08:21:08 +00:00
} else {
return ZEND_FETCH_CLASS_DEFAULT ;
2011-09-23 15:08:11 +00:00
}
2003-08-03 08:21:08 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2011-09-23 15:08:11 +00:00
2014-08-25 19:21:16 +00:00
ZEND_API zend_string * zend_get_compiled_variable_name ( const zend_op_array * op_array , uint32_t var ) /* { { { */
2011-09-23 15:08:11 +00:00
{
2014-03-27 12:00:25 +00:00
return op_array - > vars [ EX_VAR_TO_NUM ( var ) ] ;
2005-01-22 02:29:18 +00:00
}
2009-07-27 14:11:53 +00:00
/* }}} */
2011-09-23 15:08:11 +00:00
2014-08-29 05:05:58 +00:00
zend_ast * zend_ast_append_str ( zend_ast * left_ast , zend_ast * right_ast ) /* { { { */
{
2014-07-26 19:53:50 +00:00
zval * left_zv = zend_ast_get_zval ( left_ast ) ;
zend_string * left = Z_STR_P ( left_zv ) ;
zend_string * right = zend_ast_get_str ( right_ast ) ;
2007-12-07 17:11:24 +00:00
2014-07-26 19:53:50 +00:00
zend_string * result ;
size_t left_len = left - > len ;
size_t len = left_len + right - > len + 1 ; /* left\right */
2014-08-25 19:21:16 +00:00
result = zend_string_realloc ( left , len , 0 ) ;
2014-07-26 19:53:50 +00:00
result - > val [ left_len ] = ' \\ ' ;
memcpy ( & result - > val [ left_len + 1 ] , right - > val , right - > len ) ;
result - > val [ len ] = ' \0 ' ;
2014-08-25 19:21:16 +00:00
zend_string_release ( right ) ;
2014-07-26 19:53:50 +00:00
ZVAL_STR ( left_zv , result ) ;
return left_ast ;
2007-09-28 19:52:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2007-09-28 19:52:53 +00:00
2014-07-30 17:12:48 +00:00
/* A hacky way that is used to store the doc comment for properties */
2014-08-29 18:52:26 +00:00
zend_ast * zend_ast_append_doc_comment ( zend_ast * list TSRMLS_DC ) /* { { { */
2014-08-29 05:05:58 +00:00
{
2014-07-30 17:12:48 +00:00
if ( CG ( doc_comment ) ) {
list = zend_ast_list_add ( list , zend_ast_create_zval_from_str ( CG ( doc_comment ) ) ) ;
CG ( doc_comment ) = NULL ;
2011-09-23 15:08:11 +00:00
}
2014-07-30 17:12:48 +00:00
return list ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-30 17:12:48 +00:00
2008-11-25 09:56:32 +00:00
void zend_verify_namespace ( TSRMLS_D ) /* { { { */
2007-09-28 19:52:53 +00:00
{
2008-11-25 09:56:32 +00:00
if ( CG ( has_bracketed_namespaces ) & & ! CG ( in_namespace ) ) {
2013-10-19 21:22:20 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " No code may exist outside of namespace {} " ) ;
2011-09-23 15:08:11 +00:00
}
2008-11-25 09:56:32 +00:00
}
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
static void zend_reset_import_tables ( TSRMLS_D ) /* { { { */
{
2007-09-28 19:52:53 +00:00
if ( CG ( current_import ) ) {
zend_hash_destroy ( CG ( current_import ) ) ;
efree ( CG ( current_import ) ) ;
CG ( current_import ) = NULL ;
2011-09-23 15:08:11 +00:00
}
2013-07-16 18:39:33 +00:00
if ( CG ( current_import_function ) ) {
zend_hash_destroy ( CG ( current_import_function ) ) ;
efree ( CG ( current_import_function ) ) ;
CG ( current_import_function ) = NULL ;
}
2011-09-23 15:08:11 +00:00
2013-07-23 18:21:48 +00:00
if ( CG ( current_import_const ) ) {
zend_hash_destroy ( CG ( current_import_const ) ) ;
efree ( CG ( current_import_const ) ) ;
CG ( current_import_const ) = NULL ;
}
2007-09-28 19:52:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
static void zend_end_namespace ( TSRMLS_D ) /* { { { */ {
2014-07-28 13:29:56 +00:00
CG ( in_namespace ) = 0 ;
zend_reset_import_tables ( TSRMLS_C ) ;
2014-07-28 20:38:26 +00:00
if ( CG ( current_namespace ) ) {
2014-08-25 19:21:16 +00:00
zend_string_release ( CG ( current_namespace ) ) ;
2014-07-28 20:38:26 +00:00
CG ( current_namespace ) = NULL ;
2014-07-28 13:29:56 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-09-26 16:39:17 +00:00
2008-11-25 09:56:32 +00:00
void zend_do_end_compilation ( TSRMLS_D ) /* { { { */
{
CG ( has_bracketed_namespaces ) = 0 ;
2014-07-28 13:29:56 +00:00
zend_end_namespace ( TSRMLS_C ) ;
2008-11-25 09:56:32 +00:00
}
/* }}} */
2013-09-26 16:39:17 +00:00
2008-02-12 01:17:48 +00:00
/* {{{ zend_dirname
Returns directory name component of path */
2008-02-12 00:21:15 +00:00
ZEND_API size_t zend_dirname ( char * path , size_t len )
{
register char * end = path + len - 1 ;
unsigned int len_adjust = 0 ;
2011-09-23 15:08:11 +00:00
2008-02-12 00:21:15 +00:00
# ifdef PHP_WIN32
/* Note that on Win32 CWD is per drive (heritage from CP/M).
* This means dirname ( " c:foo " ) maps to " c:. " or " c: " - which means CWD on C : drive .
*/
if ( ( 2 < = len ) & & isalpha ( ( int ) ( ( unsigned char * ) path ) [ 0 ] ) & & ( ' : ' = = path [ 1 ] ) ) {
/* Skip over the drive spec (if any) so as not to change */
path + = 2 ;
len_adjust + = 2 ;
if ( 2 = = len ) {
/* Return "c:" on Win32 for dirname("c:").
2013-01-28 02:02:51 +00:00
* It would be more consistent to return " c:. "
2008-02-12 00:21:15 +00:00
* but that would require making the string * longer * .
*/
return len ;
}
}
# elif defined(NETWARE)
/*
2013-06-10 21:20:18 +00:00
* Find the first occurrence of : from the left
2008-02-12 00:21:15 +00:00
* move the path pointer to the position just after :
* increment the len_adjust to the length of path till colon character ( inclusive )
* If there is no character beyond : simple return len
*/
char * colonpos = NULL ;
colonpos = strchr ( path , ' : ' ) ;
if ( colonpos ! = NULL ) {
len_adjust = ( ( colonpos - path ) + 1 ) ;
path + = len_adjust ;
if ( len_adjust = = len ) {
return len ;
}
2011-01-19 17:17:52 +00:00
}
2008-02-12 00:21:15 +00:00
# endif
if ( len = = 0 ) {
/* Illegal use of this function */
return 0 ;
}
/* Strip trailing slashes */
while ( end > = path & & IS_SLASH_P ( end ) ) {
end - - ;
}
if ( end < path ) {
/* The path only contained slashes */
path [ 0 ] = DEFAULT_SLASH ;
path [ 1 ] = ' \0 ' ;
return 1 + len_adjust ;
}
/* Strip filename */
while ( end > = path & & ! IS_SLASH_P ( end ) ) {
end - - ;
}
if ( end < path ) {
/* No slash found, therefore return '.' */
# ifdef NETWARE
if ( len_adjust = = 0 ) {
path [ 0 ] = ' . ' ;
path [ 1 ] = ' \0 ' ;
2008-08-03 11:48:20 +00:00
return 1 ; /* only one character */
2008-02-12 00:21:15 +00:00
} else {
path [ 0 ] = ' \0 ' ;
return len_adjust ;
}
# else
path [ 0 ] = ' . ' ;
path [ 1 ] = ' \0 ' ;
return 1 + len_adjust ;
# endif
}
/* Strip slashes which came before the file name */
while ( end > = path & & IS_SLASH_P ( end ) ) {
end - - ;
}
if ( end < path ) {
path [ 0 ] = DEFAULT_SLASH ;
path [ 1 ] = ' \0 ' ;
return 1 + len_adjust ;
}
* ( end + 1 ) = ' \0 ' ;
return ( size_t ) ( end + 1 - path ) + len_adjust ;
}
/* }}} */
2008-02-12 01:17:48 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_bool zend_string_equals_str_ci ( zend_string * str1 , zend_string * str2 ) /* { { { */
{
2014-07-28 20:16:24 +00:00
return str1 - > len = = str2 - > len
& & ! zend_binary_strcasecmp ( str1 - > val , str1 - > len , str2 - > val , str2 - > len ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-28 20:16:24 +00:00
2014-08-29 05:05:58 +00:00
static void zend_adjust_for_fetch_type ( zend_op * opline , uint32_t type ) /* { { { */
{
2014-06-07 11:06:53 +00:00
switch ( type & BP_VAR_MASK ) {
case BP_VAR_R :
return ;
case BP_VAR_W :
opline - > opcode + = 3 ;
return ;
case BP_VAR_REF :
opline - > opcode + = 3 ;
opline - > extended_value | = ZEND_FETCH_MAKE_REF ;
return ;
case BP_VAR_RW :
opline - > opcode + = 6 ;
return ;
case BP_VAR_IS :
opline - > opcode + = 9 ;
return ;
case BP_VAR_FUNC_ARG :
opline - > opcode + = 12 ;
opline - > extended_value | = type > > BP_VAR_SHIFT ;
return ;
case BP_VAR_UNSET :
opline - > opcode + = 15 ;
return ;
EMPTY_SWITCH_DEFAULT_CASE ( )
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_make_var_result ( znode * result , zend_op * opline TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
opline - > result_type = IS_VAR ;
opline - > result . var = get_temporary_variable ( CG ( active_op_array ) ) ;
GET_NODE ( result , opline - > result ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-08-15 15:10:06 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_make_tmp_result ( znode * result , zend_op * opline TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
opline - > result_type = IS_TMP_VAR ;
opline - > result . var = get_temporary_variable ( CG ( active_op_array ) ) ;
GET_NODE ( result , opline - > result ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2011-09-23 15:08:11 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_emit_op ( znode * result , zend_uchar opcode , znode * op1 , znode * op2 TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = opcode ;
2014-02-10 06:04:30 +00:00
2014-06-07 11:06:53 +00:00
if ( op1 = = NULL ) {
SET_UNUSED ( opline - > op1 ) ;
} else {
SET_NODE ( opline - > op1 , op1 ) ;
}
2011-09-23 15:08:11 +00:00
2014-06-07 11:06:53 +00:00
if ( op2 = = NULL ) {
SET_UNUSED ( opline - > op2 ) ;
} else {
SET_NODE ( opline - > op2 , op2 ) ;
2011-09-23 15:08:11 +00:00
}
2014-08-15 15:10:06 +00:00
if ( result ) {
zend_make_var_result ( result , opline TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
}
return opline ;
2013-01-28 02:02:51 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2011-09-23 15:08:11 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_emit_op_tmp ( znode * result , zend_uchar opcode , znode * op1 , znode * op2 TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = opcode ;
2011-01-19 17:17:52 +00:00
2014-06-19 11:57:29 +00:00
if ( op1 = = NULL ) {
SET_UNUSED ( opline - > op1 ) ;
} else {
SET_NODE ( opline - > op1 , op1 ) ;
2004-01-28 10:25:45 +00:00
}
2014-06-14 16:30:18 +00:00
if ( op2 = = NULL ) {
SET_UNUSED ( opline - > op2 ) ;
} else {
SET_NODE ( opline - > op2 , op2 ) ;
2003-02-24 12:05:58 +00:00
}
2014-08-15 15:10:06 +00:00
zend_make_tmp_result ( result , opline TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
return opline ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-14 16:30:18 +00:00
2014-08-29 05:05:58 +00:00
static void zend_emit_tick ( TSRMLS_D ) /* { { { */
{
2014-07-09 22:00:48 +00:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_TICKS ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ;
opline - > extended_value = Z_LVAL ( CG ( declarables ) . ticks ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-09 22:00:48 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_op * zend_emit_op_data ( znode * value TSRMLS_DC ) /* { { { */
{
2014-07-28 20:03:16 +00:00
return zend_emit_op ( NULL , ZEND_OP_DATA , value , NULL TSRMLS_CC ) ;
2014-07-28 10:55:37 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-28 10:55:37 +00:00
2014-08-29 05:05:58 +00:00
static inline uint32_t zend_emit_jump ( uint32_t opnum_target TSRMLS_DC ) /* { { { */
{
2014-08-25 19:21:16 +00:00
uint32_t opnum = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
zend_op * opline = zend_emit_op ( NULL , ZEND_JMP , NULL , NULL TSRMLS_CC ) ;
2014-07-18 17:57:38 +00:00
opline - > op1 . opline_num = opnum_target ;
return opnum ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-18 17:57:38 +00:00
2014-08-29 05:05:58 +00:00
static inline uint32_t zend_emit_cond_jump ( zend_uchar opcode , znode * cond , uint32_t opnum_target TSRMLS_DC ) /* { { { */
{
2014-08-25 19:21:16 +00:00
uint32_t opnum = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
zend_op * opline = zend_emit_op ( NULL , opcode , cond , NULL TSRMLS_CC ) ;
2014-07-18 17:57:38 +00:00
opline - > op2 . opline_num = opnum_target ;
return opnum ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-18 17:57:38 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_update_jump_target ( uint32_t opnum_jump , uint32_t opnum_target TSRMLS_DC ) /* { { { */
{
2014-07-18 14:11:43 +00:00
zend_op * opline = & CG ( active_op_array ) - > opcodes [ opnum_jump ] ;
switch ( opline - > opcode ) {
case ZEND_JMP :
opline - > op1 . opline_num = opnum_target ;
break ;
case ZEND_JMPZ :
case ZEND_JMPNZ :
case ZEND_JMPZ_EX :
case ZEND_JMPNZ_EX :
opline - > op2 . opline_num = opnum_target ;
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-18 14:11:43 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_update_jump_target_to_next ( uint32_t opnum_jump TSRMLS_DC ) /* { { { */
{
2014-07-18 14:11:43 +00:00
zend_update_jump_target ( opnum_jump , get_next_op_number ( CG ( active_op_array ) ) TSRMLS_CC ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-18 14:11:43 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_op * zend_delayed_emit_op ( znode * result , zend_uchar opcode , znode * op1 , znode * op2 TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
zend_op tmp_opline ;
init_op ( & tmp_opline TSRMLS_CC ) ;
tmp_opline . opcode = opcode ;
SET_NODE ( tmp_opline . op1 , op1 ) ;
SET_NODE ( tmp_opline . op2 , op2 ) ;
if ( result ) {
zend_make_var_result ( result , & tmp_opline TSRMLS_CC ) ;
2002-11-23 20:44:12 +00:00
}
2002-12-07 21:46:12 +00:00
2014-08-15 15:10:06 +00:00
zend_stack_push ( & CG ( delayed_oplines_stack ) , & tmp_opline ) ;
return zend_stack_top ( & CG ( delayed_oplines_stack ) ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-08-15 15:10:06 +00:00
2014-08-29 05:05:58 +00:00
static inline uint32_t zend_delayed_compile_begin ( TSRMLS_D ) /* { { { */
{
2014-08-15 15:10:06 +00:00
return zend_stack_count ( & CG ( delayed_oplines_stack ) ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-08-15 15:10:06 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_delayed_compile_end ( uint32_t offset TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
zend_op * opline , * oplines = zend_stack_base ( & CG ( delayed_oplines_stack ) ) ;
2014-08-25 19:21:16 +00:00
uint32_t i , count = zend_stack_count ( & CG ( delayed_oplines_stack ) ) ;
2014-08-15 15:10:06 +00:00
ZEND_ASSERT ( count > offset ) ;
for ( i = offset ; i < count ; + + i ) {
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
memcpy ( opline , & oplines [ i ] , sizeof ( zend_op ) ) ;
2002-11-23 20:44:12 +00:00
}
2014-08-15 15:10:06 +00:00
CG ( delayed_oplines_stack ) . top = offset ;
return opline ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2002-12-09 12:10:17 +00:00
2014-08-29 05:05:58 +00:00
void zend_emit_final_return ( zval * zv TSRMLS_DC ) /* { { { */
{
2014-07-26 19:32:48 +00:00
znode zn ;
zend_bool returns_reference = ( CG ( active_op_array ) - > fn_flags & ZEND_ACC_RETURN_REFERENCE ) ! = 0 ;
zn . op_type = IS_CONST ;
if ( zv ) {
ZVAL_COPY_VALUE ( & zn . u . constant , zv ) ;
2003-01-02 13:58:08 +00:00
} else {
2014-07-26 19:32:48 +00:00
ZVAL_NULL ( & zn . u . constant ) ;
2002-12-09 12:10:17 +00:00
}
2002-12-26 16:27:59 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN , & zn , NULL TSRMLS_CC ) ;
2014-07-26 19:32:48 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-26 19:32:48 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_bool zend_is_variable ( zend_ast * ast ) /* { { { */
{
2014-06-19 11:57:29 +00:00
return ast - > kind = = ZEND_AST_VAR | | ast - > kind = = ZEND_AST_DIM
| | ast - > kind = = ZEND_AST_PROP | | ast - > kind = = ZEND_AST_STATIC_PROP
2014-06-07 11:06:53 +00:00
| | ast - > kind = = ZEND_AST_CALL | | ast - > kind = = ZEND_AST_METHOD_CALL
| | ast - > kind = = ZEND_AST_STATIC_CALL ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_bool zend_is_call ( zend_ast * ast ) /* { { { */
{
2014-06-07 11:06:53 +00:00
return ast - > kind = = ZEND_AST_CALL
| | ast - > kind = = ZEND_AST_METHOD_CALL
| | ast - > kind = = ZEND_AST_STATIC_CALL ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_bool zend_is_unticked_stmt ( zend_ast * ast ) /* { { { */
{
2014-07-09 22:00:48 +00:00
return ast - > kind = = ZEND_AST_STMT_LIST | | ast - > kind = = ZEND_AST_LABEL ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-09 22:00:48 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_bool zend_can_write_to_variable ( zend_ast * ast ) /* { { { */
{
2014-06-19 11:57:29 +00:00
while ( ast - > kind = = ZEND_AST_DIM | | ast - > kind = = ZEND_AST_PROP ) {
ast = ast - > child [ 0 ] ;
2003-03-29 11:19:38 +00:00
}
2014-06-19 11:57:29 +00:00
return zend_is_variable ( ast ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-19 11:57:29 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_bool zend_is_const_default_class_ref ( zend_ast * name_ast ) /* { { { */
{
2014-07-28 13:39:43 +00:00
zend_string * name ;
2014-07-14 21:03:53 +00:00
2014-06-28 16:03:26 +00:00
if ( name_ast - > kind ! = ZEND_AST_ZVAL ) {
2014-06-14 16:30:18 +00:00
return 0 ;
}
2014-07-14 21:03:53 +00:00
/* Fully qualified names are always default refs */
2014-07-19 21:44:33 +00:00
if ( ! name_ast - > attr ) {
2014-07-14 21:03:53 +00:00
return 1 ;
2003-03-29 11:19:38 +00:00
}
2014-07-14 21:03:53 +00:00
2014-07-28 13:39:43 +00:00
name = zend_ast_get_str ( name_ast ) ;
return ZEND_FETCH_CLASS_DEFAULT = = zend_get_class_fetch_type ( name ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-03-29 11:19:38 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_handle_numeric_op ( znode * node TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
if ( node - > op_type = = IS_CONST & & Z_TYPE ( node - > u . constant ) = = IS_STRING ) {
zend_ulong index ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-15 15:10:06 +00:00
if ( ZEND_HANDLE_NUMERIC ( Z_STR ( node - > u . constant ) , index ) ) {
zval_ptr_dtor ( & node - > u . constant ) ;
ZVAL_LONG ( & node - > u . constant , index ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
}
2014-06-19 11:57:29 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_set_class_name_op1 ( zend_op * opline , znode * class_node TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
if ( class_node - > op_type = = IS_CONST ) {
opline - > op1_type = IS_CONST ;
2014-07-19 21:30:07 +00:00
opline - > op1 . constant = zend_add_class_name_literal (
CG ( active_op_array ) , Z_STR ( class_node - > u . constant ) TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
} else {
SET_NODE ( opline - > op1 , class_node ) ;
}
2002-11-23 20:44:12 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2002-11-23 20:44:12 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_compile_class_ref ( znode * result , zend_ast * name_ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_op * opline ;
2014-07-29 21:17:54 +00:00
znode name_node ;
zend_compile_expr ( & name_node , name_ast TSRMLS_CC ) ;
2003-02-04 12:12:34 +00:00
2014-07-29 21:17:54 +00:00
if ( name_node . op_type = = IS_CONST ) {
zend_string * name = Z_STR ( name_node . u . constant ) ;
2014-08-25 19:21:16 +00:00
uint32_t fetch_type = zend_get_class_fetch_type ( name ) ;
2014-06-14 16:30:18 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_FETCH_CLASS , NULL , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
opline - > extended_value = fetch_type ;
2014-07-19 21:30:07 +00:00
if ( fetch_type = = ZEND_FETCH_CLASS_DEFAULT ) {
2014-08-25 19:21:16 +00:00
uint32_t type = name_ast - > kind = = ZEND_AST_ZVAL ? name_ast - > attr : ZEND_NAME_FQ ;
2014-07-19 21:30:07 +00:00
opline - > op2_type = IS_CONST ;
opline - > op2 . constant = zend_add_class_name_literal ( CG ( active_op_array ) ,
2014-07-29 21:17:54 +00:00
zend_resolve_class_name ( name , type TSRMLS_CC ) TSRMLS_CC ) ;
2003-03-18 16:30:23 +00:00
}
2014-07-29 21:17:54 +00:00
2014-08-25 19:21:16 +00:00
zend_string_release ( name ) ;
2014-06-14 16:30:18 +00:00
} else {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_FETCH_CLASS , NULL , & name_node TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
opline - > extended_value = ZEND_FETCH_CLASS_DEFAULT ;
2003-02-04 12:12:34 +00:00
}
2014-06-14 16:30:18 +00:00
return opline ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
static int zend_try_compile_cv ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * name_ast = ast - > child [ 0 ] ;
2014-06-28 16:03:26 +00:00
if ( name_ast - > kind = = ZEND_AST_ZVAL ) {
2014-06-07 11:06:53 +00:00
zend_string * name = zval_get_string ( zend_ast_get_zval ( name_ast ) ) ;
2014-06-19 11:57:29 +00:00
if ( zend_is_auto_global ( name TSRMLS_CC ) ) {
2014-08-25 19:21:16 +00:00
zend_string_release ( name ) ;
2014-06-07 11:06:53 +00:00
return FAILURE ;
2003-09-03 19:28:46 +00:00
}
2006-05-11 21:07:39 +00:00
2014-06-07 11:06:53 +00:00
result - > op_type = IS_CV ;
result - > u . op . var = lookup_cv ( CG ( active_op_array ) , name TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_literal ( name , " this " ) ) {
2014-06-07 11:06:53 +00:00
CG ( active_op_array ) - > this_var = result - > u . op . var ;
2005-06-09 17:20:44 +00:00
}
2014-06-07 11:06:53 +00:00
return SUCCESS ;
}
return FAILURE ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_compile_simple_var_no_cv ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * name_ast = ast - > child [ 0 ] ;
znode name_node ;
zend_op * opline ;
/* there is a chance someone is accessing $this */
2014-06-28 16:03:26 +00:00
if ( ast - > kind ! = ZEND_AST_ZVAL
2014-06-07 11:06:53 +00:00
& & CG ( active_op_array ) - > scope & & CG ( active_op_array ) - > this_var = = - 1
) {
2014-08-25 19:21:16 +00:00
zend_string * key = zend_string_init ( " this " , sizeof ( " this " ) - 1 , 0 ) ;
2014-06-07 11:06:53 +00:00
CG ( active_op_array ) - > this_var = lookup_cv ( CG ( active_op_array ) , key TSRMLS_CC ) ;
}
zend_compile_expr ( & name_node , name_ast TSRMLS_CC ) ;
2006-05-11 21:07:39 +00:00
2014-06-07 11:06:53 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_FETCH_R , & name_node , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > extended_value = ZEND_FETCH_LOCAL ;
if ( name_node . op_type = = IS_CONST ) {
if ( zend_is_auto_global ( Z_STR ( name_node . u . constant ) TSRMLS_CC ) ) {
opline - > extended_value = ZEND_FETCH_GLOBAL ;
2003-02-04 12:12:34 +00:00
}
}
2014-06-07 11:06:53 +00:00
return opline ;
2003-02-04 12:12:34 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-02-04 12:12:34 +00:00
2014-08-29 05:05:58 +00:00
static void zend_compile_simple_var ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
if ( zend_try_compile_cv ( result , ast TSRMLS_CC ) = = FAILURE ) {
zend_op * opline = zend_compile_simple_var_no_cv ( result , ast , type TSRMLS_CC ) ;
zend_adjust_for_fetch_type ( opline , type ) ;
2003-10-22 19:59:58 +00:00
}
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
static void zend_separate_if_call_and_write ( znode * node , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
if ( type ! = BP_VAR_R & & type ! = BP_VAR_IS & & zend_is_call ( ast ) ) {
2014-07-28 20:03:16 +00:00
zend_op * opline = zend_emit_op ( NULL , ZEND_SEPARATE , node , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > result_type = IS_VAR ;
opline - > result . var = opline - > op1 . var ;
2004-12-06 11:53:30 +00:00
}
2003-10-22 19:59:58 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-05-29 19:00:40 +00:00
2014-08-25 19:21:16 +00:00
void zend_delayed_compile_var ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) ;
2003-10-22 19:59:58 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_delayed_compile_dim ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
zend_ast * dim_ast = ast - > child [ 1 ] ;
2003-10-22 19:59:58 +00:00
2014-06-07 11:06:53 +00:00
znode var_node , dim_node ;
2004-01-28 09:13:41 +00:00
2014-08-15 15:10:06 +00:00
zend_delayed_compile_var ( & var_node , var_ast , type TSRMLS_CC ) ;
zend_separate_if_call_and_write ( & var_node , var_ast , type TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
if ( dim_ast = = NULL ) {
if ( type = = BP_VAR_R | | type = = BP_VAR_IS ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use [] for reading " ) ;
2003-10-22 19:59:58 +00:00
}
2014-06-07 11:06:53 +00:00
if ( type = = BP_VAR_UNSET ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use [] for unsetting " ) ;
2003-05-29 19:00:40 +00:00
}
2014-06-07 11:06:53 +00:00
dim_node . op_type = IS_UNUSED ;
} else {
zend_compile_expr ( & dim_node , dim_ast TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_handle_numeric_op ( & dim_node TSRMLS_CC ) ;
2003-05-29 19:00:40 +00:00
}
2004-01-28 09:13:41 +00:00
2014-08-15 15:10:06 +00:00
return zend_delayed_emit_op ( result , ZEND_FETCH_DIM_R , & var_node , & dim_node TSRMLS_CC ) ;
2003-05-29 19:00:40 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-05-29 19:00:40 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_op * zend_compile_dim_common ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-08-25 19:21:16 +00:00
uint32_t offset = zend_delayed_compile_begin ( TSRMLS_C ) ;
2014-08-15 15:10:06 +00:00
zend_delayed_compile_dim ( result , ast , type TSRMLS_CC ) ;
return zend_delayed_compile_end ( offset TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2010-08-11 09:38:41 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_dim ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_op * opline = zend_compile_dim_common ( result , ast , type TSRMLS_CC ) ;
zend_adjust_for_fetch_type ( opline , type ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
static zend_bool is_this_fetch ( zend_ast * ast ) /* { { { */
{
2014-08-25 17:46:21 +00:00
if ( ast - > kind = = ZEND_AST_VAR & & ast - > child [ 0 ] - > kind = = ZEND_AST_ZVAL ) {
zval * name = zend_ast_get_zval ( ast - > child [ 0 ] ) ;
2014-08-25 20:40:58 +00:00
return Z_TYPE_P ( name ) = = IS_STRING & & zend_string_equals_literal ( Z_STR_P ( name ) , " this " ) ;
2014-06-16 17:11:52 +00:00
}
2014-06-07 11:06:53 +00:00
2014-08-25 17:46:21 +00:00
return 0 ;
2014-04-14 09:24:43 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-04-14 09:24:43 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_delayed_compile_prop ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * obj_ast = ast - > child [ 0 ] ;
zend_ast * prop_ast = ast - > child [ 1 ] ;
2010-05-24 14:11:39 +00:00
2014-06-07 11:06:53 +00:00
znode obj_node , prop_node ;
zend_op * opline ;
2003-03-05 11:14:44 +00:00
2014-06-07 11:06:53 +00:00
if ( is_this_fetch ( obj_ast ) ) {
obj_node . op_type = IS_UNUSED ;
} else {
2014-08-15 15:10:06 +00:00
zend_delayed_compile_var ( & obj_node , obj_ast , type TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
zend_separate_if_call_and_write ( & obj_node , obj_ast , type TSRMLS_CC ) ;
2008-08-24 18:22:33 +00:00
}
2014-08-15 15:10:06 +00:00
zend_compile_expr ( & prop_node , prop_ast TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
2014-08-15 15:10:06 +00:00
opline = zend_delayed_emit_op ( result , ZEND_FETCH_OBJ_R , & obj_node , & prop_node TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
if ( opline - > op2_type = = IS_CONST & & Z_TYPE ( CONSTANT ( opline - > op2 . constant ) ) = = IS_STRING ) {
2014-08-15 15:10:06 +00:00
zend_alloc_polymorphic_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2008-08-24 18:22:33 +00:00
}
2014-06-07 11:06:53 +00:00
return opline ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2000-06-09 14:40:14 +00:00
2014-08-29 05:05:58 +00:00
static zend_op * zend_compile_prop_common ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-08-25 19:21:16 +00:00
uint32_t offset = zend_delayed_compile_begin ( TSRMLS_C ) ;
2014-08-15 15:10:06 +00:00
zend_delayed_compile_prop ( result , ast , type TSRMLS_CC ) ;
return zend_delayed_compile_end ( offset TSRMLS_CC ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2010-05-24 14:11:39 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_prop ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_op * opline = zend_compile_prop_common ( result , ast , type TSRMLS_CC ) ;
zend_adjust_for_fetch_type ( opline , type ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-04-09 13:51:28 +00:00
2014-08-29 05:05:58 +00:00
zend_op * zend_compile_static_prop_common ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * class_ast = ast - > child [ 0 ] ;
zend_ast * prop_ast = ast - > child [ 1 ] ;
2010-05-24 14:11:39 +00:00
2014-06-14 16:30:18 +00:00
znode class_node , prop_node ;
2014-06-07 11:06:53 +00:00
zend_op * opline ;
2010-05-24 14:11:39 +00:00
2014-06-14 16:30:18 +00:00
if ( zend_is_const_default_class_ref ( class_ast ) ) {
2014-07-19 21:30:07 +00:00
class_node . op_type = IS_CONST ;
ZVAL_STR ( & class_node . u . constant , zend_resolve_class_name_ast ( class_ast TSRMLS_CC ) ) ;
2005-09-01 10:05:32 +00:00
} else {
2014-06-14 16:30:18 +00:00
zend_compile_class_ref ( & class_node , class_ast TSRMLS_CC ) ;
2005-09-01 10:05:32 +00:00
}
2011-01-19 17:17:52 +00:00
2014-06-07 11:06:53 +00:00
zend_compile_expr ( & prop_node , prop_ast TSRMLS_CC ) ;
2002-07-15 18:09:56 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_FETCH_R , & prop_node , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
if ( opline - > op1_type = = IS_CONST ) {
2014-08-15 15:10:06 +00:00
zend_alloc_polymorphic_cache_slot ( opline - > op1 . constant TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
}
if ( class_node . op_type = = IS_CONST ) {
opline - > op2_type = IS_CONST ;
2014-07-19 21:30:07 +00:00
opline - > op2 . constant = zend_add_class_name_literal (
CG ( active_op_array ) , Z_STR ( class_node . u . constant ) TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
} else {
SET_NODE ( opline - > op2 , & class_node ) ;
}
opline - > extended_value | = ZEND_FETCH_STATIC_MEMBER ;
2014-05-26 17:29:35 +00:00
2014-06-19 11:57:29 +00:00
return opline ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-05-26 17:29:35 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_static_prop ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_op * opline = zend_compile_static_prop_common ( result , ast , type TSRMLS_CC ) ;
zend_adjust_for_fetch_type ( opline , type ) ;
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2006-05-11 21:07:39 +00:00
2014-08-29 05:05:58 +00:00
static inline zend_uchar get_list_fetch_opcode ( zend_uchar op_type ) /* { { { */
{
2014-06-07 11:06:53 +00:00
switch ( op_type ) {
case IS_VAR :
case IS_CV :
return ZEND_FETCH_DIM_R ;
case IS_TMP_VAR :
case IS_CONST :
return ZEND_FETCH_DIM_TMP_VAR ;
EMPTY_SWITCH_DEFAULT_CASE ( )
2006-05-11 21:07:39 +00:00
}
2000-06-09 14:40:14 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2000-06-09 14:40:14 +00:00
2014-08-29 05:05:58 +00:00
static void zend_compile_list_assign ( znode * result , zend_ast * ast , znode * expr_node TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2005-11-23 09:26:43 +00:00
2014-07-27 20:26:06 +00:00
if ( list - > children = = 1 & & ! list - > child [ 0 ] ) {
2014-06-07 11:06:53 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use empty list " ) ;
2004-01-28 11:53:52 +00:00
}
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * var_ast = list - > child [ i ] ;
2014-06-07 11:06:53 +00:00
znode fetch_result , dim_node , var_node , assign_result ;
zend_op * opline ;
if ( var_ast = = NULL ) {
continue ;
}
dim_node . op_type = IS_CONST ;
ZVAL_LONG ( & dim_node . u . constant , i ) ;
2014-08-15 20:36:22 +00:00
if ( expr_node - > op_type = = IS_CONST ) {
Z_TRY_ADDREF ( expr_node - > u . constant ) ;
}
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( & fetch_result ,
2014-06-07 11:06:53 +00:00
get_list_fetch_opcode ( expr_node - > op_type ) , expr_node , & dim_node TSRMLS_CC ) ;
opline - > extended_value | = ZEND_FETCH_ADD_LOCK ;
if ( var_ast - > kind ! = ZEND_AST_LIST ) {
if ( is_this_fetch ( var_ast ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot re-assign $this " ) ;
}
zend_compile_var ( & var_node , var_ast , BP_VAR_W TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( & assign_result , ZEND_ASSIGN , & var_node , & fetch_result TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
zend_do_free ( & assign_result TSRMLS_CC ) ;
} else {
zend_compile_list_assign ( & assign_result , var_ast , & fetch_result TSRMLS_CC ) ;
zend_do_free ( & assign_result TSRMLS_CC ) ;
2014-06-16 21:15:51 +00:00
}
2014-04-14 09:24:43 +00:00
}
2014-06-07 11:06:53 +00:00
* result = * expr_node ;
2014-04-14 09:24:43 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-04-14 09:24:43 +00:00
2014-08-29 05:05:58 +00:00
void zend_ensure_writable_variable ( const zend_ast * ast ) /* { { { */
{
2014-06-07 11:06:53 +00:00
if ( ast - > kind = = ZEND_AST_CALL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Can't use function return value in write context " ) ;
}
if ( ast - > kind = = ZEND_AST_METHOD_CALL | | ast - > kind = = ZEND_AST_STATIC_CALL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Can't use method return value in write context " ) ;
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2006-06-07 09:21:06 +00:00
2014-06-14 16:30:18 +00:00
/* Detects $a... = $a pattern */
2014-08-29 05:05:58 +00:00
zend_bool zend_is_assign_to_self ( zend_ast * var_ast , zend_ast * expr_ast TSRMLS_DC ) /* { { { */
{
2014-06-28 16:03:26 +00:00
if ( expr_ast - > kind ! = ZEND_AST_VAR | | expr_ast - > child [ 0 ] - > kind ! = ZEND_AST_ZVAL ) {
2014-06-07 11:06:53 +00:00
return 0 ;
2006-06-07 09:21:06 +00:00
}
2013-01-28 02:02:51 +00:00
2014-06-14 16:30:18 +00:00
while ( zend_is_variable ( var_ast ) & & var_ast - > kind ! = ZEND_AST_VAR ) {
2014-06-07 11:06:53 +00:00
var_ast = var_ast - > child [ 0 ] ;
}
2014-05-26 17:29:35 +00:00
2014-06-28 16:03:26 +00:00
if ( var_ast - > kind ! = ZEND_AST_VAR | | var_ast - > child [ 0 ] - > kind ! = ZEND_AST_ZVAL ) {
2014-06-07 11:06:53 +00:00
return 0 ;
}
2013-01-28 02:02:51 +00:00
2014-06-07 11:06:53 +00:00
{
zend_string * name1 = zval_get_string ( zend_ast_get_zval ( var_ast - > child [ 0 ] ) ) ;
zend_string * name2 = zval_get_string ( zend_ast_get_zval ( expr_ast - > child [ 0 ] ) ) ;
2014-08-25 20:40:58 +00:00
zend_bool result = zend_string_equals ( name1 , name2 ) ;
2014-08-25 19:21:16 +00:00
zend_string_release ( name1 ) ;
zend_string_release ( name2 ) ;
2014-06-07 11:06:53 +00:00
return result ;
2006-06-07 09:21:06 +00:00
}
2003-03-05 11:14:44 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-03-05 11:14:44 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_assign ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
zend_ast * expr_ast = ast - > child [ 1 ] ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-06-07 11:06:53 +00:00
znode var_node , expr_node ;
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t offset ;
2014-06-07 11:06:53 +00:00
if ( is_this_fetch ( var_ast ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot re-assign $this " ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-06-07 11:06:53 +00:00
zend_ensure_writable_variable ( var_ast ) ;
switch ( var_ast - > kind ) {
case ZEND_AST_VAR :
case ZEND_AST_STATIC_PROP :
zend_compile_var ( & var_node , var_ast , BP_VAR_W TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( result , ZEND_ASSIGN , & var_node , & expr_node TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
return ;
case ZEND_AST_DIM :
2014-08-15 15:10:06 +00:00
offset = zend_delayed_compile_begin ( TSRMLS_C ) ;
zend_delayed_compile_dim ( result , var_ast , BP_VAR_W TSRMLS_CC ) ;
if ( zend_is_assign_to_self ( var_ast , expr_ast TSRMLS_CC ) ) {
/* $a[0] = $a should evaluate the right $a first */
zend_compile_simple_var_no_cv ( & expr_node , expr_ast , BP_VAR_R TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
} else {
2014-08-15 15:10:06 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-15 15:10:06 +00:00
opline = zend_delayed_compile_end ( offset TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > opcode = ZEND_ASSIGN_DIM ;
2014-08-15 15:27:57 +00:00
opline = zend_emit_op_data ( & expr_node TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > op2 . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op2_type = IS_VAR ;
return ;
case ZEND_AST_PROP :
2014-08-15 15:10:06 +00:00
offset = zend_delayed_compile_begin ( TSRMLS_C ) ;
zend_delayed_compile_prop ( result , var_ast , BP_VAR_W TSRMLS_CC ) ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
opline = zend_delayed_compile_end ( offset TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > opcode = ZEND_ASSIGN_OBJ ;
2014-08-15 15:27:57 +00:00
zend_emit_op_data ( & expr_node TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
return ;
case ZEND_AST_LIST :
2014-08-15 15:10:06 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
zend_compile_list_assign ( result , var_ast , & expr_node TSRMLS_CC ) ;
return ;
EMPTY_SWITCH_DEFAULT_CASE ( ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_emit_assign_znode ( zend_ast * var_ast , znode * value_node TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
znode dummy_node ;
zend_ast * assign_ast = zend_ast_create ( ZEND_AST_ASSIGN , var_ast ,
zend_ast_create_znode ( value_node ) ) ;
zend_compile_assign ( & dummy_node , assign_ast TSRMLS_CC ) ;
zend_do_free ( & dummy_node TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_assign_ref ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * target_ast = ast - > child [ 0 ] ;
zend_ast * source_ast = ast - > child [ 1 ] ;
2014-08-15 15:10:06 +00:00
znode target_node , source_node ;
2014-06-07 11:06:53 +00:00
zend_op * opline ;
2014-08-15 15:10:06 +00:00
if ( is_this_fetch ( target_ast ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot re-assign $this " ) ;
}
zend_ensure_writable_variable ( target_ast ) ;
zend_compile_var ( & target_node , target_ast , BP_VAR_W TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
zend_compile_var ( & source_node , source_ast , BP_VAR_REF TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
opline = zend_emit_op ( result , ZEND_ASSIGN_REF , & target_node , & source_node TSRMLS_CC ) ;
if ( ! result ) {
opline - > result_type | = EXT_TYPE_UNUSED ;
}
2014-06-07 11:06:53 +00:00
if ( zend_is_call ( source_ast ) ) {
opline - > extended_value = ZEND_RETURNS_FUNCTION ;
2014-07-27 20:26:06 +00:00
} else if ( source_ast - > kind = = ZEND_AST_NEW ) {
2014-08-26 20:53:41 +00:00
zend_error ( E_DEPRECATED , " Assigning the return value of new by reference is deprecated " ) ;
2014-06-07 11:06:53 +00:00
opline - > extended_value = ZEND_RETURNS_NEW ;
2011-10-09 11:13:27 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_emit_assign_ref_znode ( zend_ast * var_ast , znode * value_node TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
zend_ast * assign_ast = zend_ast_create ( ZEND_AST_ASSIGN_REF , var_ast ,
zend_ast_create_znode ( value_node ) ) ;
zend_compile_assign_ref ( NULL , assign_ast TSRMLS_CC ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2011-11-05 02:05:28 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_compound_assign ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
zend_ast * expr_ast = ast - > child [ 1 ] ;
2014-08-25 19:21:16 +00:00
uint32_t opcode = ast - > attr ;
2014-06-07 11:06:53 +00:00
znode var_node , expr_node ;
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t offset ;
2014-06-07 11:06:53 +00:00
zend_ensure_writable_variable ( var_ast ) ;
switch ( var_ast - > kind ) {
case ZEND_AST_VAR :
2014-07-19 11:03:58 +00:00
case ZEND_AST_STATIC_PROP :
2014-06-07 11:06:53 +00:00
zend_compile_var ( & var_node , var_ast , BP_VAR_RW TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( result , opcode , & var_node , & expr_node TSRMLS_CC ) ;
2012-12-25 06:23:08 +00:00
return ;
2014-06-07 11:06:53 +00:00
case ZEND_AST_DIM :
2014-08-15 15:10:06 +00:00
offset = zend_delayed_compile_begin ( TSRMLS_C ) ;
zend_delayed_compile_dim ( result , var_ast , BP_VAR_RW TSRMLS_CC ) ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
opline = zend_delayed_compile_end ( offset TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
opline - > opcode = opcode ;
2014-06-07 11:06:53 +00:00
opline - > extended_value = ZEND_ASSIGN_DIM ;
2014-08-15 15:27:57 +00:00
opline = zend_emit_op_data ( & expr_node TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > op2 . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline - > op2_type = IS_VAR ;
2012-12-25 06:23:08 +00:00
return ;
2014-06-07 11:06:53 +00:00
case ZEND_AST_PROP :
2014-08-15 15:10:06 +00:00
offset = zend_delayed_compile_begin ( TSRMLS_C ) ;
zend_delayed_compile_prop ( result , var_ast , BP_VAR_RW TSRMLS_CC ) ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2011-11-01 15:25:24 +00:00
2014-08-15 15:10:06 +00:00
opline = zend_delayed_compile_end ( offset TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
opline - > opcode = opcode ;
2014-06-07 11:06:53 +00:00
opline - > extended_value = ZEND_ASSIGN_OBJ ;
2014-08-15 15:27:57 +00:00
zend_emit_op_data ( & expr_node TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
return ;
EMPTY_SWITCH_DEFAULT_CASE ( )
}
2012-12-25 06:23:08 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2011-11-01 15:25:24 +00:00
2014-08-29 05:05:58 +00:00
uint32_t zend_compile_args ( zend_ast * ast , zend_function * fbc TSRMLS_DC ) /* { { { */
{
/* TODO.AST &var error */
2014-07-27 20:26:06 +00:00
zend_ast_list * args = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-06-07 11:06:53 +00:00
zend_bool uses_arg_unpack = 0 ;
2014-08-25 19:21:16 +00:00
uint32_t arg_count = 0 ; /* number of arguments not including unpacks */
2012-12-25 06:23:08 +00:00
2014-07-13 11:11:55 +00:00
for ( i = 0 ; i < args - > children ; + + i ) {
zend_ast * arg = args - > child [ i ] ;
2014-08-25 19:21:16 +00:00
uint32_t arg_num = i + 1 ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-13 11:11:55 +00:00
znode arg_node ;
2014-06-07 11:06:53 +00:00
zend_op * opline ;
zend_uchar opcode ;
zend_ulong flags = 0 ;
2014-07-13 11:11:55 +00:00
if ( arg - > kind = = ZEND_AST_UNPACK ) {
2014-06-07 11:06:53 +00:00
uses_arg_unpack = 1 ;
2014-07-22 18:41:45 +00:00
fbc = NULL ;
2014-06-07 11:06:53 +00:00
2014-07-13 11:11:55 +00:00
zend_compile_expr ( & arg_node , arg - > child [ 0 ] TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_SEND_UNPACK , & arg_node , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > op2 . num = arg_count ;
continue ;
}
if ( uses_arg_unpack ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" Cannot use positional argument after argument unpacking " ) ;
}
arg_count + + ;
2014-07-13 11:11:55 +00:00
if ( zend_is_variable ( arg ) ) {
if ( zend_is_call ( arg ) ) {
zend_compile_var ( & arg_node , arg , BP_VAR_R TSRMLS_CC ) ;
2014-08-26 10:22:03 +00:00
if ( arg_node . op_type & ( IS_CONST | IS_TMP_VAR ) ) {
/* Function call was converted into builtin instruction */
opcode = ZEND_SEND_VAL ;
} else {
opcode = ZEND_SEND_VAR_NO_REF ;
flags | = ZEND_ARG_SEND_FUNCTION ;
if ( fbc & & ARG_SHOULD_BE_SENT_BY_REF ( fbc , arg_num ) ) {
flags | = ZEND_ARG_SEND_BY_REF ;
if ( ARG_MAY_BE_SENT_BY_REF ( fbc , arg_num ) ) {
flags | = ZEND_ARG_SEND_SILENT ;
}
2014-06-07 11:06:53 +00:00
}
}
} else if ( fbc ) {
if ( ARG_SHOULD_BE_SENT_BY_REF ( fbc , arg_num ) ) {
2014-07-13 11:11:55 +00:00
zend_compile_var ( & arg_node , arg , BP_VAR_W TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opcode = ZEND_SEND_REF ;
} else {
2014-07-13 11:11:55 +00:00
zend_compile_var ( & arg_node , arg , BP_VAR_R TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opcode = ZEND_SEND_VAR ;
}
} else {
2014-07-13 11:11:55 +00:00
zend_compile_var ( & arg_node , arg ,
2014-06-07 11:06:53 +00:00
BP_VAR_FUNC_ARG | ( arg_num < < BP_VAR_SHIFT ) TSRMLS_CC ) ;
2014-07-22 14:55:34 +00:00
opcode = ZEND_SEND_VAR_EX ;
2014-06-07 11:06:53 +00:00
}
} else {
2014-07-13 11:11:55 +00:00
zend_compile_expr ( & arg_node , arg TSRMLS_CC ) ;
if ( arg_node . op_type & ( IS_VAR | IS_CV ) ) {
2014-06-07 11:06:53 +00:00
opcode = ZEND_SEND_VAR_NO_REF ;
2014-08-16 20:29:15 +00:00
if ( fbc & & ARG_MUST_BE_SENT_BY_REF ( fbc , arg_num ) ) {
2014-06-07 11:06:53 +00:00
flags | = ZEND_ARG_SEND_BY_REF ;
}
} else {
2014-07-22 14:55:34 +00:00
if ( fbc ) {
opcode = ZEND_SEND_VAL ;
if ( ARG_MUST_BE_SENT_BY_REF ( fbc , arg_num ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Only variables can be passed by reference " ) ;
}
} else {
opcode = ZEND_SEND_VAL_EX ;
2014-06-07 11:06:53 +00:00
}
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-06-07 11:06:53 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = opcode ;
2014-07-13 11:11:55 +00:00
SET_NODE ( opline - > op1 , & arg_node ) ;
2014-06-07 11:06:53 +00:00
SET_UNUSED ( opline - > op2 ) ;
opline - > op2 . opline_num = arg_num ;
if ( opcode = = ZEND_SEND_VAR_NO_REF ) {
if ( fbc ) {
flags | = ZEND_ARG_COMPILE_TIME_BOUND ;
}
opline - > extended_value = flags ;
2014-07-22 14:55:34 +00:00
} else if ( fbc ) {
opline - > extended_value = ZEND_ARG_COMPILE_TIME_BOUND ;
2010-07-06 11:40:17 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-06-07 11:06:53 +00:00
return arg_count ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_call_common ( znode * result , zend_ast * args_ast , zend_function * fbc TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_init = get_next_op_number ( CG ( active_op_array ) ) - 1 ;
uint32_t arg_count ;
uint32_t call_flags ;
2012-12-25 06:23:08 +00:00
2014-06-07 11:06:53 +00:00
zend_do_extended_fcall_begin ( TSRMLS_C ) ;
2013-01-28 02:02:51 +00:00
2014-07-13 11:11:55 +00:00
arg_count = zend_compile_args ( args_ast , fbc TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-22 14:55:34 +00:00
opline = & CG ( active_op_array ) - > opcodes [ opnum_init ] ;
2014-06-07 11:06:53 +00:00
opline - > extended_value = arg_count ;
2011-11-17 21:04:15 +00:00
2014-07-22 14:55:34 +00:00
call_flags = ( opline - > opcode = = ZEND_NEW ? ZEND_CALL_CTOR : 0 ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_DO_FCALL , NULL , NULL TSRMLS_CC ) ;
2014-07-22 14:55:34 +00:00
opline - > op1 . num = call_flags ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-06-07 11:06:53 +00:00
zend_do_extended_fcall_end ( TSRMLS_C ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2012-12-25 06:23:08 +00:00
2014-08-29 05:05:58 +00:00
zend_bool zend_compile_function_name ( znode * name_node , zend_ast * name_ast TSRMLS_DC ) /* { { { */
{
2014-07-28 13:16:35 +00:00
zend_string * orig_name = zend_ast_get_str ( name_ast ) ;
2014-07-22 11:25:47 +00:00
zend_bool is_fully_qualified ;
2012-12-25 06:23:08 +00:00
2014-06-28 20:27:06 +00:00
name_node - > op_type = IS_CONST ;
ZVAL_STR ( & name_node - > u . constant , zend_resolve_function_name (
2014-07-22 11:25:47 +00:00
orig_name , name_ast - > attr , & is_fully_qualified TSRMLS_CC ) ) ;
2011-11-17 21:04:15 +00:00
2014-07-28 20:38:26 +00:00
return ! is_fully_qualified & & CG ( current_namespace ) ;
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_ns_call ( znode * result , znode * name_node , zend_ast * args_ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_INIT_NS_FCALL_BY_NAME ;
SET_UNUSED ( opline - > op1 ) ;
opline - > op2_type = IS_CONST ;
opline - > op2 . constant = zend_add_ns_func_name_literal (
CG ( active_op_array ) , & name_node - > u . constant TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
2014-07-13 11:11:55 +00:00
zend_compile_call_common ( result , args_ast , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_dynamic_call ( znode * result , znode * name_node , zend_ast * args_ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_op * opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_INIT_FCALL_BY_NAME ;
SET_UNUSED ( opline - > op1 ) ;
if ( name_node - > op_type = = IS_CONST & & Z_TYPE ( name_node - > u . constant ) = = IS_STRING ) {
opline - > op2_type = IS_CONST ;
opline - > op2 . constant
= zend_add_func_name_literal ( CG ( active_op_array ) , & name_node - > u . constant TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
} else {
SET_NODE ( opline - > op2 , name_node ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-07-13 11:11:55 +00:00
zend_compile_call_common ( result , args_ast , NULL TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
static zend_bool zend_args_contain_unpack ( zend_ast_list * args ) /* { { { */
{
2014-08-25 17:28:33 +00:00
uint32_t i ;
2014-07-13 11:11:55 +00:00
for ( i = 0 ; i < args - > children ; + + i ) {
if ( args - > child [ i ] - > kind = = ZEND_AST_UNPACK ) {
2014-06-07 11:06:53 +00:00
return 1 ;
}
2013-02-21 10:18:41 +00:00
}
2014-06-07 11:06:53 +00:00
return 0 ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-02-21 10:18:41 +00:00
2014-08-29 05:05:58 +00:00
int zend_compile_func_strlen ( znode * result , zend_ast_list * args TSRMLS_DC ) /* { { { */
{
2014-07-22 21:11:12 +00:00
znode arg_node ;
if ( ( CG ( compiler_options ) & ZEND_COMPILE_NO_BUILTIN_STRLEN )
2014-07-27 20:26:06 +00:00
| | args - > children ! = 1 | | args - > child [ 0 ] - > kind = = ZEND_AST_UNPACK
2014-07-22 21:11:12 +00:00
) {
return FAILURE ;
2012-12-25 06:23:08 +00:00
}
2014-07-22 21:11:12 +00:00
2014-07-27 20:26:06 +00:00
zend_compile_expr ( & arg_node , args - > child [ 0 ] TSRMLS_CC ) ;
2014-08-26 10:22:03 +00:00
zend_emit_op_tmp ( result , ZEND_STRLEN , & arg_node , NULL TSRMLS_CC ) ;
2014-07-22 21:11:12 +00:00
return SUCCESS ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
int zend_compile_func_typecheck ( znode * result , zend_ast_list * args , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-07-22 21:11:12 +00:00
znode arg_node ;
zend_op * opline ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-27 20:26:06 +00:00
if ( args - > children ! = 1 | | args - > child [ 0 ] - > kind = = ZEND_AST_UNPACK ) {
2014-07-22 21:11:12 +00:00
return FAILURE ;
}
2014-07-27 20:26:06 +00:00
zend_compile_expr ( & arg_node , args - > child [ 0 ] TSRMLS_CC ) ;
2014-08-26 10:22:03 +00:00
opline = zend_emit_op_tmp ( result , ZEND_TYPE_CHECK , & arg_node , NULL TSRMLS_CC ) ;
2014-07-22 21:11:12 +00:00
opline - > extended_value = type ;
return SUCCESS ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2011-11-17 21:04:15 +00:00
2014-08-29 05:05:58 +00:00
int zend_compile_func_defined ( znode * result , zend_ast_list * args TSRMLS_DC ) /* { { { */
{
2014-07-22 21:27:00 +00:00
zend_string * name ;
zend_op * opline ;
2013-01-28 02:02:51 +00:00
2014-07-27 20:26:06 +00:00
if ( args - > children ! = 1 | | args - > child [ 0 ] - > kind ! = ZEND_AST_ZVAL ) {
2014-07-22 21:27:00 +00:00
return FAILURE ;
}
2010-05-02 18:47:27 +00:00
2014-07-27 20:26:06 +00:00
name = zval_get_string ( zend_ast_get_zval ( args - > child [ 0 ] ) ) ;
2014-07-22 21:27:00 +00:00
if ( zend_memrchr ( name - > val , ' \\ ' , name - > len ) | | zend_memrchr ( name - > val , ' : ' , name - > len ) ) {
2014-08-25 19:21:16 +00:00
zend_string_release ( name ) ;
2014-07-22 21:27:00 +00:00
return FAILURE ;
}
2012-12-25 06:23:08 +00:00
2014-08-26 10:22:03 +00:00
opline = zend_emit_op_tmp ( result , ZEND_DEFINED , NULL , NULL TSRMLS_CC ) ;
2014-07-22 21:27:00 +00:00
opline - > op1_type = IS_CONST ;
LITERAL_STR ( opline - > op1 , name ) ;
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( opline - > op1 . constant TSRMLS_CC ) ;
2013-01-28 02:02:51 +00:00
2014-07-22 21:27:00 +00:00
/* Lowercase constant name in a separate literal */
{
zval c ;
2014-08-25 19:21:16 +00:00
zend_string * lcname = zend_string_alloc ( name - > len , 0 ) ;
2014-07-22 21:27:00 +00:00
zend_str_tolower_copy ( lcname - > val , name - > val , name - > len ) ;
ZVAL_NEW_STR ( & c , lcname ) ;
zend_add_literal ( CG ( active_op_array ) , & c TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-07-22 21:27:00 +00:00
return SUCCESS ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
static int zend_try_compile_ct_bound_init_user_func ( znode * result , zend_ast * name_ast , uint32_t num_args TSRMLS_DC ) /* { { { */
{
2014-07-24 17:22:46 +00:00
zend_string * name , * lcname ;
zend_function * fbc ;
zend_op * opline ;
2011-11-17 21:04:15 +00:00
2014-07-24 17:22:46 +00:00
if ( name_ast - > kind ! = ZEND_AST_CONST | | Z_TYPE_P ( zend_ast_get_zval ( name_ast ) ) ! = IS_STRING ) {
return FAILURE ;
}
2011-11-17 21:04:15 +00:00
2014-07-28 13:16:35 +00:00
name = zend_ast_get_str ( name_ast ) ;
2014-08-25 19:21:16 +00:00
lcname = zend_string_alloc ( name - > len , 0 ) ;
2014-07-24 17:22:46 +00:00
zend_str_tolower_copy ( lcname - > val , name - > val , name - > len ) ;
fbc = zend_hash_find_ptr ( CG ( function_table ) , lcname ) ;
if ( ! fbc | | ( fbc - > type = = ZEND_INTERNAL_FUNCTION & &
( CG ( compiler_options ) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS ) )
) {
2014-08-25 19:21:16 +00:00
zend_string_free ( lcname ) ;
2014-07-24 17:22:46 +00:00
return FAILURE ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-07-24 17:22:46 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_INIT_FCALL , NULL , NULL TSRMLS_CC ) ;
2014-07-24 17:22:46 +00:00
opline - > op2_type = IS_CONST ;
LITERAL_STR ( opline - > op2 , lcname ) ;
opline - > extended_value = num_args ;
return SUCCESS ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
static void zend_compile_init_user_func ( znode * result , zend_ast * name_ast , uint32_t num_args , zend_string * orig_func_name TSRMLS_DC ) /* { { { */
{
2014-07-24 17:22:46 +00:00
zend_op * opline ;
znode name_node ;
2013-01-28 02:02:51 +00:00
2014-07-24 17:22:46 +00:00
if ( zend_try_compile_ct_bound_init_user_func ( result , name_ast , num_args TSRMLS_CC ) = = SUCCESS ) {
2011-06-20 01:36:23 +00:00
return ;
}
2014-07-24 17:22:46 +00:00
zend_compile_expr ( & name_node , name_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_INIT_USER_CALL , NULL , & name_node TSRMLS_CC ) ;
2014-07-24 17:22:46 +00:00
opline - > op1_type = IS_CONST ;
2014-08-25 19:21:16 +00:00
LITERAL_STR ( opline - > op1 , zend_string_copy ( orig_func_name ) ) ;
2014-07-24 17:22:46 +00:00
opline - > extended_value = num_args ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-24 17:22:46 +00:00
2014-07-24 18:35:18 +00:00
/* cufa = call_user_func_array */
2014-08-29 05:05:58 +00:00
int zend_compile_func_cufa ( znode * result , zend_ast_list * args , zend_string * lcname TSRMLS_DC ) /* { { { */
{
2014-07-24 17:22:46 +00:00
znode arg_node ;
2014-07-27 20:26:06 +00:00
if ( args - > children ! = 2 | | zend_args_contain_unpack ( args ) ) {
2014-07-24 17:22:46 +00:00
return FAILURE ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-07-24 17:22:46 +00:00
2014-07-27 20:26:06 +00:00
zend_compile_init_user_func ( NULL , args - > child [ 0 ] , 1 , lcname TSRMLS_CC ) ;
zend_compile_expr ( & arg_node , args - > child [ 1 ] TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_SEND_ARRAY , & arg_node , NULL TSRMLS_CC ) ;
zend_emit_op ( result , ZEND_DO_FCALL , NULL , NULL TSRMLS_CC ) ;
2014-07-24 17:22:46 +00:00
return SUCCESS ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-24 18:35:18 +00:00
/* cuf = call_user_func */
2014-08-29 05:05:58 +00:00
int zend_compile_func_cuf ( znode * result , zend_ast_list * args , zend_string * lcname TSRMLS_DC ) /* { { { */
{
2014-08-25 17:28:33 +00:00
uint32_t i ;
2012-12-25 06:23:08 +00:00
2014-07-27 20:26:06 +00:00
if ( args - > children < 1 | | zend_args_contain_unpack ( args ) ) {
2014-07-24 18:35:18 +00:00
return FAILURE ;
}
2011-01-19 17:17:52 +00:00
2014-07-27 20:26:06 +00:00
zend_compile_init_user_func ( NULL , args - > child [ 0 ] , args - > children - 1 , lcname TSRMLS_CC ) ;
for ( i = 1 ; i < args - > children ; + + i ) {
zend_ast * arg_ast = args - > child [ i ] ;
2014-07-24 18:35:18 +00:00
znode arg_node ;
zend_op * opline ;
zend_bool send_user = 0 ;
2011-07-09 12:06:11 +00:00
2014-07-24 18:35:18 +00:00
if ( zend_is_variable ( arg_ast ) & & ! zend_is_call ( arg_ast ) ) {
zend_compile_var ( & arg_node , arg_ast , BP_VAR_FUNC_ARG | ( i < < BP_VAR_SHIFT ) TSRMLS_CC ) ;
send_user = 1 ;
} else {
zend_compile_expr ( & arg_node , arg_ast TSRMLS_CC ) ;
if ( arg_node . op_type & ( IS_VAR | IS_CV ) ) {
send_user = 1 ;
}
}
2012-12-25 06:23:08 +00:00
2014-07-24 18:35:18 +00:00
if ( send_user ) {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_SEND_USER , & arg_node , NULL TSRMLS_CC ) ;
2011-07-09 12:06:11 +00:00
} else {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_SEND_VAL , & arg_node , NULL TSRMLS_CC ) ;
2011-07-09 12:06:11 +00:00
}
2014-07-24 18:35:18 +00:00
opline - > op2 . opline_num = i ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-07-28 20:03:16 +00:00
zend_emit_op ( result , ZEND_DO_FCALL , NULL , NULL TSRMLS_CC ) ;
2013-01-28 02:02:51 +00:00
2014-07-24 18:35:18 +00:00
return SUCCESS ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
int zend_try_compile_special_func ( znode * result , zend_string * lcname , zend_ast_list * args TSRMLS_DC ) /* { { { */
{
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_literal ( lcname , " strlen " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_strlen ( result , args TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_null " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , IS_NULL TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_bool " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , _IS_BOOL TSRMLS_CC ) ;
2014-08-28 19:53:32 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_long " )
| | zend_string_equals_literal ( lcname , " is_int " )
| | zend_string_equals_literal ( lcname , " is_integer " )
) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , IS_LONG TSRMLS_CC ) ;
2014-08-28 19:53:32 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_float " )
| | zend_string_equals_literal ( lcname , " is_double " )
| | zend_string_equals_literal ( lcname , " is_real " )
) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , IS_DOUBLE TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_string " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , IS_STRING TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_array " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , IS_ARRAY TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_object " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , IS_OBJECT TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " is_resource " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_typecheck ( result , args , IS_RESOURCE TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " defined " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_defined ( result , args TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " call_user_func_array " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_cufa ( result , args , lcname TSRMLS_CC ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , " call_user_func " ) ) {
2014-07-27 20:26:06 +00:00
return zend_compile_func_cuf ( result , args , lcname TSRMLS_CC ) ;
2014-07-22 21:27:00 +00:00
} else {
return FAILURE ;
2012-12-25 06:23:08 +00:00
}
2010-12-20 00:52:40 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2010-12-20 00:52:40 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_call ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * name_ast = ast - > child [ 0 ] ;
2014-07-13 11:11:55 +00:00
zend_ast * args_ast = ast - > child [ 1 ] ;
2010-12-20 00:52:40 +00:00
2014-06-07 11:06:53 +00:00
znode name_node ;
2014-06-28 20:27:06 +00:00
if ( name_ast - > kind ! = ZEND_AST_ZVAL | | Z_TYPE_P ( zend_ast_get_zval ( name_ast ) ) ! = IS_STRING ) {
2014-06-07 11:06:53 +00:00
zend_compile_expr ( & name_node , name_ast TSRMLS_CC ) ;
2014-07-13 11:11:55 +00:00
zend_compile_dynamic_call ( result , & name_node , args_ast TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
return ;
2012-01-20 12:30:57 +00:00
}
2014-06-07 11:06:53 +00:00
{
2014-07-28 20:03:16 +00:00
zend_bool runtime_resolution = zend_compile_function_name ( & name_node , name_ast TSRMLS_CC ) ;
if ( runtime_resolution ) {
2014-07-13 11:11:55 +00:00
zend_compile_ns_call ( result , & name_node , args_ast TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
return ;
}
}
2011-12-19 16:48:18 +00:00
2014-06-07 11:06:53 +00:00
{
zval * name = & name_node . u . constant ;
2014-08-25 19:21:16 +00:00
zend_string * lcname = zend_string_alloc ( Z_STRLEN_P ( name ) , 0 ) ;
2014-06-07 11:06:53 +00:00
zend_function * fbc ;
zend_op * opline ;
2012-12-25 06:23:08 +00:00
2014-06-07 11:06:53 +00:00
zend_str_tolower_copy ( lcname - > val , Z_STRVAL_P ( name ) , Z_STRLEN_P ( name ) ) ;
2014-02-10 06:04:30 +00:00
2014-07-24 17:22:46 +00:00
fbc = zend_hash_find_ptr ( CG ( function_table ) , lcname ) ;
if ( ! fbc | | ( fbc - > type = = ZEND_INTERNAL_FUNCTION & &
( CG ( compiler_options ) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS ) )
) {
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
2014-07-24 17:22:46 +00:00
zend_compile_dynamic_call ( result , & name_node , args_ast TSRMLS_CC ) ;
2014-07-22 21:11:12 +00:00
return ;
2014-07-22 20:57:38 +00:00
}
2011-01-19 17:17:52 +00:00
2014-07-27 20:26:06 +00:00
if ( zend_try_compile_special_func ( result , lcname ,
zend_ast_get_list ( args_ast ) TSRMLS_CC ) = = SUCCESS
) {
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
2014-07-24 17:22:46 +00:00
zval_ptr_dtor ( & name_node . u . constant ) ;
2014-06-07 11:06:53 +00:00
return ;
}
2011-12-19 16:48:18 +00:00
2014-06-07 11:06:53 +00:00
zval_ptr_dtor ( & name_node . u . constant ) ;
ZVAL_NEW_STR ( & name_node . u . constant , lcname ) ;
2011-01-19 17:17:52 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_INIT_FCALL , NULL , & name_node TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2010-12-20 00:52:40 +00:00
2014-07-22 14:55:34 +00:00
zend_compile_call_common ( result , args_ast , fbc TSRMLS_CC ) ;
2010-12-20 00:52:40 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_method_call ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
zend_ast * obj_ast = ast - > child [ 0 ] ;
zend_ast * method_ast = ast - > child [ 1 ] ;
2014-07-13 11:11:55 +00:00
zend_ast * args_ast = ast - > child [ 2 ] ;
2013-01-28 02:02:51 +00:00
2014-08-15 15:10:06 +00:00
znode obj_node , method_node ;
zend_op * opline ;
2011-11-18 13:49:07 +00:00
2014-08-15 15:10:06 +00:00
if ( is_this_fetch ( obj_ast ) ) {
obj_node . op_type = IS_UNUSED ;
} else {
2014-08-28 22:18:38 +00:00
zend_compile_expr ( & obj_node , obj_ast TSRMLS_CC ) ;
2011-11-17 21:04:15 +00:00
}
2014-08-15 15:10:06 +00:00
zend_compile_expr ( & method_node , method_ast TSRMLS_CC ) ;
opline = zend_emit_op ( NULL , ZEND_INIT_METHOD_CALL , & obj_node , NULL TSRMLS_CC ) ;
if ( method_node . op_type = = IS_CONST ) {
if ( Z_TYPE ( method_node . u . constant ) ! = IS_STRING ) {
2014-06-07 11:06:53 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Method name must be a string " ) ;
}
2010-12-20 00:52:40 +00:00
2014-08-15 15:10:06 +00:00
opline - > op2_type = IS_CONST ;
2014-06-07 11:06:53 +00:00
opline - > op2 . constant =
2014-08-15 15:10:06 +00:00
zend_add_func_name_literal ( CG ( active_op_array ) , & method_node . u . constant TSRMLS_CC ) ;
zend_alloc_polymorphic_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
} else {
SET_NODE ( opline - > op2 , & method_node ) ;
2010-12-20 00:52:40 +00:00
}
2014-07-13 11:11:55 +00:00
zend_compile_call_common ( result , args_ast , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
zend_bool zend_is_constructor ( zend_string * name ) /* { { { */
{
2014-08-25 20:40:58 +00:00
return zend_string_equals_literal_ci ( name , ZEND_CONSTRUCTOR_FUNC_NAME ) ;
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2010-12-20 00:52:40 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_static_call ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * class_ast = ast - > child [ 0 ] ;
zend_ast * method_ast = ast - > child [ 1 ] ;
2014-07-13 11:11:55 +00:00
zend_ast * args_ast = ast - > child [ 2 ] ;
2010-12-20 00:52:40 +00:00
2014-06-14 16:30:18 +00:00
znode class_node , method_node ;
2014-06-07 11:06:53 +00:00
zend_op * opline ;
zend_ulong extended_value = 0 ;
2013-01-28 02:02:51 +00:00
2014-06-14 16:30:18 +00:00
if ( zend_is_const_default_class_ref ( class_ast ) ) {
2014-07-19 21:30:07 +00:00
class_node . op_type = IS_CONST ;
ZVAL_STR ( & class_node . u . constant , zend_resolve_class_name_ast ( class_ast TSRMLS_CC ) ) ;
2014-06-07 11:06:53 +00:00
} else {
2014-06-14 16:30:18 +00:00
opline = zend_compile_class_ref ( & class_node , class_ast TSRMLS_CC ) ;
extended_value = opline - > extended_value ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2010-04-20 10:57:45 +00:00
2014-06-07 11:06:53 +00:00
zend_compile_expr ( & method_node , method_ast TSRMLS_CC ) ;
if ( method_node . op_type = = IS_CONST ) {
zval * name = & method_node . u . constant ;
if ( Z_TYPE_P ( name ) ! = IS_STRING ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Method name must be a string " ) ;
}
if ( zend_is_constructor ( Z_STR_P ( name ) ) ) {
zval_ptr_dtor ( name ) ;
method_node . op_type = IS_UNUSED ;
}
2010-04-20 10:57:45 +00:00
}
1999-05-15 15:47:24 +00:00
2014-06-07 11:06:53 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_INIT_STATIC_METHOD_CALL ;
opline - > extended_value = extended_value ;
2002-09-24 19:05:53 +00:00
2014-06-19 11:57:29 +00:00
zend_set_class_name_op1 ( opline , & class_node TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
if ( method_node . op_type = = IS_CONST ) {
opline - > op2_type = IS_CONST ;
opline - > op2 . constant =
zend_add_func_name_literal ( CG ( active_op_array ) , & method_node . u . constant TSRMLS_CC ) ;
if ( opline - > op1_type = = IS_CONST ) {
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2002-09-24 19:05:53 +00:00
} else {
2014-08-15 15:10:06 +00:00
zend_alloc_polymorphic_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2002-09-24 19:05:53 +00:00
}
} else {
2014-06-07 11:06:53 +00:00
SET_NODE ( opline - > op2 , & method_node ) ;
2002-09-24 19:05:53 +00:00
}
2014-06-07 11:06:53 +00:00
2014-07-13 11:11:55 +00:00
zend_compile_call_common ( result , args_ast , NULL TSRMLS_CC ) ;
2002-09-24 19:05:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2006-05-09 23:53:23 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_new ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * class_ast = ast - > child [ 0 ] ;
2014-07-13 11:11:55 +00:00
zend_ast * args_ast = ast - > child [ 1 ] ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-06-14 16:30:18 +00:00
znode class_node , ctor_result ;
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t opnum ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_class_ref ( & class_node , class_ast TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-06-14 16:30:18 +00:00
opnum = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_NEW , & class_node , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
2014-07-13 11:11:55 +00:00
zend_compile_call_common ( & ctor_result , args_ast , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
zend_do_free ( & ctor_result TSRMLS_CC ) ;
/* New jumps over ctor call if ctor does not exist */
opline = & CG ( active_op_array ) - > opcodes [ opnum ] ;
opline - > op2 . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_clone ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * obj_ast = ast - > child [ 0 ] ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-06-14 16:30:18 +00:00
znode obj_node ;
zend_compile_expr ( & obj_node , obj_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( result , ZEND_CLONE , & obj_node , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-14 16:30:18 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_global_var ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
2014-07-22 18:24:47 +00:00
zend_ast * name_ast = var_ast - > child [ 0 ] ;
2014-06-07 11:06:53 +00:00
2014-07-22 18:24:47 +00:00
znode name_node , result ;
2014-06-07 11:06:53 +00:00
2014-07-22 18:24:47 +00:00
zend_compile_expr ( & name_node , name_ast TSRMLS_CC ) ;
if ( name_node . op_type = = IS_CONST ) {
if ( Z_TYPE ( name_node . u . constant ) ! = IS_STRING ) {
convert_to_string ( & name_node . u . constant ) ;
2014-06-07 11:06:53 +00:00
}
2010-05-06 19:20:12 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-22 18:24:47 +00:00
if ( zend_try_compile_cv ( & result , var_ast TSRMLS_CC ) = = SUCCESS ) {
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_BIND_GLOBAL , & result , & name_node TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
} else {
2014-07-28 20:03:16 +00:00
zend_emit_op ( & result , ZEND_FETCH_W , & name_node , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
2014-07-22 18:24:47 +00:00
// TODO.AST Avoid double fetch
//opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
2014-06-07 11:06:53 +00:00
2014-08-15 15:10:06 +00:00
zend_emit_assign_ref_znode ( var_ast , & result TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
static void zend_compile_static_var_common ( zend_ast * var_ast , zval * value , zend_bool by_ref TSRMLS_DC ) /* { { { */
{
2014-07-12 15:00:53 +00:00
znode var_node , result ;
zend_op * opline ;
zend_compile_expr ( & var_node , var_ast TSRMLS_CC ) ;
if ( ! CG ( active_op_array ) - > static_variables ) {
if ( CG ( active_op_array ) - > scope ) {
CG ( active_op_array ) - > scope - > ce_flags | = ZEND_HAS_STATIC_IN_METHODS ;
}
ALLOC_HASHTABLE ( CG ( active_op_array ) - > static_variables ) ;
zend_hash_init ( CG ( active_op_array ) - > static_variables , 8 , NULL , ZVAL_PTR_DTOR , 0 ) ;
}
2014-07-18 10:30:39 +00:00
zend_hash_update ( CG ( active_op_array ) - > static_variables , Z_STR ( var_node . u . constant ) , value ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( & result , by_ref ? ZEND_FETCH_W : ZEND_FETCH_R , & var_node , NULL TSRMLS_CC ) ;
2014-07-12 15:00:53 +00:00
opline - > extended_value = ZEND_FETCH_STATIC ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-18 10:30:39 +00:00
if ( by_ref ) {
2014-07-28 16:18:47 +00:00
zend_ast * fetch_ast = zend_ast_create ( ZEND_AST_VAR , var_ast ) ;
2014-08-15 15:10:06 +00:00
zend_emit_assign_ref_znode ( fetch_ast , & result TSRMLS_CC ) ;
2014-07-18 10:30:39 +00:00
} else {
2014-07-28 16:18:47 +00:00
zend_ast * fetch_ast = zend_ast_create ( ZEND_AST_VAR , var_ast ) ;
2014-08-15 15:10:06 +00:00
zend_emit_assign_znode ( fetch_ast , & result TSRMLS_CC ) ;
2014-07-18 10:30:39 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_static_var ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-18 10:30:39 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
zend_ast * value_ast = ast - > child [ 1 ] ;
zval value_zv ;
2002-09-24 19:05:53 +00:00
2014-07-18 10:30:39 +00:00
if ( value_ast ) {
2014-07-30 15:44:26 +00:00
zend_const_expr_to_zval ( & value_zv , value_ast TSRMLS_CC ) ;
2010-04-20 10:57:45 +00:00
} else {
2014-07-18 10:30:39 +00:00
ZVAL_NULL ( & value_zv ) ;
2010-04-20 10:57:45 +00:00
}
2014-07-18 10:30:39 +00:00
zend_compile_static_var_common ( var_ast , & value_zv , 1 TSRMLS_CC ) ;
2014-07-12 15:00:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-12 15:00:53 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_unset ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
znode var_node ;
zend_op * opline ;
switch ( var_ast - > kind ) {
case ZEND_AST_VAR :
2014-06-19 11:57:29 +00:00
if ( zend_try_compile_cv ( & var_node , var_ast TSRMLS_CC ) = = SUCCESS ) {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_UNSET_VAR , & var_node , NULL TSRMLS_CC ) ;
2014-06-07 11:06:53 +00:00
opline - > extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET ;
} else {
opline = zend_compile_simple_var_no_cv ( NULL , var_ast , BP_VAR_UNSET TSRMLS_CC ) ;
opline - > opcode = ZEND_UNSET_VAR ;
}
return ;
case ZEND_AST_DIM :
opline = zend_compile_dim_common ( NULL , var_ast , BP_VAR_UNSET TSRMLS_CC ) ;
opline - > opcode = ZEND_UNSET_DIM ;
return ;
case ZEND_AST_PROP :
opline = zend_compile_prop_common ( NULL , var_ast , BP_VAR_UNSET TSRMLS_CC ) ;
opline - > opcode = ZEND_UNSET_OBJ ;
return ;
2014-06-19 11:57:29 +00:00
case ZEND_AST_STATIC_PROP :
opline = zend_compile_static_prop_common ( NULL , var_ast , BP_VAR_UNSET TSRMLS_CC ) ;
opline - > opcode = ZEND_UNSET_VAR ;
return ;
2014-06-07 11:06:53 +00:00
EMPTY_SWITCH_DEFAULT_CASE ( )
2002-09-24 19:05:53 +00:00
}
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-07 11:06:53 +00:00
2014-08-29 05:05:58 +00:00
static void zend_free_foreach_and_switch_variables ( TSRMLS_D ) /* { { { */
{
2014-08-25 19:21:16 +00:00
uint32_t opnum_start , opnum_end , i ;
2014-07-07 19:06:02 +00:00
opnum_start = get_next_op_number ( CG ( active_op_array ) ) ;
# ifdef ZTS
2014-08-29 19:47:10 +00:00
zend_stack_apply_with_argument ( & CG ( loop_var_stack ) , ZEND_STACK_APPLY_TOPDOWN , ( int ( * ) ( void * element , void * ) ) generate_free_loop_var TSRMLS_CC ) ;
2014-07-07 19:06:02 +00:00
# else
2014-08-29 19:47:10 +00:00
zend_stack_apply ( & CG ( loop_var_stack ) , ZEND_STACK_APPLY_TOPDOWN , ( int ( * ) ( void * element ) ) generate_free_loop_var ) ;
2014-07-07 19:06:02 +00:00
# endif
opnum_end = get_next_op_number ( CG ( active_op_array ) ) ;
for ( i = opnum_start ; i < opnum_end ; + + i ) {
CG ( active_op_array ) - > opcodes [ i ] . extended_value | = EXT_TYPE_FREE_ON_RETURN ;
2002-09-24 19:05:53 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2000-05-25 16:26:22 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_return ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-07 19:06:02 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
zend_bool by_ref = ( CG ( active_op_array ) - > fn_flags & ZEND_ACC_RETURN_REFERENCE ) ! = 0 ;
2010-04-20 10:57:45 +00:00
2014-07-07 19:06:02 +00:00
znode expr_node ;
zend_op * opline ;
if ( ! expr_ast ) {
expr_node . op_type = IS_CONST ;
ZVAL_NULL ( & expr_node . u . constant ) ;
} else if ( by_ref & & zend_is_variable ( expr_ast ) & & ! zend_is_call ( expr_ast ) ) {
zend_compile_var ( & expr_node , expr_ast , BP_VAR_REF TSRMLS_CC ) ;
2010-04-20 10:57:45 +00:00
} else {
2014-07-07 19:06:02 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2010-04-20 10:57:45 +00:00
}
2002-09-15 07:54:01 +00:00
2014-07-07 19:06:02 +00:00
zend_free_foreach_and_switch_variables ( TSRMLS_C ) ;
2002-09-24 19:05:53 +00:00
2014-07-07 19:06:02 +00:00
if ( CG ( context ) . in_finally ) {
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_DISCARD_EXCEPTION , NULL , NULL TSRMLS_CC ) ;
2002-09-24 19:05:53 +00:00
}
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN ,
& expr_node , NULL TSRMLS_CC ) ;
2014-07-07 19:06:02 +00:00
if ( expr_ast ) {
if ( zend_is_call ( expr_ast ) ) {
opline - > extended_value = ZEND_RETURNS_FUNCTION ;
} else if ( ! zend_is_variable ( expr_ast ) ) {
opline - > extended_value = ZEND_RETURNS_VALUE ;
}
2004-08-26 22:59:25 +00:00
}
2014-07-07 19:06:02 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2004-08-26 22:59:25 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_echo ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-07 19:14:14 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
2002-09-24 19:05:53 +00:00
2014-07-07 19:14:14 +00:00
znode expr_node ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2002-09-24 19:32:01 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_ECHO , & expr_node , NULL TSRMLS_CC ) ;
1999-05-15 15:47:24 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-05-15 15:47:24 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_throw ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-09 20:47:36 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
1999-05-15 15:47:24 +00:00
2014-07-09 20:47:36 +00:00
znode expr_node ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2003-01-28 11:34:24 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_THROW , & expr_node , NULL TSRMLS_CC ) ;
2014-07-09 20:47:36 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2008-03-18 08:36:30 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_break_continue ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-09 21:05:21 +00:00
zend_ast * depth_ast = ast - > child [ 0 ] ;
2008-03-18 08:36:30 +00:00
2014-07-09 21:05:21 +00:00
znode depth_node ;
zend_op * opline ;
2004-02-04 16:30:15 +00:00
2014-07-27 20:26:06 +00:00
ZEND_ASSERT ( ast - > kind = = ZEND_AST_BREAK | | ast - > kind = = ZEND_AST_CONTINUE ) ;
2014-07-09 21:05:21 +00:00
if ( depth_ast ) {
if ( depth_ast - > kind ! = ZEND_AST_ZVAL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " '%s' operator with non-constant operand "
2014-07-27 20:26:06 +00:00
" is no longer supported " , ast - > kind = = ZEND_AST_BREAK ? " break " : " continue " ) ;
2014-07-09 21:05:21 +00:00
}
zend_compile_expr ( & depth_node , depth_ast TSRMLS_CC ) ;
if ( Z_TYPE ( depth_node . u . constant ) ! = IS_LONG | | Z_LVAL ( depth_node . u . constant ) < 1 ) {
zend_error_noreturn ( E_COMPILE_ERROR , " '%s' operator accepts only positive numbers " ,
2014-07-27 20:26:06 +00:00
ast - > kind = = ZEND_AST_BREAK ? " break " : " continue " ) ;
2014-07-09 21:05:21 +00:00
}
} else {
depth_node . op_type = IS_CONST ;
ZVAL_LONG ( & depth_node . u . constant , 1 ) ;
1999-07-26 21:18:35 +00:00
}
2002-09-24 19:05:53 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ast - > kind = = ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT ,
2014-07-27 20:26:06 +00:00
NULL , & depth_node TSRMLS_CC ) ;
2014-07-09 21:05:21 +00:00
opline - > op1 . opline_num = CG ( context ) . current_brk_cont ;
1999-05-15 15:47:24 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-05-15 15:47:24 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_goto ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-09 21:11:32 +00:00
zend_ast * label_ast = ast - > child [ 0 ] ;
znode label_node ;
zend_op * opline ;
zend_compile_expr ( & label_node , label_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_GOTO , NULL , & label_node TSRMLS_CC ) ;
2014-07-09 21:11:32 +00:00
opline - > extended_value = CG ( context ) . current_brk_cont ;
zend_resolve_goto_label ( CG ( active_op_array ) , opline , 0 TSRMLS_CC ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-09 21:11:32 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_label ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-09 21:46:22 +00:00
zval * label = zend_ast_get_zval ( ast - > child [ 0 ] ) ;
zend_label dest ;
ZEND_ASSERT ( Z_TYPE_P ( label ) = = IS_STRING ) ;
if ( ! CG ( context ) . labels ) {
ALLOC_HASHTABLE ( CG ( context ) . labels ) ;
zend_hash_init ( CG ( context ) . labels , 8 , NULL , ptr_dtor , 0 ) ;
}
dest . brk_cont = CG ( context ) . current_brk_cont ;
dest . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
2008-03-18 08:36:30 +00:00
2014-07-09 21:46:22 +00:00
if ( ! zend_hash_add_mem ( CG ( context ) . labels , Z_STR_P ( label ) , & dest , sizeof ( zend_label ) ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Label '%s' already defined " , Z_STRVAL_P ( label ) ) ;
2008-03-18 08:36:30 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-05-15 15:47:24 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_while ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-10 12:35:59 +00:00
zend_ast * cond_ast = ast - > child [ 0 ] ;
zend_ast * stmt_ast = ast - > child [ 1 ] ;
1999-04-07 18:10:10 +00:00
2014-07-10 12:35:59 +00:00
znode cond_node ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_start , opnum_jmpz ;
2006-05-09 23:53:23 +00:00
2014-07-10 12:35:59 +00:00
opnum_start = get_next_op_number ( CG ( active_op_array ) ) ;
zend_compile_expr ( & cond_node , cond_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-18 17:57:38 +00:00
opnum_jmpz = zend_emit_cond_jump ( ZEND_JMPZ , & cond_node , 0 TSRMLS_CC ) ;
2014-07-30 16:27:41 +00:00
zend_begin_loop ( TSRMLS_C ) ;
1999-04-07 18:10:10 +00:00
2014-07-10 12:35:59 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-18 17:57:38 +00:00
zend_emit_jump ( opnum_start TSRMLS_CC ) ;
2014-07-10 12:35:59 +00:00
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_jmpz TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-30 16:27:41 +00:00
zend_end_loop ( opnum_start , 0 TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_do_while ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-10 12:46:22 +00:00
zend_ast * stmt_ast = ast - > child [ 0 ] ;
zend_ast * cond_ast = ast - > child [ 1 ] ;
1999-04-07 18:10:10 +00:00
2014-07-10 12:46:22 +00:00
znode cond_node ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_start , opnum_cond ;
2006-05-09 23:53:23 +00:00
2014-07-30 16:27:41 +00:00
zend_begin_loop ( TSRMLS_C ) ;
1999-04-07 18:10:10 +00:00
2014-07-10 12:46:22 +00:00
opnum_start = get_next_op_number ( CG ( active_op_array ) ) ;
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-10 12:46:22 +00:00
opnum_cond = get_next_op_number ( CG ( active_op_array ) ) ;
zend_compile_expr ( & cond_node , cond_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-18 17:57:38 +00:00
zend_emit_cond_jump ( ZEND_JMPNZ , & cond_node , opnum_start TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-30 16:27:41 +00:00
zend_end_loop ( opnum_cond , 0 TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_expr_list ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
1999-04-07 18:10:10 +00:00
2014-07-19 11:21:12 +00:00
result - > op_type = IS_CONST ;
ZVAL_TRUE ( & result - > u . constant ) ;
1999-04-07 18:10:10 +00:00
2014-07-19 11:21:12 +00:00
if ( ! ast ) {
return ;
}
1999-04-07 18:10:10 +00:00
2014-07-27 20:26:06 +00:00
list = zend_ast_get_list ( ast ) ;
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * expr_ast = list - > child [ i ] ;
1999-04-07 18:10:10 +00:00
2014-07-10 13:51:47 +00:00
zend_do_free ( result TSRMLS_CC ) ;
zend_compile_expr ( result , expr_ast TSRMLS_CC ) ;
}
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_for ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-10 13:51:47 +00:00
zend_ast * init_ast = ast - > child [ 0 ] ;
zend_ast * cond_ast = ast - > child [ 1 ] ;
zend_ast * loop_ast = ast - > child [ 2 ] ;
zend_ast * stmt_ast = ast - > child [ 3 ] ;
1999-04-07 18:10:10 +00:00
2014-07-10 13:51:47 +00:00
znode result ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_cond , opnum_jmpz , opnum_loop ;
1999-04-07 18:10:10 +00:00
2014-07-10 13:51:47 +00:00
zend_compile_expr_list ( & result , init_ast TSRMLS_CC ) ;
zend_do_free ( & result TSRMLS_CC ) ;
2000-08-10 20:42:57 +00:00
2014-07-10 13:51:47 +00:00
opnum_cond = get_next_op_number ( CG ( active_op_array ) ) ;
zend_compile_expr_list ( & result , cond_ast TSRMLS_CC ) ;
zend_do_extended_info ( TSRMLS_C ) ;
2014-07-18 17:57:38 +00:00
opnum_jmpz = zend_emit_cond_jump ( ZEND_JMPZ , & result , 0 TSRMLS_CC ) ;
2014-07-30 16:27:41 +00:00
zend_begin_loop ( TSRMLS_C ) ;
2014-07-10 13:51:47 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-10 13:51:47 +00:00
opnum_loop = get_next_op_number ( CG ( active_op_array ) ) ;
zend_compile_expr_list ( & result , loop_ast TSRMLS_CC ) ;
zend_do_free ( & result TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-18 17:57:38 +00:00
zend_emit_jump ( opnum_cond TSRMLS_CC ) ;
2014-07-10 13:51:47 +00:00
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_jmpz TSRMLS_CC ) ;
2014-07-10 13:51:47 +00:00
2014-07-30 16:27:41 +00:00
zend_end_loop ( opnum_loop , 0 TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_foreach ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-11 10:16:21 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
zend_ast * value_ast = ast - > child [ 1 ] ;
zend_ast * key_ast = ast - > child [ 2 ] ;
zend_ast * stmt_ast = ast - > child [ 3 ] ;
zend_bool by_ref = value_ast - > kind = = ZEND_AST_REF ;
zend_bool is_variable = zend_is_variable ( expr_ast ) & & ! zend_is_call ( expr_ast )
& & zend_can_write_to_variable ( expr_ast ) ;
znode expr_node , reset_node , value_node , key_node , dummy_node ;
1999-04-07 18:10:10 +00:00
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_reset , opnum_fetch ;
1999-04-07 18:10:10 +00:00
2014-07-11 10:16:21 +00:00
if ( key_ast ) {
if ( key_ast - > kind = = ZEND_AST_REF ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Key element cannot be a reference " ) ;
}
if ( key_ast - > kind = = ZEND_AST_LIST ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use list as key element " ) ;
}
2004-10-08 18:50:00 +00:00
}
2014-07-11 10:16:21 +00:00
if ( by_ref ) {
value_ast = value_ast - > child [ 0 ] ;
}
2011-01-19 17:17:52 +00:00
2014-07-11 10:16:21 +00:00
if ( by_ref & & is_variable ) {
zend_compile_var ( & expr_node , expr_ast , BP_VAR_W TSRMLS_CC ) ;
} else {
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-07-11 10:16:21 +00:00
opnum_reset = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( & reset_node , ZEND_FE_RESET , & expr_node , NULL TSRMLS_CC ) ;
2014-07-11 10:16:21 +00:00
if ( by_ref & & is_variable ) {
2014-07-12 14:25:47 +00:00
opline - > extended_value = ZEND_FE_RESET_VARIABLE | ZEND_FE_RESET_REFERENCE ; // ???
2014-07-11 10:16:21 +00:00
}
1999-04-07 18:10:10 +00:00
2014-08-29 19:47:10 +00:00
zend_stack_push ( & CG ( loop_var_stack ) , & reset_node ) ;
2014-07-11 10:16:21 +00:00
opnum_fetch = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( & value_node , ZEND_FE_FETCH , & reset_node , NULL TSRMLS_CC ) ;
2014-07-11 10:16:21 +00:00
if ( by_ref ) {
opline - > extended_value | = ZEND_FE_FETCH_BYREF ;
2000-03-29 22:28:04 +00:00
}
2014-07-11 10:16:21 +00:00
if ( key_ast ) {
opline - > extended_value | = ZEND_FE_FETCH_WITH_KEY ;
1999-04-07 18:10:10 +00:00
}
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_OP_DATA , NULL , NULL TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-11 10:16:21 +00:00
/* Allocate enough space to keep HashPointer on VM stack */
opline - > op1_type = IS_TMP_VAR ;
opline - > op1 . var = get_temporary_variable ( CG ( active_op_array ) ) ;
if ( sizeof ( HashPointer ) > sizeof ( zval ) ) {
/* Make sure 1 zval is enough for HashPointer (2 must be enough) */
get_temporary_variable ( CG ( active_op_array ) ) ;
}
1999-04-07 18:10:10 +00:00
2014-07-11 10:16:21 +00:00
if ( key_ast ) {
2014-08-15 15:10:06 +00:00
zend_make_tmp_result ( & key_node , opline TSRMLS_CC ) ;
2014-07-11 10:16:21 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-11 10:16:21 +00:00
if ( value_ast - > attr = = ZEND_AST_LIST ) {
zend_compile_list_assign ( & dummy_node , value_ast , & value_node TSRMLS_CC ) ;
zend_do_free ( & dummy_node TSRMLS_CC ) ;
} else if ( by_ref ) {
2014-08-15 15:10:06 +00:00
zend_emit_assign_ref_znode ( value_ast , & value_node TSRMLS_CC ) ;
2014-07-11 10:16:21 +00:00
} else {
2014-08-15 15:10:06 +00:00
zend_emit_assign_znode ( value_ast , & value_node TSRMLS_CC ) ;
2004-08-23 20:16:35 +00:00
}
2014-07-11 10:16:21 +00:00
if ( key_ast ) {
2014-08-15 15:10:06 +00:00
zend_emit_assign_znode ( key_ast , & key_node TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2006-05-09 23:53:23 +00:00
2014-07-30 16:27:41 +00:00
zend_begin_loop ( TSRMLS_C ) ;
1999-04-07 18:10:10 +00:00
2014-07-11 10:16:21 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-18 17:57:38 +00:00
zend_emit_jump ( opnum_fetch TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-11 10:16:21 +00:00
opline = & CG ( active_op_array ) - > opcodes [ opnum_reset ] ;
opline - > op2 . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
1999-04-07 18:10:10 +00:00
2014-07-11 10:16:21 +00:00
opline = & CG ( active_op_array ) - > opcodes [ opnum_fetch ] ;
opline - > op2 . opline_num = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-30 16:27:41 +00:00
zend_end_loop ( opnum_fetch , 1 TSRMLS_CC ) ;
2014-07-11 10:16:21 +00:00
2014-08-29 19:47:10 +00:00
generate_free_loop_var ( & reset_node TSRMLS_CC ) ;
zend_stack_del_top ( & CG ( loop_var_stack ) ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_if ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-08-26 17:39:40 +00:00
uint32_t * jmp_opnums ;
if ( list - > children > 1 ) {
jmp_opnums = safe_emalloc ( sizeof ( uint32_t ) , list - > children - 1 , 0 ) ;
}
1999-04-07 18:10:10 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * elem_ast = list - > child [ i ] ;
2014-07-10 14:38:04 +00:00
zend_ast * cond_ast = elem_ast - > child [ 0 ] ;
zend_ast * stmt_ast = elem_ast - > child [ 1 ] ;
2004-10-08 18:50:00 +00:00
2014-07-10 14:38:04 +00:00
znode cond_node ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_jmpz ;
2014-07-10 14:38:04 +00:00
if ( cond_ast ) {
zend_compile_expr ( & cond_node , cond_ast TSRMLS_CC ) ;
2014-07-30 16:27:41 +00:00
opnum_jmpz = zend_emit_cond_jump ( ZEND_JMPZ , & cond_node , 0 TSRMLS_CC ) ;
2014-07-10 14:38:04 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-10 14:38:04 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
2014-07-27 20:26:06 +00:00
if ( i ! = list - > children - 1 ) {
2014-07-18 17:57:38 +00:00
jmp_opnums [ i ] = zend_emit_jump ( 0 TSRMLS_CC ) ;
2014-07-10 14:38:04 +00:00
}
if ( cond_ast ) {
2014-07-30 16:27:41 +00:00
zend_update_jump_target_to_next ( opnum_jmpz TSRMLS_CC ) ;
2014-07-10 14:38:04 +00:00
}
1999-04-07 18:10:10 +00:00
}
2014-07-10 14:38:04 +00:00
2014-08-26 17:39:40 +00:00
if ( list - > children > 1 ) {
for ( i = 0 ; i < list - > children - 1 ; + + i ) {
zend_update_jump_target_to_next ( jmp_opnums [ i ] TSRMLS_CC ) ;
}
efree ( jmp_opnums ) ;
2014-07-10 14:38:04 +00:00
}
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_switch ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-11 13:31:47 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
2014-07-27 20:26:06 +00:00
zend_ast_list * cases = zend_ast_get_list ( ast - > child [ 1 ] ) ;
2001-10-29 17:19:02 +00:00
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-11 13:31:47 +00:00
zend_bool has_default_case = 0 ;
2004-01-12 07:15:55 +00:00
2014-07-11 13:31:47 +00:00
znode expr_node , case_node ;
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t * jmpnz_opnums = safe_emalloc ( sizeof ( uint32_t ) , cases - > children , 0 ) ;
uint32_t opnum_default_jmp ;
2006-12-21 02:09:36 +00:00
2014-07-11 13:31:47 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2003-02-10 16:11:24 +00:00
2014-08-29 19:47:10 +00:00
zend_stack_push ( & CG ( loop_var_stack ) , & expr_node ) ;
2007-09-28 19:52:53 +00:00
2014-07-30 16:27:41 +00:00
zend_begin_loop ( TSRMLS_C ) ;
2007-09-28 19:52:53 +00:00
2014-07-11 13:31:47 +00:00
case_node . op_type = IS_TMP_VAR ;
case_node . u . op . var = get_temporary_variable ( CG ( active_op_array ) ) ;
2007-09-28 19:52:53 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < cases - > children ; + + i ) {
zend_ast * case_ast = cases - > child [ i ] ;
2014-07-11 13:31:47 +00:00
zend_ast * cond_ast = case_ast - > child [ 0 ] ;
znode cond_node ;
2007-11-12 15:52:22 +00:00
2014-07-11 13:31:47 +00:00
if ( ! cond_ast ) {
has_default_case = 1 ;
continue ;
2007-11-12 15:52:22 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-11 13:31:47 +00:00
zend_compile_expr ( & cond_node , cond_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_CASE , & expr_node , & cond_node TSRMLS_CC ) ;
2014-07-11 13:31:47 +00:00
SET_NODE ( opline - > result , & case_node ) ;
if ( opline - > op1_type = = IS_CONST ) {
zval_copy_ctor ( & CONSTANT ( opline - > op1 . constant ) ) ;
2005-06-24 08:45:17 +00:00
}
2014-07-11 13:31:47 +00:00
2014-07-18 17:57:38 +00:00
jmpnz_opnums [ i ] = zend_emit_cond_jump ( ZEND_JMPNZ , & case_node , 0 TSRMLS_CC ) ;
2001-10-29 17:19:02 +00:00
}
2014-07-18 17:57:38 +00:00
opnum_default_jmp = zend_emit_jump ( 0 TSRMLS_CC ) ;
2013-01-28 02:02:51 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < cases - > children ; + + i ) {
zend_ast * case_ast = cases - > child [ i ] ;
2014-07-11 13:31:47 +00:00
zend_ast * cond_ast = case_ast - > child [ 0 ] ;
zend_ast * stmt_ast = case_ast - > child [ 1 ] ;
2006-05-09 23:53:23 +00:00
2014-07-11 13:31:47 +00:00
if ( cond_ast ) {
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( jmpnz_opnums [ i ] TSRMLS_CC ) ;
2014-07-11 13:31:47 +00:00
} else {
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_default_jmp TSRMLS_CC ) ;
2012-08-22 10:32:03 +00:00
}
2014-07-11 13:31:47 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
1999-07-08 16:55:27 +00:00
}
2002-09-24 19:05:53 +00:00
2014-07-11 13:31:47 +00:00
if ( ! has_default_case ) {
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_default_jmp TSRMLS_CC ) ;
2014-07-11 13:31:47 +00:00
}
2003-03-05 11:14:44 +00:00
2014-07-30 16:27:41 +00:00
zend_end_loop ( get_next_op_number ( CG ( active_op_array ) ) , 1 TSRMLS_CC ) ;
2003-04-02 16:51:49 +00:00
2014-07-11 13:31:47 +00:00
if ( expr_node . op_type = = IS_VAR | | expr_node . op_type = = IS_TMP_VAR ) {
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , expr_node . op_type = = IS_TMP_VAR ? ZEND_FREE : ZEND_SWITCH_FREE ,
2014-07-11 13:31:47 +00:00
& expr_node , NULL TSRMLS_CC ) ;
} else if ( expr_node . op_type = = IS_CONST ) {
zval_dtor ( & expr_node . u . constant ) ;
2003-04-02 16:51:49 +00:00
}
2014-07-11 13:31:47 +00:00
2014-08-29 19:47:10 +00:00
zend_stack_del_top ( & CG ( loop_var_stack ) ) ;
2014-07-11 13:33:39 +00:00
efree ( jmpnz_opnums ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_try ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-12 11:50:58 +00:00
zend_ast * try_ast = ast - > child [ 0 ] ;
2014-07-27 20:26:06 +00:00
zend_ast_list * catches = zend_ast_get_list ( ast - > child [ 1 ] ) ;
2014-07-12 11:50:58 +00:00
zend_ast * finally_ast = ast - > child [ 2 ] ;
2003-03-06 22:53:23 +00:00
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-12 11:50:58 +00:00
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t try_catch_offset = zend_add_try_element (
2014-07-12 11:50:58 +00:00
get_next_op_number ( CG ( active_op_array ) ) TSRMLS_CC ) ;
2014-08-25 19:21:16 +00:00
uint32_t * jmp_opnums = safe_emalloc ( sizeof ( uint32_t ) , catches - > children , 0 ) ;
2003-03-06 22:53:23 +00:00
2014-07-27 20:26:06 +00:00
if ( catches - > children = = 0 & & ! finally_ast ) {
2014-07-12 11:50:58 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use try without catch or finally " ) ;
}
2003-05-29 19:00:40 +00:00
2014-07-12 11:50:58 +00:00
zend_compile_stmt ( try_ast TSRMLS_CC ) ;
2014-07-27 20:26:06 +00:00
if ( catches - > children ! = 0 ) {
2014-07-18 17:57:38 +00:00
jmp_opnums [ 0 ] = zend_emit_jump ( 0 TSRMLS_CC ) ;
2003-08-23 15:38:58 +00:00
}
2014-07-12 11:50:58 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < catches - > children ; + + i ) {
zend_ast * catch_ast = catches - > child [ i ] ;
2014-07-12 11:50:58 +00:00
zend_ast * class_ast = catch_ast - > child [ 0 ] ;
zend_ast * var_ast = catch_ast - > child [ 1 ] ;
zend_ast * stmt_ast = catch_ast - > child [ 2 ] ;
zval * var_name = zend_ast_get_zval ( var_ast ) ;
2014-07-27 20:26:06 +00:00
zend_bool is_last_catch = ( i + 1 = = catches - > children ) ;
2014-07-12 11:50:58 +00:00
2014-08-25 19:21:16 +00:00
uint32_t opnum_catch ;
2014-07-12 11:50:58 +00:00
2014-07-19 21:30:07 +00:00
if ( ! zend_is_const_default_class_ref ( class_ast ) ) {
2014-07-12 11:50:58 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Bad class name in the catch statement " ) ;
2003-09-02 13:26:25 +00:00
}
2014-07-12 11:50:58 +00:00
opnum_catch = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-12 14:25:47 +00:00
if ( i = = 0 ) {
CG ( active_op_array ) - > try_catch_array [ try_catch_offset ] . catch_op = opnum_catch ;
2004-01-23 20:52:39 +00:00
}
2003-08-23 15:38:58 +00:00
2014-07-16 21:27:27 +00:00
CG ( zend_lineno ) = catch_ast - > lineno ;
2013-01-28 02:02:51 +00:00
2014-07-12 11:50:58 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_CATCH ;
opline - > op1_type = IS_CONST ;
2014-07-19 21:30:07 +00:00
opline - > op1 . constant = zend_add_class_name_literal ( CG ( active_op_array ) ,
zend_resolve_class_name_ast ( class_ast TSRMLS_CC ) TSRMLS_CC ) ;
2010-05-07 16:29:15 +00:00
2014-07-12 11:50:58 +00:00
opline - > op2_type = IS_CV ;
2014-08-25 19:21:16 +00:00
opline - > op2 . var = lookup_cv ( CG ( active_op_array ) , zend_string_copy ( Z_STR_P ( var_name ) ) TSRMLS_CC ) ;
2014-07-12 17:08:09 +00:00
opline - > result . num = is_last_catch ;
2010-05-07 16:29:15 +00:00
2014-07-12 11:50:58 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
2003-03-31 20:42:01 +00:00
2014-07-12 17:08:09 +00:00
if ( ! is_last_catch ) {
2014-07-18 17:57:38 +00:00
jmp_opnums [ i + 1 ] = zend_emit_jump ( 0 TSRMLS_CC ) ;
2004-02-27 09:14:55 +00:00
}
2014-07-12 11:50:58 +00:00
opline = & CG ( active_op_array ) - > opcodes [ opnum_catch ] ;
opline - > extended_value = get_next_op_number ( CG ( active_op_array ) ) ;
2003-03-06 22:53:23 +00:00
}
2014-07-12 11:50:58 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < catches - > children ; + + i ) {
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( jmp_opnums [ i ] TSRMLS_CC ) ;
2014-07-12 11:50:58 +00:00
}
if ( finally_ast ) {
2014-08-25 19:21:16 +00:00
uint32_t opnum_jmp = get_next_op_number ( CG ( active_op_array ) ) + 1 ;
2014-07-12 11:50:58 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_FAST_CALL , NULL , NULL TSRMLS_CC ) ;
2014-07-12 11:50:58 +00:00
opline - > op1 . opline_num = opnum_jmp + 1 ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_JMP , NULL , NULL TSRMLS_CC ) ;
2014-07-12 11:50:58 +00:00
CG ( context ) . in_finally + + ;
zend_compile_stmt ( finally_ast TSRMLS_CC ) ;
CG ( context ) . in_finally - - ;
CG ( active_op_array ) - > try_catch_array [ try_catch_offset ] . finally_op = opnum_jmp + 1 ;
CG ( active_op_array ) - > try_catch_array [ try_catch_offset ] . finally_end
= get_next_op_number ( CG ( active_op_array ) ) ;
2014-08-27 18:45:27 +00:00
CG ( active_op_array ) - > fn_flags | = ZEND_ACC_HAS_FINALLY_BLOCK ;
2014-07-12 11:50:58 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_FAST_RET , NULL , NULL TSRMLS_CC ) ;
2014-07-12 11:50:58 +00:00
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_jmp TSRMLS_CC ) ;
2006-06-07 09:21:06 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-12 11:50:58 +00:00
efree ( jmp_opnums ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-12 11:50:58 +00:00
2014-08-18 14:07:18 +00:00
/* Encoding declarations must already be handled during parsing */
2014-08-29 18:52:26 +00:00
void zend_handle_encoding_declaration ( zend_ast * ast TSRMLS_DC ) /* { { { */
2014-08-29 05:05:58 +00:00
{
2014-08-29 18:52:26 +00:00
zend_ast_list * declares = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < declares - > children ; + + i ) {
zend_ast * declare_ast = declares - > child [ i ] ;
2014-07-22 14:11:19 +00:00
zend_ast * name_ast = declare_ast - > child [ 0 ] ;
zend_ast * value_ast = declare_ast - > child [ 1 ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( name_ast ) ;
2014-07-22 14:11:19 +00:00
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_literal_ci ( name , " encoding " ) ) {
2014-08-18 14:07:18 +00:00
if ( value_ast - > kind ! = ZEND_AST_ZVAL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Encoding must be a literal " ) ;
2014-07-22 14:11:19 +00:00
}
if ( CG ( multibyte ) ) {
2014-08-18 14:07:18 +00:00
zend_string * encoding_name = zval_get_string ( zend_ast_get_zval ( value_ast ) ) ;
2014-07-22 14:11:19 +00:00
const zend_encoding * new_encoding , * old_encoding ;
zend_encoding_filter old_input_filter ;
CG ( encoding_declared ) = 1 ;
2014-08-18 14:07:18 +00:00
new_encoding = zend_multibyte_fetch_encoding ( encoding_name - > val TSRMLS_CC ) ;
2014-07-22 14:11:19 +00:00
if ( ! new_encoding ) {
2014-08-18 14:07:18 +00:00
zend_error ( E_COMPILE_WARNING , " Unsupported encoding [%s] " , encoding_name - > val ) ;
2014-07-22 14:11:19 +00:00
} else {
old_input_filter = LANG_SCNG ( input_filter ) ;
old_encoding = LANG_SCNG ( script_encoding ) ;
zend_multibyte_set_filter ( new_encoding TSRMLS_CC ) ;
/* need to re-scan if input filter changed */
if ( old_input_filter ! = LANG_SCNG ( input_filter ) | |
( old_input_filter & & new_encoding ! = old_encoding ) ) {
zend_multibyte_yyinput_again ( old_input_filter , old_encoding TSRMLS_CC ) ;
}
}
2014-08-18 14:07:18 +00:00
2014-08-25 19:21:16 +00:00
zend_string_release ( encoding_name ) ;
2014-07-22 14:11:19 +00:00
} else {
zend_error ( E_COMPILE_WARNING , " declare(encoding=...) ignored because "
" Zend multibyte feature is turned off by settings " ) ;
}
2014-08-18 14:07:18 +00:00
}
}
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_declare ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-08-18 14:07:18 +00:00
zend_ast_list * declares = zend_ast_get_list ( ast - > child [ 0 ] ) ;
zend_ast * stmt_ast = ast - > child [ 1 ] ;
zend_declarables orig_declarables = CG ( declarables ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-08-18 14:07:18 +00:00
for ( i = 0 ; i < declares - > children ; + + i ) {
zend_ast * declare_ast = declares - > child [ i ] ;
zend_ast * name_ast = declare_ast - > child [ 0 ] ;
zend_ast * value_ast = declare_ast - > child [ 1 ] ;
zend_string * name = zend_ast_get_str ( name_ast ) ;
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_literal_ci ( name , " ticks " ) ) {
2014-08-18 14:07:18 +00:00
zval value_zv ;
zend_const_expr_to_zval ( & value_zv , value_ast TSRMLS_CC ) ;
2014-08-25 19:59:30 +00:00
convert_to_long ( & value_zv ) ;
2014-08-18 14:07:18 +00:00
ZVAL_COPY_VALUE ( & CG ( declarables ) . ticks , & value_zv ) ;
2014-07-22 14:11:19 +00:00
zval_dtor ( & value_zv ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal_ci ( name , " encoding " ) ) {
2014-08-18 14:07:18 +00:00
/* Encoding declaration was already handled during parsing. Here we
* only check that it is the first statement in the file . */
2014-08-25 19:21:16 +00:00
uint32_t num = CG ( active_op_array ) - > last ;
2014-08-18 14:07:18 +00:00
while ( num > 0 & &
( CG ( active_op_array ) - > opcodes [ num - 1 ] . opcode = = ZEND_EXT_STMT | |
CG ( active_op_array ) - > opcodes [ num - 1 ] . opcode = = ZEND_TICKS ) ) {
- - num ;
}
2003-03-05 11:14:44 +00:00
2014-08-18 14:07:18 +00:00
if ( num > 0 ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Encoding declaration pragma must be "
" the very first statement in the script " ) ;
}
2014-07-22 14:11:19 +00:00
} else {
zend_error ( E_COMPILE_WARNING , " Unsupported declare '%s' " , name - > val ) ;
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-07-22 14:11:19 +00:00
if ( stmt_ast ) {
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
2014-07-22 14:18:13 +00:00
CG ( declarables ) = orig_declarables ;
2005-06-24 08:45:17 +00:00
}
2014-07-22 14:11:19 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2006-05-09 23:53:23 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_stmt_list ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_compile_stmt ( list - > child [ i ] TSRMLS_CC ) ;
2014-07-09 21:39:21 +00:00
}
2003-03-05 11:14:44 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-03-05 11:14:44 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_params ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-14 21:03:53 +00:00
zend_op_array * op_array = CG ( active_op_array ) ;
zend_arg_info * arg_infos ;
2012-12-25 06:23:08 +00:00
2014-07-27 20:26:06 +00:00
if ( list - > children = = 0 ) {
2014-07-14 21:03:53 +00:00
return ;
2011-12-19 10:05:48 +00:00
}
2014-07-14 21:03:53 +00:00
2014-07-27 20:26:06 +00:00
arg_infos = safe_emalloc ( sizeof ( zend_arg_info ) , list - > children , 0 ) ;
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * param_ast = list - > child [ i ] ;
2014-07-14 21:03:53 +00:00
zend_ast * type_ast = param_ast - > child [ 0 ] ;
zend_ast * var_ast = param_ast - > child [ 1 ] ;
zend_ast * default_ast = param_ast - > child [ 2 ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( var_ast ) ;
2014-07-14 21:03:53 +00:00
zend_bool is_ref = ( param_ast - > attr & ZEND_PARAM_REF ) ! = 0 ;
zend_bool is_variadic = ( param_ast - > attr & ZEND_PARAM_VARIADIC ) ! = 0 ;
znode var_node , default_node ;
zend_uchar opcode ;
zend_op * opline ;
zend_arg_info * arg_info ;
2011-11-01 00:39:10 +00:00
2014-07-14 21:03:53 +00:00
if ( zend_is_auto_global ( name TSRMLS_CC ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot re-assign auto-global variable %s " ,
name - > val ) ;
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-14 21:03:53 +00:00
var_node . op_type = IS_CV ;
2014-08-25 19:21:16 +00:00
var_node . u . op . var = lookup_cv ( CG ( active_op_array ) , zend_string_copy ( name ) TSRMLS_CC ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-22 14:55:34 +00:00
if ( EX_VAR_TO_NUM ( var_node . u . op . var ) ! = i ) {
2014-08-25 19:21:16 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Redefinition of parameter $%s " ,
2014-07-22 14:55:34 +00:00
name - > val ) ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( name , " this " ) ) {
2014-07-14 21:03:53 +00:00
if ( op_array - > scope & & ( op_array - > fn_flags & ZEND_ACC_STATIC ) = = 0 ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot re-assign $this " ) ;
}
op_array - > this_var = var_node . u . op . var ;
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-14 21:03:53 +00:00
if ( op_array - > fn_flags & ZEND_ACC_VARIADIC ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Only the last parameter can be variadic " ) ;
}
2006-05-09 23:53:23 +00:00
2014-07-14 21:03:53 +00:00
if ( is_variadic ) {
opcode = ZEND_RECV_VARIADIC ;
default_node . op_type = IS_UNUSED ;
op_array - > fn_flags | = ZEND_ACC_VARIADIC ;
1999-04-07 18:10:10 +00:00
2014-07-14 21:03:53 +00:00
if ( default_ast ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" Variadic parameter cannot have a default value " ) ;
}
} else if ( default_ast ) {
opcode = ZEND_RECV_INIT ;
default_node . op_type = IS_CONST ;
2014-07-30 15:44:26 +00:00
zend_const_expr_to_zval ( & default_node . u . constant , default_ast TSRMLS_CC ) ;
2014-07-14 21:03:53 +00:00
} else {
opcode = ZEND_RECV ;
default_node . op_type = IS_UNUSED ;
op_array - > required_num_args = i + 1 ;
}
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , opcode , NULL , & default_node TSRMLS_CC ) ;
2014-07-14 21:03:53 +00:00
SET_NODE ( opline - > result , & var_node ) ;
opline - > op1 . num = i + 1 ;
arg_info = & arg_infos [ i ] ;
arg_info - > name = estrndup ( name - > val , name - > len ) ;
arg_info - > name_len = name - > len ;
arg_info - > pass_by_reference = is_ref ;
arg_info - > is_variadic = is_variadic ;
arg_info - > type_hint = 0 ;
arg_info - > allow_null = 1 ;
arg_info - > class_name = NULL ;
arg_info - > class_name_len = 0 ;
if ( type_ast ) {
zend_bool has_null_default = default_ast
& & ( Z_TYPE ( default_node . u . constant ) = = IS_NULL
| | ( Z_TYPE ( default_node . u . constant ) = = IS_CONSTANT
2014-08-28 23:34:46 +00:00
& & strcasecmp ( Z_STRVAL ( default_node . u . constant ) , " NULL " ) = = 0 )
2014-07-14 21:03:53 +00:00
| | Z_TYPE ( default_node . u . constant ) = = IS_CONSTANT_AST ) ; // ???
op_array - > fn_flags | = ZEND_ACC_HAS_TYPE_HINTS ;
arg_info - > allow_null = has_null_default ;
if ( type_ast - > kind = = ZEND_AST_TYPE ) {
arg_info - > type_hint = type_ast - > attr ;
if ( arg_info - > type_hint = = IS_ARRAY ) {
if ( default_ast & & ! has_null_default
& & Z_TYPE ( default_node . u . constant ) ! = IS_ARRAY
) {
zend_error_noreturn ( E_COMPILE_ERROR , " Default value for parameters "
" with array type hint can only be an array or NULL " ) ;
}
} else if ( arg_info - > type_hint = = IS_CALLABLE & & default_ast ) {
2014-08-28 13:37:30 +00:00
if ( ! has_null_default ) {
2014-07-14 21:03:53 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Default value for parameters "
" with callable type hint can only be NULL " ) ;
}
}
} else {
2014-07-28 13:16:35 +00:00
zend_string * class_name = zend_ast_get_str ( type_ast ) ;
2005-09-16 17:05:09 +00:00
2014-07-14 21:03:53 +00:00
if ( zend_is_const_default_class_ref ( type_ast ) ) {
2014-07-19 21:36:01 +00:00
class_name = zend_resolve_class_name_ast ( type_ast TSRMLS_CC ) ;
2014-07-14 21:03:53 +00:00
} else {
2014-08-25 19:21:16 +00:00
zend_string_addref ( class_name ) ;
2014-07-14 21:03:53 +00:00
}
2006-07-24 17:58:32 +00:00
2014-07-14 21:03:53 +00:00
arg_info - > type_hint = IS_OBJECT ;
arg_info - > class_name = estrndup ( class_name - > val , class_name - > len ) ;
arg_info - > class_name_len = class_name - > len ;
2003-06-08 18:53:58 +00:00
2014-08-25 19:21:16 +00:00
zend_string_release ( class_name ) ;
2014-07-14 21:03:53 +00:00
if ( default_ast & & ! has_null_default ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Default value for parameters "
" with a class type hint can only be NULL " ) ;
}
}
2013-01-14 08:23:22 +00:00
}
2003-06-08 18:53:58 +00:00
}
2014-07-14 21:03:53 +00:00
/* These are assigned at the end to avoid unitialized memory in case of an error */
2014-07-27 20:26:06 +00:00
op_array - > num_args = list - > children ;
2014-07-14 21:03:53 +00:00
op_array - > arg_info = arg_infos ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-14 21:03:53 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_closure_uses ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-18 10:30:39 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * var_ast = list - > child [ i ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( var_ast ) ;
2014-07-18 10:30:39 +00:00
zend_bool by_ref = var_ast - > attr ;
zval zv ;
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_literal ( name , " this " ) ) {
2014-07-18 10:30:39 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use $this as lexical variable " ) ;
2013-01-14 08:23:22 +00:00
}
2014-07-18 10:30:39 +00:00
ZVAL_NULL ( & zv ) ;
Z_CONST_FLAGS ( zv ) = by_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR ;
zend_compile_static_var_common ( var_ast , & zv , by_ref TSRMLS_CC ) ;
2013-01-14 08:23:22 +00:00
}
2003-06-08 18:53:58 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-06-08 18:53:58 +00:00
2014-08-29 05:05:58 +00:00
void zend_begin_method_decl ( zend_op_array * op_array , zend_string * name , zend_bool has_body TSRMLS_DC ) /* { { { */
{
2014-07-19 10:52:44 +00:00
zend_class_entry * ce = CG ( active_class_entry ) ;
zend_bool in_interface = ( ce - > ce_flags & ZEND_ACC_INTERFACE ) ! = 0 ;
2014-07-21 15:14:01 +00:00
zend_bool in_trait = ZEND_CE_IS_TRAIT ( ce ) ;
2014-07-19 10:52:44 +00:00
zend_bool is_public = ( op_array - > fn_flags & ZEND_ACC_PUBLIC ) ! = 0 ;
zend_bool is_static = ( op_array - > fn_flags & ZEND_ACC_STATIC ) ! = 0 ;
1999-12-26 21:21:33 +00:00
2014-07-19 10:52:44 +00:00
zend_string * lcname ;
2003-03-05 11:14:44 +00:00
2014-07-19 10:52:44 +00:00
if ( in_interface ) {
2014-07-26 16:23:46 +00:00
if ( ( op_array - > fn_flags & ZEND_ACC_PPP_MASK ) ! = ZEND_ACC_PUBLIC ) {
2014-07-19 10:52:44 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Access type for interface method "
" %s::%s() must be omitted " , ce - > name - > val , name - > val ) ;
}
op_array - > fn_flags | = ZEND_ACC_ABSTRACT ;
} else if ( is_static & & ( op_array - > fn_flags & ZEND_ACC_ABSTRACT ) ) {
zend_error ( E_STRICT , " Static function %s::%s() should not be abstract " ,
ce - > name - > val , name - > val ) ;
2003-02-11 09:48:37 +00:00
}
2014-07-19 10:52:44 +00:00
if ( op_array - > fn_flags & ZEND_ACC_ABSTRACT ) {
//zend_op *opline;
2003-04-20 14:52:40 +00:00
2014-07-19 10:52:44 +00:00
if ( op_array - > fn_flags & ZEND_ACC_PRIVATE ) {
zend_error_noreturn ( E_COMPILE_ERROR , " %s function %s::%s() cannot be declared private " ,
in_interface ? " Interface " : " Abstract " , ce - > name - > val , name - > val ) ;
}
1999-04-07 18:10:10 +00:00
2014-07-19 10:52:44 +00:00
if ( has_body ) {
zend_error_noreturn ( E_COMPILE_ERROR , " %s function %s::%s() cannot contain body " ,
in_interface ? " Interface " : " Abstract " , ce - > name - > val , name - > val ) ;
}
2002-02-14 04:01:53 +00:00
2014-07-19 10:52:44 +00:00
ce - > ce_flags | = ZEND_ACC_IMPLICIT_ABSTRACT_CLASS ;
2005-04-19 22:04:59 +00:00
2014-07-19 10:52:44 +00:00
/*opline = get_next_op(op_array TSRMLS_CC);
opline - > opcode = ZEND_RAISE_ABSTRACT_ERROR ;
SET_UNUSED ( opline - > op1 ) ;
SET_UNUSED ( opline - > op2 ) ; */
} else if ( ! has_body ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Non-abstract method %s::%s() must contain body " ,
ce - > name - > val , name - > val ) ;
2014-04-03 11:26:23 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-19 10:52:44 +00:00
op_array - > scope = ce ;
2014-08-25 19:21:16 +00:00
op_array - > function_name = zend_string_copy ( name ) ;
2006-05-09 23:53:23 +00:00
2014-08-25 19:21:16 +00:00
lcname = zend_string_alloc ( name - > len , 0 ) ;
2014-07-19 10:52:44 +00:00
zend_str_tolower_copy ( lcname - > val , name - > val , name - > len ) ;
lcname = zend_new_interned_string ( lcname TSRMLS_CC ) ;
2013-01-28 02:02:51 +00:00
2014-07-19 10:52:44 +00:00
if ( zend_hash_add_ptr ( & ce - > function_table , lcname , op_array ) = = NULL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redeclare %s::%s() " ,
ce - > name - > val , name - > val ) ;
2009-11-14 19:17:22 +00:00
}
2002-12-06 17:09:44 +00:00
2014-07-19 10:52:44 +00:00
if ( in_interface ) {
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_literal ( lcname , ZEND_CALL_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __call() must have "
" public visibility and cannot be static " ) ;
2002-10-16 18:06:36 +00:00
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_CALLSTATIC_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | ! is_static ) {
zend_error ( E_WARNING , " The magic method __callStatic() must have "
" public visibility and be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_GET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __get() must have "
" public visibility and cannot be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_SET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __set() must have "
" public visibility and cannot be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_UNSET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __unset() must have "
" public visibility and cannot be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_ISSET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __isset() must have "
" public visibility and cannot be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_TOSTRING_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __toString() must have "
" public visibility and cannot be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_INVOKE_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __invoke() must have "
" public visibility and cannot be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_DEBUGINFO_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __debugInfo() must have "
" public visibility and cannot be static " ) ;
2010-04-20 10:57:45 +00:00
}
2014-07-19 10:52:44 +00:00
}
} else {
2014-08-25 20:40:58 +00:00
if ( ! in_trait & & zend_string_equals_str_ci ( lcname , ce - > name ) ) {
2014-07-19 10:52:44 +00:00
if ( ! ce - > constructor ) {
ce - > constructor = ( zend_function * ) op_array ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_CONSTRUCTOR_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( CG ( active_class_entry ) - > constructor ) {
zend_error ( E_STRICT , " Redefining already defined constructor for class %s " ,
ce - > name - > val ) ;
}
ce - > constructor = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_DESTRUCTOR_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
ce - > destructor = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_CLONE_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
ce - > clone = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_CALL_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __call() must have "
" public visibility and cannot be static " ) ;
}
ce - > __call = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_CALLSTATIC_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | ! is_static ) {
zend_error ( E_WARNING , " The magic method __callStatic() must have "
" public visibility and be static " ) ;
}
ce - > __callstatic = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_GET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __get() must have "
" public visibility and cannot be static " ) ;
}
ce - > __get = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_SET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __set() must have "
" public visibility and cannot be static " ) ;
}
ce - > __set = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_UNSET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __unset() must have "
" public visibility and cannot be static " ) ;
}
ce - > __unset = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_ISSET_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __isset() must have "
" public visibility and cannot be static " ) ;
}
ce - > __isset = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_TOSTRING_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __toString() must have "
" public visibility and cannot be static " ) ;
}
ce - > __tostring = ( zend_function * ) op_array ;
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_INVOKE_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __invoke() must have "
" public visibility and cannot be static " ) ;
}
2014-08-25 20:40:58 +00:00
} else if ( zend_string_equals_literal ( lcname , ZEND_DEBUGINFO_FUNC_NAME ) ) {
2014-07-19 10:52:44 +00:00
if ( ! is_public | | is_static ) {
zend_error ( E_WARNING , " The magic method __debugInfo() must have "
" public visibility and cannot be static " ) ;
}
ce - > __debugInfo = ( zend_function * ) op_array ;
} else if ( ! is_static ) {
op_array - > fn_flags | = ZEND_ACC_ALLOW_STATIC ;
2002-01-05 15:18:30 +00:00
}
}
1999-04-07 18:10:10 +00:00
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static void zend_begin_func_decl ( znode * result , zend_op_array * op_array , zend_ast_decl * decl TSRMLS_DC ) /* { { { */
{
2014-07-21 13:38:21 +00:00
zend_ast * params_ast = decl - > child [ 0 ] ;
zend_string * name = decl - > name , * lcname ;
2014-07-21 13:22:13 +00:00
zend_op * opline ;
2013-01-28 02:02:51 +00:00
2014-07-22 11:30:26 +00:00
op_array - > function_name = name = zend_prefix_with_ns ( name TSRMLS_CC ) ;
2013-01-28 02:02:51 +00:00
2014-08-25 19:21:16 +00:00
lcname = zend_string_alloc ( name - > len , 0 ) ;
2014-07-21 13:22:13 +00:00
zend_str_tolower_copy ( lcname - > val , name - > val , name - > len ) ;
2013-01-28 02:02:51 +00:00
2014-07-21 13:22:13 +00:00
if ( CG ( current_import_function ) ) {
zend_string * import_name = zend_hash_find_ptr ( CG ( current_import_function ) , lcname ) ;
2014-08-25 20:40:58 +00:00
if ( import_name & & ! zend_string_equals_str_ci ( lcname , import_name ) ) {
2014-07-28 20:16:24 +00:00
zend_error ( E_COMPILE_ERROR , " Cannot declare function %s "
" because the name is already in use " , name - > val ) ;
2014-07-21 13:22:13 +00:00
}
2011-05-19 23:20:47 +00:00
}
2003-06-09 13:51:53 +00:00
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_literal ( lcname , ZEND_AUTOLOAD_FUNC_NAME )
2014-07-27 20:26:06 +00:00
& & zend_ast_get_list ( params_ast ) - > children ! = 1
) {
2014-07-21 13:22:13 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " %s() must take exactly 1 argument " ,
ZEND_AUTOLOAD_FUNC_NAME ) ;
}
1999-04-07 18:10:10 +00:00
2014-07-21 13:22:13 +00:00
if ( op_array - > fn_flags & ZEND_ACC_CLOSURE ) {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op_tmp ( result , ZEND_DECLARE_LAMBDA_FUNCTION , NULL , NULL TSRMLS_CC ) ;
2014-07-21 13:22:13 +00:00
} else {
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_DECLARE_FUNCTION ;
opline - > op2_type = IS_CONST ;
2014-08-25 19:21:16 +00:00
LITERAL_STR ( opline - > op2 , zend_string_copy ( lcname ) ) ;
2003-06-09 13:51:53 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-21 13:22:13 +00:00
{
2014-07-29 18:01:11 +00:00
zend_string * key = zend_build_runtime_definition_key ( lcname , decl - > lex_pos TSRMLS_CC ) ;
2006-05-09 23:53:23 +00:00
2014-07-21 13:22:13 +00:00
opline - > op1_type = IS_CONST ;
2014-07-29 18:01:11 +00:00
LITERAL_STR ( opline - > op1 , key ) ;
2014-07-21 13:22:13 +00:00
2014-07-29 18:01:11 +00:00
zend_hash_update_ptr ( CG ( function_table ) , key , op_array ) ;
2014-07-21 13:22:13 +00:00
}
2006-05-09 23:53:23 +00:00
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_func_decl ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-21 13:38:21 +00:00
zend_ast_decl * decl = ( zend_ast_decl * ) ast ;
zend_ast * params_ast = decl - > child [ 0 ] ;
zend_ast * uses_ast = decl - > child [ 1 ] ;
zend_ast * stmt_ast = decl - > child [ 2 ] ;
zend_bool is_method = decl - > kind = = ZEND_AST_METHOD ;
1999-04-07 18:10:10 +00:00
2014-07-18 12:57:00 +00:00
zend_op_array * orig_op_array = CG ( active_op_array ) ;
2014-07-22 14:55:34 +00:00
zend_op_array * op_array = zend_arena_alloc ( & CG ( arena ) , sizeof ( zend_op_array ) ) ;
1999-04-07 18:10:10 +00:00
2014-07-15 22:06:41 +00:00
// TODO.AST interactive (not just here - also bpc etc!)
init_op_array ( op_array , ZEND_USER_FUNCTION , INITIAL_OP_ARRAY_SIZE TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-21 13:38:21 +00:00
op_array - > fn_flags | = decl - > flags ;
op_array - > line_start = decl - > start_lineno ;
op_array - > line_end = decl - > end_lineno ;
if ( decl - > doc_comment ) {
2014-08-25 19:21:16 +00:00
op_array - > doc_comment = zend_string_copy ( decl - > doc_comment ) ;
2014-07-18 13:23:16 +00:00
}
2014-07-21 13:38:21 +00:00
if ( decl - > kind = = ZEND_AST_CLOSURE ) {
2014-07-18 11:15:58 +00:00
op_array - > fn_flags | = ZEND_ACC_CLOSURE ;
}
2006-03-15 09:04:36 +00:00
2014-07-19 10:52:44 +00:00
if ( is_method ) {
2014-07-21 13:38:21 +00:00
zend_bool has_body = stmt_ast ! = NULL ;
zend_begin_method_decl ( op_array , decl - > name , has_body TSRMLS_CC ) ;
2014-07-19 10:52:44 +00:00
} else {
2014-07-21 13:38:21 +00:00
zend_begin_func_decl ( result , op_array , decl TSRMLS_CC ) ;
2006-03-15 09:04:36 +00:00
}
2014-07-15 22:06:41 +00:00
CG ( active_op_array ) = op_array ;
zend_stack_push ( & CG ( context_stack ) , ( void * ) & CG ( context ) ) ;
zend_init_compiler_context ( TSRMLS_C ) ;
if ( CG ( compiler_options ) & ZEND_COMPILE_EXTENDED_INFO ) {
2014-07-28 20:03:16 +00:00
zend_op * opline_ext = zend_emit_op ( NULL , ZEND_EXT_NOP , NULL , NULL TSRMLS_CC ) ;
2014-07-21 13:38:21 +00:00
opline_ext - > lineno = decl - > start_lineno ;
2007-09-28 19:52:53 +00:00
}
2014-07-15 22:06:41 +00:00
{
2014-08-29 19:47:10 +00:00
/* Push a separator to the loop variable stack */
znode dummy_var ;
dummy_var . op_type = IS_UNUSED ;
2014-07-15 22:06:41 +00:00
2014-08-29 19:47:10 +00:00
zend_stack_push ( & CG ( loop_var_stack ) , ( void * ) & dummy_var ) ;
2006-03-15 09:04:36 +00:00
}
2014-07-21 13:38:21 +00:00
zend_compile_params ( params_ast TSRMLS_CC ) ;
2014-07-27 20:26:06 +00:00
if ( uses_ast ) {
zend_compile_closure_uses ( uses_ast TSRMLS_CC ) ;
2008-11-04 15:58:55 +00:00
}
2014-07-21 13:38:21 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
2008-11-04 15:58:55 +00:00
2014-07-19 10:52:44 +00:00
if ( is_method ) {
zend_check_magic_method_implementation (
CG ( active_class_entry ) , ( zend_function * ) op_array , E_COMPILE_ERROR TSRMLS_CC ) ;
}
2008-11-11 19:45:29 +00:00
2014-07-15 22:06:41 +00:00
zend_do_extended_info ( TSRMLS_C ) ;
2014-07-26 19:32:48 +00:00
zend_emit_final_return ( NULL TSRMLS_CC ) ;
2008-11-11 19:45:29 +00:00
2014-07-15 22:06:41 +00:00
pass_two ( CG ( active_op_array ) TSRMLS_CC ) ;
zend_release_labels ( 0 TSRMLS_CC ) ;
2008-11-11 19:45:29 +00:00
2014-08-29 19:47:10 +00:00
/* Pop the loop variable stack separator */
zend_stack_del_top ( & CG ( loop_var_stack ) ) ;
2008-11-04 15:58:55 +00:00
2014-07-18 10:58:24 +00:00
CG ( active_op_array ) = orig_op_array ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-01-28 02:02:51 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_prop_decl ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t flags = list - > attr ;
2014-07-19 12:54:56 +00:00
zend_class_entry * ce = CG ( active_class_entry ) ;
2014-08-25 19:21:16 +00:00
uint32_t i , children = list - > children ;
2014-07-30 17:12:48 +00:00
zend_string * doc_comment = NULL ;
2008-11-04 15:58:55 +00:00
2014-07-19 12:54:56 +00:00
if ( ce - > ce_flags & ZEND_ACC_INTERFACE ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Interfaces may not include member variables " ) ;
1999-04-07 18:10:10 +00:00
}
2014-07-19 12:54:56 +00:00
if ( flags & ZEND_ACC_ABSTRACT ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Properties cannot be declared abstract " ) ;
}
2014-06-30 11:43:45 +00:00
2014-07-30 17:12:48 +00:00
/* Doc comment has been appended as last element in property list */
if ( list - > child [ children - 1 ] - > kind = = ZEND_AST_ZVAL ) {
2014-08-25 19:21:16 +00:00
doc_comment = zend_string_copy ( zend_ast_get_str ( list - > child [ children - 1 ] ) ) ;
2014-07-30 17:12:48 +00:00
children - = 1 ;
1999-04-07 18:10:10 +00:00
}
2014-07-30 17:12:48 +00:00
for ( i = 0 ; i < children ; + + i ) {
2014-07-27 20:26:06 +00:00
zend_ast * prop_ast = list - > child [ i ] ;
2014-07-19 12:54:56 +00:00
zend_ast * name_ast = prop_ast - > child [ 0 ] ;
zend_ast * value_ast = prop_ast - > child [ 1 ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( name_ast ) ;
2014-07-19 12:54:56 +00:00
zval value_zv ;
1999-04-07 18:10:10 +00:00
2014-07-19 12:54:56 +00:00
if ( flags & ZEND_ACC_FINAL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot declare property %s::$%s final, "
" the final modifier is allowed only for methods and classes " ,
ce - > name - > val , name - > val ) ;
}
1999-04-07 18:10:10 +00:00
2014-07-19 12:54:56 +00:00
if ( zend_hash_exists ( & ce - > properties_info , name ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redeclare %s::$%s " ,
ce - > name - > val , name - > val ) ;
}
2014-04-22 15:54:34 +00:00
2014-07-19 12:54:56 +00:00
if ( value_ast ) {
2014-07-30 15:44:26 +00:00
zend_const_expr_to_zval ( & value_zv , value_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
} else {
2014-07-19 12:54:56 +00:00
ZVAL_NULL ( & value_zv ) ;
1999-04-07 18:10:10 +00:00
}
2014-07-24 19:35:57 +00:00
name = zend_new_interned_string_safe ( name TSRMLS_CC ) ;
2014-07-30 17:12:48 +00:00
zend_declare_property_ex ( ce , name , & value_zv , flags , doc_comment TSRMLS_CC ) ;
/* Doc comment is only assigned to first property */
doc_comment = NULL ;
1999-04-07 18:10:10 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_class_const_decl ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-07-19 13:13:50 +00:00
zend_class_entry * ce = CG ( active_class_entry ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-05-29 14:21:56 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * const_ast = list - > child [ i ] ;
2014-07-19 13:13:50 +00:00
zend_ast * name_ast = const_ast - > child [ 0 ] ;
zend_ast * value_ast = const_ast - > child [ 1 ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( name_ast ) ;
2014-07-19 13:13:50 +00:00
zval value_zv ;
2014-05-29 14:21:56 +00:00
2014-07-21 15:14:01 +00:00
if ( ZEND_CE_IS_TRAIT ( ce ) ) {
2014-07-19 13:13:50 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Traits cannot have constants " ) ;
return ;
2014-05-29 14:21:56 +00:00
}
2014-07-30 15:44:26 +00:00
zend_const_expr_to_zval ( & value_zv , value_ast TSRMLS_CC ) ;
2014-07-19 13:13:50 +00:00
2014-07-24 19:35:57 +00:00
name = zend_new_interned_string_safe ( name TSRMLS_CC ) ;
2014-07-19 13:13:50 +00:00
if ( zend_hash_add ( & ce - > constants_table , name , & value_zv ) = = NULL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redefine class constant %s::%s " ,
2014-07-26 16:23:46 +00:00
ce - > name - > val , name - > val ) ;
2014-05-29 14:21:56 +00:00
}
2014-07-22 14:55:34 +00:00
if ( Z_CONSTANT ( value_zv ) ) {
ce - > ce_flags & = ~ ZEND_ACC_CONSTANTS_UPDATED ;
}
2014-05-29 14:21:56 +00:00
}
2014-04-22 15:54:34 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-04-22 15:54:34 +00:00
2014-08-29 05:05:58 +00:00
static zend_trait_method_reference * zend_compile_method_ref ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-19 20:39:01 +00:00
zend_ast * class_ast = ast - > child [ 0 ] ;
zend_ast * method_ast = ast - > child [ 1 ] ;
1999-04-07 18:10:10 +00:00
2014-07-19 20:39:01 +00:00
zend_trait_method_reference * method_ref = emalloc ( sizeof ( zend_trait_method_reference ) ) ;
method_ref - > ce = NULL ;
2014-08-25 19:21:16 +00:00
method_ref - > method_name = zend_string_copy ( zend_ast_get_str ( method_ast ) ) ;
2002-03-17 19:13:46 +00:00
2014-07-19 20:39:01 +00:00
if ( class_ast ) {
2014-07-19 21:36:01 +00:00
method_ref - > class_name = zend_resolve_class_name_ast ( class_ast TSRMLS_CC ) ;
2014-07-19 20:39:01 +00:00
} else {
method_ref - > class_name = NULL ;
1999-04-07 18:10:10 +00:00
}
2014-07-19 20:39:01 +00:00
return method_ref ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static zend_string * * zend_compile_name_list ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
zend_string * * names = safe_emalloc ( sizeof ( zend_string * ) , list - > children + 1 , 0 ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-19 20:39:01 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * name_ast = list - > child [ i ] ;
2014-07-19 21:36:01 +00:00
names [ i ] = zend_resolve_class_name_ast ( name_ast TSRMLS_CC ) ;
2014-07-19 20:39:01 +00:00
}
2014-07-27 20:26:06 +00:00
names [ list - > children ] = NULL ;
2014-07-19 20:39:01 +00:00
return names ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static void zend_compile_trait_precedence ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-19 20:39:01 +00:00
zend_ast * method_ref_ast = ast - > child [ 0 ] ;
zend_ast * insteadof_ast = ast - > child [ 1 ] ;
zend_trait_precedence * precedence = emalloc ( sizeof ( zend_trait_precedence ) ) ;
precedence - > trait_method = zend_compile_method_ref ( method_ref_ast TSRMLS_CC ) ;
precedence - > exclude_from_classes
= ( void * ) zend_compile_name_list ( insteadof_ast TSRMLS_CC ) ;
zend_add_to_list ( & CG ( active_class_entry ) - > trait_precedences , precedence TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static void zend_compile_trait_alias ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-19 20:39:01 +00:00
zend_ast * method_ref_ast = ast - > child [ 0 ] ;
zend_ast * alias_ast = ast - > child [ 1 ] ;
2014-08-25 19:21:16 +00:00
uint32_t modifiers = ast - > attr ;
2014-07-19 20:39:01 +00:00
zend_trait_alias * alias ;
if ( modifiers = = ZEND_ACC_STATIC ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use 'static' as method modifier " ) ;
} else if ( modifiers = = ZEND_ACC_ABSTRACT ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use 'abstract' as method modifier " ) ;
} else if ( modifiers = = ZEND_ACC_FINAL ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use 'final' as method modifier " ) ;
}
alias = emalloc ( sizeof ( zend_trait_alias ) ) ;
alias - > trait_method = zend_compile_method_ref ( method_ref_ast TSRMLS_CC ) ;
alias - > modifiers = modifiers ;
if ( alias_ast ) {
2014-08-25 19:21:16 +00:00
alias - > alias = zend_string_copy ( zend_ast_get_str ( alias_ast ) ) ;
2014-07-19 20:39:01 +00:00
} else {
alias - > alias = NULL ;
}
zend_add_to_list ( & CG ( active_class_entry ) - > trait_aliases , alias TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_use_trait ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * traits = zend_ast_get_list ( ast - > child [ 0 ] ) ;
zend_ast_list * adaptations = ast - > child [ 1 ] ? zend_ast_get_list ( ast - > child [ 1 ] ) : NULL ;
2014-07-19 20:39:01 +00:00
zend_class_entry * ce = CG ( active_class_entry ) ;
1999-04-07 18:10:10 +00:00
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
1999-04-07 18:10:10 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < traits - > children ; + + i ) {
zend_ast * trait_ast = traits - > child [ i ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( trait_ast ) ;
2014-07-19 20:39:01 +00:00
if ( ce - > ce_flags & ZEND_ACC_INTERFACE ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use traits inside of interfaces. "
" %s is used in %s " , name - > val , ce - > name - > val ) ;
1999-04-07 18:10:10 +00:00
}
2014-07-19 20:39:01 +00:00
2014-07-28 13:39:43 +00:00
switch ( zend_get_class_fetch_type ( name ) ) {
2014-07-19 20:39:01 +00:00
case ZEND_FETCH_CLASS_SELF :
case ZEND_FETCH_CLASS_PARENT :
case ZEND_FETCH_CLASS_STATIC :
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use '%s' as trait name "
" as it is reserved " , name - > val ) ;
break ;
}
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_ADD_TRAIT ;
SET_NODE ( opline - > op1 , & CG ( implementing_class ) ) ;
opline - > extended_value = ZEND_FETCH_CLASS_TRAIT ;
opline - > op2_type = IS_CONST ;
2014-07-19 21:30:07 +00:00
opline - > op2 . constant = zend_add_class_name_literal ( CG ( active_op_array ) ,
zend_resolve_class_name_ast ( trait_ast TSRMLS_CC ) TSRMLS_CC ) ;
2014-07-19 20:39:01 +00:00
ce - > num_traits + + ;
1999-04-07 18:10:10 +00:00
}
2001-07-16 15:48:31 +00:00
2014-07-27 20:26:06 +00:00
if ( ! adaptations ) {
2014-07-19 20:39:01 +00:00
return ;
}
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < adaptations - > children ; + + i ) {
zend_ast * adaptation_ast = adaptations - > child [ i ] ;
2014-07-19 20:39:01 +00:00
switch ( adaptation_ast - > kind ) {
case ZEND_AST_TRAIT_PRECEDENCE :
zend_compile_trait_precedence ( adaptation_ast TSRMLS_CC ) ;
break ;
case ZEND_AST_TRAIT_ALIAS :
zend_compile_trait_alias ( adaptation_ast TSRMLS_CC ) ;
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
}
2001-07-16 15:48:31 +00:00
}
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_implements ( znode * class_node , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * class_ast = list - > child [ i ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( class_ast ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-21 15:14:01 +00:00
zend_op * opline ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-21 15:14:01 +00:00
/* Traits can not implement interfaces */
if ( ZEND_CE_IS_TRAIT ( CG ( active_class_entry ) ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use '%s' as interface on '%s' "
" since it is a Trait " , name - > val , CG ( active_class_entry ) - > name - > val ) ;
}
if ( ! zend_is_const_default_class_ref ( class_ast ) ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" Cannot use '%s' as interface name as it is reserved " , name - > val ) ;
}
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_ADD_INTERFACE , class_node , NULL TSRMLS_CC ) ;
2014-07-21 15:14:01 +00:00
opline - > extended_value = ZEND_FETCH_CLASS_INTERFACE ;
opline - > op2_type = IS_CONST ;
opline - > op2 . constant = zend_add_class_name_literal ( CG ( active_op_array ) ,
zend_resolve_class_name_ast ( class_ast TSRMLS_CC ) TSRMLS_CC ) ;
CG ( active_class_entry ) - > num_interfaces + + ;
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_class_decl ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-21 14:34:45 +00:00
zend_ast_decl * decl = ( zend_ast_decl * ) ast ;
zend_ast * extends_ast = decl - > child [ 0 ] ;
zend_ast * implements_ast = decl - > child [ 1 ] ;
zend_ast * stmt_ast = decl - > child [ 2 ] ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-21 14:34:45 +00:00
zend_string * name = decl - > name , * lcname , * import_name = NULL ;
2014-07-22 14:55:34 +00:00
zend_class_entry * ce = zend_arena_alloc ( & CG ( arena ) , sizeof ( zend_class_entry ) ) ;
2014-07-21 14:34:45 +00:00
zend_op * opline ;
2014-07-21 15:14:01 +00:00
znode declare_node , extends_node ;
2014-07-21 14:34:45 +00:00
if ( CG ( active_class_entry ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Class declarations may not be nested " ) ;
return ;
2012-12-25 06:23:08 +00:00
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-28 13:39:43 +00:00
if ( ZEND_FETCH_CLASS_DEFAULT ! = zend_get_class_fetch_type ( name ) ) {
2014-07-21 14:34:45 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use '%s' as class name as it is reserved " ,
name - > val ) ;
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-08-25 19:21:16 +00:00
lcname = zend_string_alloc ( name - > len , 0 ) ;
2014-07-21 14:34:45 +00:00
zend_str_tolower_copy ( lcname - > val , name - > val , name - > len ) ;
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-21 14:34:45 +00:00
if ( CG ( current_import ) ) {
import_name = zend_hash_find_ptr ( CG ( current_import ) , lcname ) ;
}
Implemented Traits for PHP as proposed in the RFC [TRAITS]
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
2010-04-22 22:05:56 +00:00
2014-07-28 20:38:26 +00:00
if ( CG ( current_namespace ) ) {
name = zend_prefix_with_ns ( name TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-08-25 19:21:16 +00:00
zend_string_release ( lcname ) ;
lcname = zend_string_alloc ( name - > len , 0 ) ;
2014-07-21 14:34:45 +00:00
zend_str_tolower_copy ( lcname - > val , name - > val , name - > len ) ;
2002-11-10 17:50:27 +00:00
} else {
2014-08-25 19:21:16 +00:00
zend_string_addref ( name ) ;
2002-11-10 17:50:27 +00:00
}
2014-07-21 14:34:45 +00:00
2014-08-25 20:40:58 +00:00
if ( import_name & & ! zend_string_equals_str_ci ( lcname , import_name ) ) {
2014-07-28 20:16:24 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot declare class %s "
" because the name is already in use " , name - > val ) ;
2014-07-21 14:34:45 +00:00
}
2014-07-24 19:07:37 +00:00
name = zend_new_interned_string ( name TSRMLS_CC ) ;
lcname = zend_new_interned_string ( lcname TSRMLS_CC ) ;
2014-07-21 14:34:45 +00:00
ce - > type = ZEND_USER_CLASS ;
2014-07-24 19:07:37 +00:00
ce - > name = name ;
2014-07-21 14:34:45 +00:00
zend_initialize_class_data ( ce , 1 TSRMLS_CC ) ;
ce - > ce_flags | = decl - > flags ;
ce - > info . user . filename = zend_get_compiled_filename ( TSRMLS_C ) ;
ce - > info . user . line_start = decl - > start_lineno ;
ce - > info . user . line_end = decl - > end_lineno ;
if ( decl - > doc_comment ) {
2014-08-25 19:21:16 +00:00
ce - > info . user . doc_comment = zend_string_copy ( decl - > doc_comment ) ;
1999-04-07 18:10:10 +00:00
}
2003-01-19 17:25:39 +00:00
2014-07-21 14:34:45 +00:00
if ( extends_ast ) {
2014-07-21 15:14:01 +00:00
if ( ZEND_CE_IS_TRAIT ( ce ) ) {
2014-07-21 14:34:45 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " A trait (%s) cannot extend a class. "
" Traits can only be composed from other traits with the 'use' keyword. Error " ,
name - > val ) ;
}
if ( ! zend_is_const_default_class_ref ( extends_ast ) ) {
2014-07-28 13:16:35 +00:00
zend_string * extends_name = zend_ast_get_str ( extends_ast ) ;
2014-07-21 14:34:45 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
2014-07-21 16:15:09 +00:00
" Cannot use '%s' as class name as it is reserved " , extends_name - > val ) ;
2008-01-23 17:55:55 +00:00
}
2014-07-21 14:34:45 +00:00
zend_compile_class_ref ( & extends_node , extends_ast TSRMLS_CC ) ;
2008-01-23 17:55:55 +00:00
}
2003-01-19 17:25:39 +00:00
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_make_var_result ( & declare_node , opline TSRMLS_CC ) ;
2003-01-19 17:25:39 +00:00
2014-07-21 15:14:01 +00:00
// TODO.AST drop this
GET_NODE ( & CG ( implementing_class ) , opline - > result ) ;
2003-01-19 17:25:39 +00:00
2014-07-21 14:34:45 +00:00
opline - > op2_type = IS_CONST ;
LITERAL_STR ( opline - > op2 , lcname ) ;
2008-07-14 09:49:03 +00:00
2014-07-21 14:34:45 +00:00
if ( extends_ast ) {
opline - > opcode = ZEND_DECLARE_INHERITED_CLASS ;
opline - > extended_value = extends_node . u . op . var ;
2008-07-14 09:49:03 +00:00
} else {
2014-07-21 14:34:45 +00:00
opline - > opcode = ZEND_DECLARE_CLASS ;
2008-07-14 09:49:03 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-21 14:34:45 +00:00
{
2014-07-29 18:01:11 +00:00
zend_string * key = zend_build_runtime_definition_key ( lcname , decl - > lex_pos TSRMLS_CC ) ;
2008-07-14 09:49:03 +00:00
2014-07-21 14:34:45 +00:00
opline - > op1_type = IS_CONST ;
2014-07-29 18:01:11 +00:00
LITERAL_STR ( opline - > op1 , key ) ;
2014-07-21 14:34:45 +00:00
2014-07-29 18:01:11 +00:00
zend_hash_update_ptr ( CG ( class_table ) , key , ce ) ;
2008-07-14 09:49:03 +00:00
}
2014-07-21 14:34:45 +00:00
CG ( active_class_entry ) = ce ;
2008-07-14 09:49:03 +00:00
2014-07-21 15:14:01 +00:00
if ( implements_ast ) {
zend_compile_implements ( & declare_node , implements_ast TSRMLS_CC ) ;
}
1999-04-07 18:10:10 +00:00
2014-07-21 14:34:45 +00:00
zend_compile_stmt ( stmt_ast TSRMLS_CC ) ;
2014-07-21 16:15:09 +00:00
if ( ce - > constructor ) {
ce - > constructor - > common . fn_flags | = ZEND_ACC_CTOR ;
if ( ce - > constructor - > common . fn_flags & ZEND_ACC_STATIC ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Constructor %s::%s() cannot be static " ,
ce - > name - > val , ce - > constructor - > common . function_name - > val ) ;
}
}
if ( ce - > destructor ) {
ce - > destructor - > common . fn_flags | = ZEND_ACC_DTOR ;
if ( ce - > destructor - > common . fn_flags & ZEND_ACC_STATIC ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Destructor %s::%s() cannot be static " ,
ce - > name - > val , ce - > destructor - > common . function_name - > val ) ;
}
}
if ( ce - > clone ) {
ce - > clone - > common . fn_flags | = ZEND_ACC_CLONE ;
if ( ce - > clone - > common . fn_flags & ZEND_ACC_STATIC ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Clone method %s::%s() cannot be static " ,
ce - > name - > val , ce - > clone - > common . function_name - > val ) ;
2008-01-23 17:55:55 +00:00
}
}
2014-07-21 15:14:01 +00:00
/* Check for traits and proceed like with interfaces.
* The only difference will be a combined handling of them in the end .
* Thus , we need another opcode here . */
if ( ce - > num_traits > 0 ) {
ce - > traits = NULL ;
ce - > num_traits = 0 ;
ce - > ce_flags | = ZEND_ACC_IMPLEMENT_TRAITS ;
1999-04-07 18:10:10 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_BIND_TRAITS , & declare_node , NULL TSRMLS_CC ) ;
2014-07-21 15:14:01 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-21 15:14:01 +00:00
if ( ! ( ce - > ce_flags & ( ZEND_ACC_INTERFACE | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS ) )
& & ( extends_ast | | ce - > num_interfaces > 0 )
) {
zend_verify_abstract_class ( ce TSRMLS_CC ) ;
if ( ce - > num_interfaces & & ! ( ce - > ce_flags & ZEND_ACC_IMPLEMENT_TRAITS ) ) {
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_VERIFY_ABSTRACT_CLASS , & declare_node , NULL TSRMLS_CC ) ;
2014-06-06 11:04:30 +00:00
}
}
1999-04-07 18:10:10 +00:00
2014-07-21 15:14:01 +00:00
/* Inherit interfaces; reset number to zero, we need it for above check and
* will restore it during actual implementation .
* The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
* zend_verify_abstract_class ( ) */
if ( ce - > num_interfaces > 0 ) {
ce - > interfaces = NULL ;
ce - > num_interfaces = 0 ;
ce - > ce_flags | = ZEND_ACC_IMPLEMENT_INTERFACES ;
}
1999-04-07 18:10:10 +00:00
2014-07-21 14:34:45 +00:00
CG ( active_class_entry ) = NULL ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static HashTable * zend_get_import_ht ( uint32_t type TSRMLS_DC ) /* { { { */
{
2014-07-21 21:41:11 +00:00
switch ( type ) {
case T_CLASS :
if ( ! CG ( current_import ) ) {
CG ( current_import ) = emalloc ( sizeof ( HashTable ) ) ;
zend_hash_init ( CG ( current_import ) , 8 , NULL , str_dtor , 0 ) ;
}
return CG ( current_import ) ;
case T_FUNCTION :
if ( ! CG ( current_import_function ) ) {
CG ( current_import_function ) = emalloc ( sizeof ( HashTable ) ) ;
zend_hash_init ( CG ( current_import_function ) , 8 , NULL , str_dtor , 0 ) ;
}
return CG ( current_import_function ) ;
case T_CONST :
if ( ! CG ( current_import_const ) ) {
CG ( current_import_const ) = emalloc ( sizeof ( HashTable ) ) ;
zend_hash_init ( CG ( current_import_const ) , 8 , NULL , str_dtor , 0 ) ;
}
return CG ( current_import_const ) ;
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-12-23 15:03:25 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static char * zend_get_use_type_str ( uint32_t type ) /* { { { */
{
2014-07-21 21:41:11 +00:00
switch ( type ) {
case T_CLASS :
return " " ;
case T_FUNCTION :
return " function " ;
case T_CONST :
return " const " ;
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-07 18:10:10 +00:00
}
2014-07-21 21:41:11 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-21 21:41:11 +00:00
2014-08-29 05:05:58 +00:00
static void zend_check_already_in_use ( uint32_t type , zend_string * old_name , zend_string * new_name , zend_string * check_name ) /* { { { */
{
2014-08-25 20:40:58 +00:00
if ( zend_string_equals_str_ci ( old_name , check_name ) ) {
2014-07-28 20:16:24 +00:00
return ;
2010-12-01 13:33:49 +00:00
}
2014-07-21 21:41:11 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use%s %s as %s because the name "
" is already in use " , zend_get_use_type_str ( type ) , old_name - > val , new_name - > val ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_use ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-28 20:38:26 +00:00
zend_string * current_ns = CG ( current_namespace ) ;
2014-08-25 19:21:16 +00:00
uint32_t type = ast - > attr ;
2014-07-21 21:41:11 +00:00
HashTable * current_import = zend_get_import_ht ( type TSRMLS_CC ) ;
zend_bool case_sensitive = type = = T_CONST ;
2014-07-21 20:49:31 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * use_ast = list - > child [ i ] ;
2014-07-21 20:49:31 +00:00
zend_ast * old_name_ast = use_ast - > child [ 0 ] ;
zend_ast * new_name_ast = use_ast - > child [ 1 ] ;
2014-07-28 13:16:35 +00:00
zend_string * old_name = zend_ast_get_str ( old_name_ast ) ;
2014-07-21 21:41:11 +00:00
zend_string * new_name , * lookup_name ;
2014-07-21 20:49:31 +00:00
if ( new_name_ast ) {
2014-08-25 19:21:16 +00:00
new_name = zend_string_copy ( zend_ast_get_str ( new_name_ast ) ) ;
2014-07-21 20:49:31 +00:00
} else {
/* The form "use A\B" is eqivalent to "use A\B as B" */
const char * p = zend_memrchr ( old_name - > val , ' \\ ' , old_name - > len ) ;
if ( p ) {
2014-08-25 19:21:16 +00:00
new_name = zend_string_init ( p + 1 , old_name - > len - ( p - old_name - > val + 1 ) , 0 ) ;
2014-07-21 20:49:31 +00:00
} else {
2014-08-25 19:21:16 +00:00
new_name = zend_string_copy ( old_name ) ;
1999-04-07 18:10:10 +00:00
2014-07-21 20:49:31 +00:00
if ( ! current_ns ) {
2014-08-25 20:40:58 +00:00
if ( type = = T_CLASS & & zend_string_equals_literal ( new_name , " strict " ) ) {
2014-07-21 20:49:31 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
" You seem to be trying to use a different language... " ) ;
}
2002-03-17 19:13:46 +00:00
2014-07-21 20:49:31 +00:00
zend_error ( E_WARNING , " The use statement with non-compound name '%s' "
" has no effect " , new_name - > val ) ;
}
}
}
1999-04-07 18:10:10 +00:00
2014-07-21 21:41:11 +00:00
if ( case_sensitive ) {
2014-08-25 19:21:16 +00:00
lookup_name = zend_string_copy ( new_name ) ;
2014-07-21 21:41:11 +00:00
} else {
2014-08-25 19:21:16 +00:00
lookup_name = zend_string_alloc ( new_name - > len , 0 ) ;
2014-07-21 21:41:11 +00:00
zend_str_tolower_copy ( lookup_name - > val , new_name - > val , new_name - > len ) ;
}
1999-04-07 18:10:10 +00:00
2014-08-25 20:40:58 +00:00
if ( type = = T_CLASS & & ( zend_string_equals_literal ( lookup_name , " self " )
| | zend_string_equals_literal ( lookup_name , " parent " ) )
2014-07-21 21:41:11 +00:00
) {
2014-07-21 20:49:31 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use %s as %s because '%s' "
" is a special class name " , old_name - > val , new_name - > val , new_name - > val ) ;
2004-10-04 19:54:35 +00:00
}
1999-04-07 18:10:10 +00:00
2014-07-21 20:49:31 +00:00
if ( current_ns ) {
2014-08-25 19:21:16 +00:00
zend_string * ns_name = zend_string_alloc ( current_ns - > len + 1 + new_name - > len , 0 ) ;
2014-07-21 20:49:31 +00:00
zend_str_tolower_copy ( ns_name - > val , current_ns - > val , current_ns - > len ) ;
ns_name - > val [ current_ns - > len ] = ' \\ ' ;
2014-07-21 21:41:11 +00:00
memcpy ( ns_name - > val + current_ns - > len + 1 , lookup_name - > val , lookup_name - > len ) ;
1999-04-07 18:10:10 +00:00
2014-07-21 20:49:31 +00:00
if ( zend_hash_exists ( CG ( class_table ) , ns_name ) ) {
2014-07-21 21:41:11 +00:00
zend_check_already_in_use ( type , old_name , new_name , ns_name ) ;
2014-07-21 20:49:31 +00:00
}
2001-12-26 14:46:18 +00:00
2014-08-25 19:21:16 +00:00
zend_string_free ( ns_name ) ;
2012-04-12 09:54:52 +00:00
} else {
2014-07-21 21:41:11 +00:00
switch ( type ) {
case T_CLASS :
{
zend_class_entry * ce = zend_hash_find_ptr ( CG ( class_table ) , lookup_name ) ;
if ( ce & & ce - > type = = ZEND_USER_CLASS
& & ce - > info . user . filename = = CG ( compiled_filename )
) {
zend_check_already_in_use ( type , old_name , new_name , lookup_name ) ;
}
break ;
}
case T_FUNCTION :
{
zend_function * fn = zend_hash_find_ptr ( CG ( function_table ) , lookup_name ) ;
if ( fn & & fn - > type = = ZEND_USER_FUNCTION
2014-07-28 20:30:24 +00:00
& & fn - > op_array . filename = = CG ( compiled_filename )
2014-07-21 21:41:11 +00:00
) {
zend_check_already_in_use ( type , old_name , new_name , lookup_name ) ;
}
break ;
}
case T_CONST :
{
zend_string * filename = zend_hash_find_ptr ( & CG ( const_filenames ) , lookup_name ) ;
2014-07-28 20:30:24 +00:00
if ( filename & & filename = = CG ( compiled_filename ) ) {
2014-07-21 21:41:11 +00:00
zend_check_already_in_use ( type , old_name , new_name , lookup_name ) ;
}
break ;
}
EMPTY_SWITCH_DEFAULT_CASE ( )
2014-07-21 20:49:31 +00:00
}
2012-04-12 09:54:52 +00:00
}
2014-08-25 19:21:16 +00:00
zend_string_addref ( old_name ) ;
2014-07-21 21:41:11 +00:00
if ( ! zend_hash_add_ptr ( current_import , lookup_name , old_name ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use%s %s as %s because the name "
" is already in use " , zend_get_use_type_str ( type ) , old_name - > val , new_name - > val ) ;
2014-07-21 20:49:31 +00:00
}
2014-08-25 19:21:16 +00:00
zend_string_release ( lookup_name ) ;
zend_string_release ( new_name ) ;
2012-04-12 09:54:52 +00:00
}
2014-07-21 20:49:31 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2006-05-09 23:53:23 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_const_decl ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * const_ast = list - > child [ i ] ;
2014-07-22 09:55:07 +00:00
zend_ast * name_ast = const_ast - > child [ 0 ] ;
zend_ast * value_ast = const_ast - > child [ 1 ] ;
2014-07-28 13:16:35 +00:00
zend_string * name = zend_ast_get_str ( name_ast ) ;
2006-05-09 23:53:23 +00:00
2014-07-22 09:55:07 +00:00
zend_string * import_name ;
znode name_node , value_node ;
zval * value_zv = & value_node . u . constant ;
value_node . op_type = IS_CONST ;
2014-07-30 15:44:26 +00:00
zend_const_expr_to_zval ( value_zv , value_ast TSRMLS_CC ) ;
2014-07-22 09:55:07 +00:00
if ( zend_get_ct_const ( name , 0 TSRMLS_CC ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot redeclare constant '%s' " , name - > val ) ;
2004-10-04 19:54:35 +00:00
}
2002-02-04 19:29:56 +00:00
2014-07-22 11:30:26 +00:00
name = zend_prefix_with_ns ( name TSRMLS_CC ) ;
2014-07-22 09:55:07 +00:00
if ( CG ( current_import_const )
& & ( import_name = zend_hash_find_ptr ( CG ( current_import_const ) , name ) )
) {
2014-08-25 20:40:58 +00:00
if ( ! zend_string_equals ( import_name , name ) ) {
2014-07-22 09:55:07 +00:00
zend_error ( E_COMPILE_ERROR , " Cannot declare const %s because "
" the name is already in use " , name - > val ) ;
}
}
name_node . op_type = IS_CONST ;
ZVAL_STR ( & name_node . u . constant , name ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_DECLARE_CONST , & name_node , & value_node TSRMLS_CC ) ;
2014-07-22 09:55:07 +00:00
zend_hash_add_ptr ( & CG ( const_filenames ) , name , CG ( compiled_filename ) ) ;
}
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}}*/
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_namespace ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-22 10:45:44 +00:00
zend_ast * name_ast = ast - > child [ 0 ] ;
zend_ast * stmt_ast = ast - > child [ 1 ] ;
zend_string * name ;
2014-07-22 12:08:52 +00:00
zend_bool with_bracket = stmt_ast ! = NULL ;
2002-07-30 04:07:15 +00:00
2014-07-22 12:08:52 +00:00
/* handle mixed syntax declaration or nested namespaces */
if ( ! CG ( has_bracketed_namespaces ) ) {
2014-07-28 20:38:26 +00:00
if ( CG ( current_namespace ) ) {
2014-07-22 12:08:52 +00:00
/* previous namespace declarations were unbracketed */
if ( with_bracket ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot mix bracketed namespace declarations "
" with unbracketed namespace declarations " ) ;
}
}
} else {
/* previous namespace declarations were bracketed */
if ( ! with_bracket ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot mix bracketed namespace declarations "
" with unbracketed namespace declarations " ) ;
2014-07-28 20:38:26 +00:00
} else if ( CG ( current_namespace ) | | CG ( in_namespace ) ) {
2014-07-22 12:08:52 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Namespace declarations cannot be nested " ) ;
2005-09-09 06:48:49 +00:00
}
}
2014-07-28 20:38:26 +00:00
if ( ( ( ! with_bracket & & ! CG ( current_namespace ) )
2014-07-22 12:08:52 +00:00
| | ( with_bracket & & ! CG ( has_bracketed_namespaces ) ) ) & & CG ( active_op_array ) - > last > 0
) {
/* ignore ZEND_EXT_STMT and ZEND_TICKS */
2014-08-25 19:21:16 +00:00
uint32_t num = CG ( active_op_array ) - > last ;
2014-07-22 12:08:52 +00:00
while ( num > 0 & &
( CG ( active_op_array ) - > opcodes [ num - 1 ] . opcode = = ZEND_EXT_STMT | |
CG ( active_op_array ) - > opcodes [ num - 1 ] . opcode = = ZEND_TICKS ) ) {
- - num ;
}
if ( num > 0 ) {
2014-07-28 20:03:16 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Namespace declaration statement has to be "
" the very first statement in the script " ) ;
2014-07-22 12:08:52 +00:00
}
2006-12-12 23:25:23 +00:00
}
2014-07-28 20:38:26 +00:00
if ( CG ( current_namespace ) ) {
2014-08-25 19:21:16 +00:00
zend_string_release ( CG ( current_namespace ) ) ;
2014-07-22 10:45:44 +00:00
}
2002-07-30 04:07:15 +00:00
2014-07-22 10:45:44 +00:00
if ( name_ast ) {
2014-07-28 13:16:35 +00:00
name = zend_ast_get_str ( name_ast ) ;
2001-08-08 15:07:11 +00:00
2014-07-28 13:39:43 +00:00
if ( ZEND_FETCH_CLASS_DEFAULT ! = zend_get_class_fetch_type ( name ) ) {
2014-07-22 10:45:44 +00:00
zend_error_noreturn ( E_COMPILE_ERROR , " Cannot use '%s' as namespace name " , name - > val ) ;
2001-08-08 15:07:11 +00:00
}
2014-07-22 10:45:44 +00:00
2014-08-25 19:21:16 +00:00
CG ( current_namespace ) = zend_string_copy ( name ) ;
2001-08-08 15:07:11 +00:00
} else {
2014-07-28 20:38:26 +00:00
CG ( current_namespace ) = NULL ;
2001-08-08 15:07:11 +00:00
}
2014-07-22 10:45:44 +00:00
zend_reset_import_tables ( TSRMLS_C ) ;
2005-02-11 22:26:45 +00:00
2014-07-22 10:45:44 +00:00
CG ( in_namespace ) = 1 ;
2014-07-22 12:08:52 +00:00
if ( with_bracket ) {
CG ( has_bracketed_namespaces ) = 1 ;
}
1999-04-07 18:10:10 +00:00
2014-07-22 10:45:44 +00:00
if ( stmt_ast ) {
2014-07-22 11:02:51 +00:00
zend_compile_top_stmt ( stmt_ast TSRMLS_CC ) ;
2014-07-28 13:29:56 +00:00
zend_end_namespace ( TSRMLS_C ) ;
2014-07-22 10:45:44 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_halt_compiler ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-22 12:22:59 +00:00
zend_ast * offset_ast = ast - > child [ 0 ] ;
2014-08-25 19:21:16 +00:00
zend_long offset = Z_LVAL_P ( zend_ast_get_zval ( offset_ast ) ) ;
2006-05-09 23:53:23 +00:00
2014-07-22 12:22:59 +00:00
zend_string * filename , * name ;
const char const_name [ ] = " __COMPILER_HALT_OFFSET__ " ;
2005-02-07 15:22:38 +00:00
2014-07-22 12:22:59 +00:00
if ( CG ( has_bracketed_namespaces ) & & CG ( in_namespace ) ) {
2014-07-28 20:03:16 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
" __HALT_COMPILER() can only be used from the outermost scope " ) ;
2014-07-22 12:22:59 +00:00
}
2005-02-07 16:09:54 +00:00
2014-07-22 12:22:59 +00:00
filename = zend_get_compiled_filename ( TSRMLS_C ) ;
name = zend_mangle_property_name ( const_name , sizeof ( const_name ) - 1 ,
filename - > val , filename - > len , 0 ) ;
zend_register_long_constant ( name - > val , name - > len , offset , CONST_CS , 0 TSRMLS_CC ) ;
2014-08-25 19:21:16 +00:00
zend_string_release ( name ) ;
2014-07-22 12:22:59 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-22 12:22:59 +00:00
2014-08-29 05:05:58 +00:00
static zend_bool zend_try_ct_eval_magic_const ( zval * zv , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-29 21:22:23 +00:00
zend_op_array * op_array = CG ( active_op_array ) ;
zend_class_entry * ce = CG ( active_class_entry ) ;
switch ( ast - > attr ) {
2014-08-26 20:47:11 +00:00
case T_LINE :
ZVAL_LONG ( zv , CG ( zend_lineno ) ) ;
break ;
case T_FILE :
ZVAL_STR ( zv , zend_string_copy ( CG ( compiled_filename ) ) ) ;
break ;
case T_DIR :
{
zend_string * filename = CG ( compiled_filename ) ;
zend_string * dirname = zend_string_init ( filename - > val , filename - > len , 0 ) ;
zend_dirname ( dirname - > val , dirname - > len ) ;
if ( strcmp ( dirname - > val , " . " ) = = 0 ) {
dirname = zend_string_realloc ( dirname , MAXPATHLEN , 0 ) ;
# if HAVE_GETCWD
VCWD_GETCWD ( dirname - > val , MAXPATHLEN ) ;
# elif HAVE_GETWD
VCWD_GETWD ( dirname - > val ) ;
# endif
}
dirname - > len = strlen ( dirname - > val ) ;
ZVAL_STR ( zv , dirname ) ;
break ;
}
2014-07-29 21:22:23 +00:00
case T_FUNC_C :
if ( op_array & & op_array - > function_name ) {
2014-08-25 19:21:16 +00:00
ZVAL_STR ( zv , zend_string_copy ( op_array - > function_name ) ) ;
2014-07-29 21:22:23 +00:00
} else {
ZVAL_EMPTY_STRING ( zv ) ;
}
break ;
case T_METHOD_C :
if ( ce ) {
if ( op_array & & op_array - > function_name ) {
ZVAL_STR ( zv , zend_concat3 ( ce - > name - > val , ce - > name - > len , " :: " , 2 ,
op_array - > function_name - > val , op_array - > function_name - > len ) ) ;
} else {
2014-08-25 19:21:16 +00:00
ZVAL_STR ( zv , zend_string_copy ( ce - > name ) ) ;
2014-07-29 21:22:23 +00:00
}
} else if ( op_array & & op_array - > function_name ) {
2014-08-25 19:21:16 +00:00
ZVAL_STR ( zv , zend_string_copy ( op_array - > function_name ) ) ;
2014-07-29 21:22:23 +00:00
} else {
ZVAL_EMPTY_STRING ( zv ) ;
}
break ;
case T_CLASS_C :
if ( ce ) {
if ( ZEND_CE_IS_TRAIT ( ce ) ) {
return 0 ;
} else {
2014-08-25 19:21:16 +00:00
ZVAL_STR ( zv , zend_string_copy ( ce - > name ) ) ;
2014-07-29 21:22:23 +00:00
}
} else {
ZVAL_EMPTY_STRING ( zv ) ;
}
break ;
case T_TRAIT_C :
if ( ce & & ZEND_CE_IS_TRAIT ( ce ) ) {
2014-08-25 19:21:16 +00:00
ZVAL_STR ( zv , zend_string_copy ( ce - > name ) ) ;
2014-07-29 21:22:23 +00:00
} else {
ZVAL_EMPTY_STRING ( zv ) ;
}
break ;
case T_NS_C :
if ( CG ( current_namespace ) ) {
2014-08-25 19:21:16 +00:00
ZVAL_STR ( zv , zend_string_copy ( CG ( current_namespace ) ) ) ;
2014-07-29 21:22:23 +00:00
} else {
ZVAL_EMPTY_STRING ( zv ) ;
}
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
2014-03-13 13:01:28 +00:00
}
2014-07-29 21:22:23 +00:00
return 1 ;
2005-02-07 15:22:38 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2005-02-07 15:22:38 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_ct_eval_binary_op ( zval * result , uint32_t opcode , zval * op1 , zval * op2 TSRMLS_DC ) /* { { { */
{
2014-07-29 21:22:23 +00:00
binary_op_type fn = get_binary_op ( opcode ) ;
fn ( result , op1 , op2 TSRMLS_CC ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_ct_eval_unary_pm ( zval * result , zend_ast_kind kind , zval * op TSRMLS_DC ) /* { { { */
{
2014-07-29 21:22:23 +00:00
binary_op_type fn = kind = = ZEND_AST_UNARY_PLUS
? add_function : sub_function ;
1999-04-07 18:10:10 +00:00
2014-07-29 21:22:23 +00:00
zval left ;
ZVAL_LONG ( & left , 0 ) ;
fn ( result , & left , op TSRMLS_CC ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2004-08-12 05:41:01 +00:00
2014-08-29 05:05:58 +00:00
static inline void zend_ct_eval_greater ( zval * result , zend_ast_kind kind , zval * op1 , zval * op2 TSRMLS_DC ) /* { { { */
{
2014-07-29 21:22:23 +00:00
binary_op_type fn = kind = = ZEND_AST_GREATER
? is_smaller_function : is_smaller_or_equal_function ;
fn ( result , op2 , op1 TSRMLS_CC ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static zend_bool zend_try_ct_eval_array ( zval * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-29 21:22:23 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2005-02-07 16:09:54 +00:00
2014-07-29 21:22:23 +00:00
/* First ensure that *all* child nodes are constant and by-val */
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * elem_ast = list - > child [ i ] ;
zend_bool by_ref = elem_ast - > attr ;
2014-07-30 11:43:04 +00:00
zend_eval_const_expr ( & elem_ast - > child [ 0 ] TSRMLS_CC ) ;
zend_eval_const_expr ( & elem_ast - > child [ 1 ] TSRMLS_CC ) ;
2012-07-22 12:33:25 +00:00
2014-07-30 11:43:04 +00:00
if ( by_ref | | elem_ast - > child [ 0 ] - > kind ! = ZEND_AST_ZVAL
| | ( elem_ast - > child [ 1 ] & & elem_ast - > child [ 1 ] - > kind ! = ZEND_AST_ZVAL )
2014-07-29 21:22:23 +00:00
) {
return 0 ;
2007-01-10 15:58:08 +00:00
}
1999-04-07 18:10:10 +00:00
}
2014-07-29 21:22:23 +00:00
array_init_size ( result , list - > children ) ;
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * elem_ast = list - > child [ i ] ;
zend_ast * value_ast = elem_ast - > child [ 0 ] ;
zend_ast * key_ast = elem_ast - > child [ 1 ] ;
2006-05-11 21:07:39 +00:00
2014-07-29 21:22:23 +00:00
zval * value = zend_ast_get_zval ( value_ast ) ;
if ( Z_REFCOUNTED_P ( value ) ) Z_ADDREF_P ( value ) ;
if ( key_ast ) {
zval * key = zend_ast_get_zval ( key_ast ) ;
switch ( Z_TYPE_P ( key ) ) {
case IS_LONG :
zend_hash_index_update ( Z_ARRVAL_P ( result ) , Z_LVAL_P ( key ) , value ) ;
break ;
case IS_STRING :
zend_symtable_update ( Z_ARRVAL_P ( result ) , Z_STR_P ( key ) , value ) ;
break ;
case IS_DOUBLE :
zend_hash_index_update ( Z_ARRVAL_P ( result ) ,
zend_dval_to_lval ( Z_DVAL_P ( key ) ) , value ) ;
break ;
case IS_FALSE :
zend_hash_index_update ( Z_ARRVAL_P ( result ) , 0 , value ) ;
break ;
case IS_TRUE :
zend_hash_index_update ( Z_ARRVAL_P ( result ) , 1 , value ) ;
break ;
case IS_NULL :
zend_hash_update ( Z_ARRVAL_P ( result ) , STR_EMPTY_ALLOC ( ) , value ) ;
break ;
default :
zend_error ( E_COMPILE_ERROR , " Illegal offset type " ) ;
break ;
}
2012-08-25 14:23:14 +00:00
} else {
2014-07-29 21:22:23 +00:00
zend_hash_next_index_insert ( Z_ARRVAL_P ( result ) , value ) ;
2012-08-25 14:23:14 +00:00
}
2003-07-24 12:38:33 +00:00
}
2005-02-07 16:09:54 +00:00
2014-07-29 21:22:23 +00:00
return 1 ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-29 21:22:23 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_binary_op ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * left_ast = ast - > child [ 0 ] ;
zend_ast * right_ast = ast - > child [ 1 ] ;
2014-08-25 19:21:16 +00:00
uint32_t opcode = ast - > attr ;
2005-02-20 10:19:11 +00:00
2014-06-14 16:30:18 +00:00
znode left_node , right_node ;
2014-06-23 19:30:57 +00:00
zend_compile_expr ( & left_node , left_ast TSRMLS_CC ) ;
zend_compile_expr ( & right_node , right_ast TSRMLS_CC ) ;
2005-02-07 16:09:54 +00:00
2014-07-29 21:22:23 +00:00
if ( left_node . op_type = = IS_CONST & & right_node . op_type = = IS_CONST ) {
result - > op_type = IS_CONST ;
zend_ct_eval_binary_op ( & result - > u . constant , opcode ,
& left_node . u . constant , & right_node . u . constant TSRMLS_CC ) ;
zval_ptr_dtor ( & left_node . u . constant ) ;
zval_ptr_dtor ( & right_node . u . constant ) ;
return ;
1999-04-07 18:10:10 +00:00
}
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , opcode , & left_node , & right_node TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
* evaluation order . */
2014-08-29 05:05:58 +00:00
void zend_compile_greater ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * left_ast = ast - > child [ 0 ] ;
zend_ast * right_ast = ast - > child [ 1 ] ;
znode left_node , right_node ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
ZEND_ASSERT ( ast - > kind = = ZEND_AST_GREATER | | ast - > kind = = ZEND_AST_GREATER_EQUAL ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & left_node , left_ast TSRMLS_CC ) ;
zend_compile_expr ( & right_node , right_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-29 21:22:23 +00:00
if ( left_node . op_type = = IS_CONST & & right_node . op_type = = IS_CONST ) {
result - > op_type = IS_CONST ;
zend_ct_eval_greater ( & result - > u . constant , ast - > kind ,
& left_node . u . constant , & right_node . u . constant TSRMLS_CC ) ;
zval_ptr_dtor ( & left_node . u . constant ) ;
zval_ptr_dtor ( & right_node . u . constant ) ;
return ;
}
1999-04-07 18:10:10 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result ,
ast - > kind = = ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL ,
2014-06-14 16:30:18 +00:00
& right_node , & left_node TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_unary_op ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
2014-08-25 19:21:16 +00:00
uint32_t opcode = ast - > attr ;
2000-01-24 19:00:30 +00:00
2014-06-14 16:30:18 +00:00
znode expr_node ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2008-07-24 22:21:41 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , opcode , & expr_node , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2008-06-29 08:21:35 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_unary_pm ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
znode zero_node , expr_node ;
2010-11-24 05:41:23 +00:00
2014-06-26 10:43:20 +00:00
ZEND_ASSERT ( ast - > kind = = ZEND_AST_UNARY_PLUS | | ast - > kind = = ZEND_AST_UNARY_MINUS ) ;
2010-11-24 05:41:23 +00:00
2014-07-29 21:22:23 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2000-01-24 19:00:30 +00:00
2014-07-29 21:22:23 +00:00
if ( expr_node . op_type = = IS_CONST ) {
result - > op_type = IS_CONST ;
zend_ct_eval_unary_pm ( & result - > u . constant , ast - > kind , & expr_node . u . constant TSRMLS_CC ) ;
zval_ptr_dtor ( & expr_node . u . constant ) ;
return ;
2002-07-30 22:19:50 +00:00
}
2000-01-24 19:00:30 +00:00
2014-06-14 16:30:18 +00:00
zero_node . op_type = IS_CONST ;
ZVAL_LONG ( & zero_node . u . constant , 0 ) ;
1999-04-07 18:10:10 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , ast - > kind = = ZEND_AST_UNARY_PLUS ? ZEND_ADD : ZEND_SUB ,
2014-06-14 16:30:18 +00:00
& zero_node , & expr_node TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_short_circuiting ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * left_ast = ast - > child [ 0 ] ;
zend_ast * right_ast = ast - > child [ 1 ] ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
znode left_node , right_node ;
zend_op * opline_jmpz , * opline_bool ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_jmpz ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
ZEND_ASSERT ( ast - > kind = = ZEND_AST_AND | | ast - > kind = = ZEND_AST_OR ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & left_node , left_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
opnum_jmpz = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
opline_jmpz = zend_emit_op ( NULL , ast - > kind = = ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX ,
2014-06-14 16:30:18 +00:00
& left_node , NULL TSRMLS_CC ) ;
2007-11-21 09:41:35 +00:00
2014-06-14 16:30:18 +00:00
if ( left_node . op_type = = IS_TMP_VAR ) {
SET_NODE ( opline_jmpz - > result , & left_node ) ;
2011-10-18 19:42:42 +00:00
} else {
2014-06-14 16:30:18 +00:00
opline_jmpz - > result . var = get_temporary_variable ( CG ( active_op_array ) ) ;
opline_jmpz - > result_type = IS_TMP_VAR ;
2011-10-18 19:42:42 +00:00
}
2014-06-14 16:30:18 +00:00
GET_NODE ( result , opline_jmpz - > result ) ;
2013-01-28 02:02:51 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & right_node , right_ast TSRMLS_CC ) ;
2007-11-21 09:41:35 +00:00
2014-07-28 20:03:16 +00:00
opline_bool = zend_emit_op ( NULL , ZEND_BOOL , & right_node , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
SET_NODE ( opline_bool - > result , result ) ;
2007-11-21 09:41:35 +00:00
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_jmpz TSRMLS_CC ) ;
2007-11-21 09:41:35 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2007-11-21 09:41:35 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_post_incdec ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
2014-07-27 20:26:06 +00:00
ZEND_ASSERT ( ast - > kind = = ZEND_AST_POST_INC | | ast - > kind = = ZEND_AST_POST_DEC ) ;
2007-11-21 09:41:35 +00:00
2014-06-14 16:30:18 +00:00
if ( var_ast - > kind = = ZEND_AST_PROP ) {
2014-07-29 19:00:19 +00:00
zend_op * opline = zend_compile_prop_common ( NULL , var_ast , BP_VAR_RW TSRMLS_CC ) ;
2014-07-27 20:26:06 +00:00
opline - > opcode = ast - > kind = = ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ ;
2014-08-15 15:10:06 +00:00
zend_make_tmp_result ( result , opline TSRMLS_CC ) ;
2011-10-18 19:42:42 +00:00
} else {
2014-07-29 19:00:19 +00:00
znode var_node ;
2014-06-14 16:30:18 +00:00
zend_compile_var ( & var_node , var_ast , BP_VAR_RW TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , ast - > kind = = ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC ,
2014-07-27 20:26:06 +00:00
& var_node , NULL TSRMLS_CC ) ;
2011-10-18 19:42:42 +00:00
}
2014-06-14 16:30:18 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2007-11-21 09:41:35 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_pre_incdec ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
2014-07-27 20:26:06 +00:00
ZEND_ASSERT ( ast - > kind = = ZEND_AST_PRE_INC | | ast - > kind = = ZEND_AST_PRE_DEC ) ;
2013-01-28 02:02:51 +00:00
2014-06-14 16:30:18 +00:00
if ( var_ast - > kind = = ZEND_AST_PROP ) {
2014-07-29 19:00:19 +00:00
zend_op * opline = zend_compile_prop_common ( result , var_ast , BP_VAR_RW TSRMLS_CC ) ;
2014-07-27 20:26:06 +00:00
opline - > opcode = ast - > kind = = ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ ;
2014-06-14 16:30:18 +00:00
} else {
2014-07-29 19:00:19 +00:00
znode var_node ;
2014-06-14 16:30:18 +00:00
zend_compile_var ( & var_node , var_ast , BP_VAR_RW TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( result , ast - > kind = = ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC ,
2014-07-27 20:26:06 +00:00
& var_node , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
}
2007-11-21 09:41:35 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2007-11-21 09:41:35 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_cast ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
znode expr_node ;
1999-04-07 18:10:10 +00:00
zend_op * opline ;
2006-05-09 23:53:23 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_CAST , & expr_node , NULL TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
opline - > extended_value = ast - > attr ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
static void zend_compile_shorthand_conditional ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * cond_ast = ast - > child [ 0 ] ;
zend_ast * false_ast = ast - > child [ 2 ] ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
znode cond_node , false_node ;
zend_op * opline_jmp_set , * opline_qm_assign ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_jmp_set ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
ZEND_ASSERT ( ast - > child [ 1 ] = = NULL ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & cond_node , cond_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
opnum_jmp_set = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , ZEND_JMP_SET , & cond_node , NULL TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & false_node , false_ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
opline_jmp_set = & CG ( active_op_array ) - > opcodes [ opnum_jmp_set ] ;
opline_jmp_set - > op2 . opline_num = get_next_op_number ( CG ( active_op_array ) ) + 1 ;
if ( cond_node . op_type = = IS_VAR | | cond_node . op_type = = IS_CV
| | false_node . op_type = = IS_VAR | | false_node . op_type = = IS_CV
) {
opline_jmp_set - > opcode = ZEND_JMP_SET_VAR ;
opline_jmp_set - > result_type = IS_VAR ;
GET_NODE ( result , opline_jmp_set - > result ) ;
2014-07-28 20:03:16 +00:00
opline_qm_assign = zend_emit_op ( NULL , ZEND_QM_ASSIGN_VAR , & false_node , NULL TSRMLS_CC ) ;
2011-10-18 19:42:42 +00:00
} else {
2014-07-28 20:03:16 +00:00
opline_qm_assign = zend_emit_op ( NULL , ZEND_QM_ASSIGN , & false_node , NULL TSRMLS_CC ) ;
2011-10-18 19:42:42 +00:00
}
2014-06-14 16:30:18 +00:00
SET_NODE ( opline_qm_assign - > result , result ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_conditional ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * cond_ast = ast - > child [ 0 ] ;
zend_ast * true_ast = ast - > child [ 1 ] ;
zend_ast * false_ast = ast - > child [ 2 ] ;
2006-05-09 23:53:23 +00:00
2014-06-14 16:30:18 +00:00
znode cond_node , true_node , false_node ;
2014-07-18 14:11:43 +00:00
zend_op * opline_qm_assign1 , * opline_qm_assign2 ;
2014-08-25 19:21:16 +00:00
uint32_t opnum_jmpz , opnum_jmp , opnum_qm_assign1 ;
2014-06-14 16:30:18 +00:00
if ( ! true_ast ) {
zend_compile_shorthand_conditional ( result , ast TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
return ;
}
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & cond_node , cond_ast TSRMLS_CC ) ;
2006-05-09 23:53:23 +00:00
2014-07-18 17:57:38 +00:00
opnum_jmpz = zend_emit_cond_jump ( ZEND_JMPZ , & cond_node , 0 TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & true_node , true_ast TSRMLS_CC ) ;
2006-05-09 23:53:23 +00:00
2014-06-14 16:30:18 +00:00
opnum_qm_assign1 = get_next_op_number ( CG ( active_op_array ) ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( result , ZEND_QM_ASSIGN , & true_node , NULL TSRMLS_CC ) ;
2006-05-09 23:53:23 +00:00
2014-07-18 17:57:38 +00:00
opnum_jmp = zend_emit_jump ( 0 TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_jmpz TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & false_node , false_ast TSRMLS_CC ) ;
2006-05-09 23:53:23 +00:00
2014-06-14 16:30:18 +00:00
opline_qm_assign1 = & CG ( active_op_array ) - > opcodes [ opnum_qm_assign1 ] ;
if ( true_node . op_type = = IS_VAR | | true_node . op_type = = IS_CV
| | false_node . op_type = = IS_VAR | | false_node . op_type = = IS_CV
) {
opline_qm_assign1 - > opcode = ZEND_QM_ASSIGN_VAR ;
opline_qm_assign1 - > result_type = IS_VAR ;
GET_NODE ( result , opline_qm_assign1 - > result ) ;
1999-04-07 18:10:10 +00:00
}
2006-05-09 23:53:23 +00:00
2014-07-28 20:03:16 +00:00
opline_qm_assign2 = zend_emit_op ( NULL , opline_qm_assign1 - > opcode , & false_node , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
SET_NODE ( opline_qm_assign2 - > result , result ) ;
1999-04-07 18:10:10 +00:00
2014-07-18 14:11:43 +00:00
zend_update_jump_target_to_next ( opnum_jmp TSRMLS_CC ) ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
1999-04-07 18:10:10 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_print ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
2000-01-24 19:00:30 +00:00
2014-06-14 16:30:18 +00:00
znode expr_node ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , ZEND_PRINT , & expr_node , NULL TSRMLS_CC ) ;
2000-01-24 19:00:30 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2000-01-24 19:00:30 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_exit ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
2003-03-02 13:33:31 +00:00
2014-06-14 16:30:18 +00:00
if ( expr_ast ) {
znode expr_node ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_EXIT , & expr_node , NULL TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
} else {
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_EXIT , NULL , NULL TSRMLS_CC ) ;
2003-03-02 13:33:31 +00:00
}
2014-06-14 16:30:18 +00:00
result - > op_type = IS_CONST ;
ZVAL_BOOL ( & result - > u . constant , 1 ) ;
2003-03-02 13:33:31 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-03-02 13:33:31 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_yield ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * value_ast = ast - > child [ 0 ] ;
zend_ast * key_ast = ast - > child [ 1 ] ;
2003-03-02 10:04:53 +00:00
2014-06-14 16:30:18 +00:00
znode value_node , key_node ;
znode * value_node_ptr = NULL , * key_node_ptr = NULL ;
zend_op * opline ;
zend_bool returns_by_ref = ( CG ( active_op_array ) - > fn_flags & ZEND_ACC_RETURN_REFERENCE ) ! = 0 ;
2003-03-02 10:04:53 +00:00
2014-06-14 16:30:18 +00:00
if ( ! CG ( active_op_array ) - > function_name ) {
2014-07-28 20:03:16 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
" The \" yield \" expression can only be used inside a function " ) ;
2014-06-14 16:30:18 +00:00
}
2014-04-10 11:50:25 +00:00
2014-06-14 16:30:18 +00:00
CG ( active_op_array ) - > fn_flags | = ZEND_ACC_GENERATOR ;
2001-08-08 17:18:16 +00:00
2014-06-14 16:30:18 +00:00
if ( key_ast ) {
zend_compile_expr ( & key_node , key_ast TSRMLS_CC ) ;
key_node_ptr = & key_node ;
}
2014-06-16 17:11:52 +00:00
2014-06-14 16:30:18 +00:00
if ( value_ast ) {
if ( returns_by_ref & & zend_is_variable ( value_ast ) & & ! zend_is_call ( value_ast ) ) {
zend_compile_var ( & value_node , value_ast , BP_VAR_REF TSRMLS_CC ) ;
2014-06-16 17:11:52 +00:00
} else {
2014-06-14 16:30:18 +00:00
zend_compile_expr ( & value_node , value_ast TSRMLS_CC ) ;
2014-06-16 17:11:52 +00:00
}
2014-06-14 16:30:18 +00:00
value_node_ptr = & value_node ;
}
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_YIELD , value_node_ptr , key_node_ptr TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
if ( value_ast & & returns_by_ref & & zend_is_call ( value_ast ) ) {
opline - > extended_value = ZEND_RETURNS_FUNCTION ;
}
2010-07-08 14:05:11 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2010-07-08 14:05:11 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_instanceof ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-14 16:30:18 +00:00
zend_ast * obj_ast = ast - > child [ 0 ] ;
zend_ast * class_ast = ast - > child [ 1 ] ;
1999-04-07 18:10:10 +00:00
2014-06-14 16:30:18 +00:00
znode obj_node , class_node ;
zend_op * opline ;
zend_compile_expr ( & obj_node , obj_ast TSRMLS_CC ) ;
if ( obj_node . op_type = = IS_CONST ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" instanceof expects an object instance, constant given " ) ;
2001-08-06 14:36:46 +00:00
}
2014-06-14 16:30:18 +00:00
opline = zend_compile_class_ref ( & class_node , class_ast TSRMLS_CC ) ;
opline - > extended_value | = ZEND_FETCH_CLASS_NO_AUTOLOAD ;
2003-05-29 09:01:55 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , ZEND_INSTANCEOF , & obj_node , & class_node TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-14 16:30:18 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_include_or_eval ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
znode expr_node ;
zend_op * opline ;
zend_do_extended_fcall_begin ( TSRMLS_C ) ;
zend_compile_expr ( & expr_node , expr_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_INCLUDE_OR_EVAL , & expr_node , NULL TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
opline - > extended_value = ast - > attr ;
zend_do_extended_fcall_end ( TSRMLS_C ) ;
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-19 11:57:29 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_isset_or_empty ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_ast * var_ast = ast - > child [ 0 ] ;
znode var_node ;
zend_op * opline ;
ZEND_ASSERT ( ast - > kind = = ZEND_AST_ISSET | | ast - > kind = = ZEND_AST_EMPTY ) ;
if ( ! zend_is_variable ( var_ast ) | | zend_is_call ( var_ast ) ) {
if ( ast - > kind = = ZEND_AST_EMPTY ) {
/* empty(expr) can be transformed to !expr */
2014-07-28 16:18:47 +00:00
zend_ast * not_ast = zend_ast_create_ex ( ZEND_AST_UNARY_OP , ZEND_BOOL_NOT , var_ast ) ;
2014-06-19 11:57:29 +00:00
zend_compile_expr ( result , not_ast TSRMLS_CC ) ;
return ;
} else {
zend_error_noreturn ( E_COMPILE_ERROR ,
" Cannot use isset() on the result of an expression "
" (you can use \" null !== expression \" instead) " ) ;
}
}
switch ( var_ast - > kind ) {
case ZEND_AST_VAR :
if ( zend_try_compile_cv ( & var_node , var_ast TSRMLS_CC ) = = SUCCESS ) {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( result , ZEND_ISSET_ISEMPTY_VAR , & var_node , NULL TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
opline - > extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET ;
} else {
opline = zend_compile_simple_var_no_cv ( result , var_ast , BP_VAR_IS TSRMLS_CC ) ;
opline - > opcode = ZEND_ISSET_ISEMPTY_VAR ;
2008-11-25 09:56:32 +00:00
}
1999-04-07 18:10:10 +00:00
break ;
2014-06-19 11:57:29 +00:00
case ZEND_AST_DIM :
opline = zend_compile_dim_common ( result , var_ast , BP_VAR_IS TSRMLS_CC ) ;
opline - > opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ ;
break ;
case ZEND_AST_PROP :
opline = zend_compile_prop_common ( result , var_ast , BP_VAR_IS TSRMLS_CC ) ;
opline - > opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ ;
1999-04-07 18:10:10 +00:00
break ;
2014-06-19 11:57:29 +00:00
case ZEND_AST_STATIC_PROP :
opline = zend_compile_static_prop_common ( result , var_ast , BP_VAR_IS TSRMLS_CC ) ;
opline - > opcode = ZEND_ISSET_ISEMPTY_VAR ;
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
1999-04-07 18:10:10 +00:00
}
2006-05-09 23:53:23 +00:00
2014-08-26 10:22:03 +00:00
result - > op_type = opline - > result_type = IS_TMP_VAR ;
2014-06-19 11:57:29 +00:00
opline - > extended_value | = ast - > kind = = ZEND_AST_ISSET ? ZEND_ISSET : ZEND_ISEMPTY ;
1999-04-07 18:10:10 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-03-31 20:42:01 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_silence ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
znode silence_node ;
2003-02-10 16:11:24 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( & silence_node , ZEND_BEGIN_SILENCE , NULL , NULL TSRMLS_CC ) ;
2005-12-01 11:48:17 +00:00
2014-06-19 11:57:29 +00:00
if ( expr_ast - > kind = = ZEND_AST_VAR ) {
/* For @$var we need to force a FETCH instruction, otherwise the CV access will
* happen outside the silenced section . */
zend_compile_simple_var_no_cv ( result , expr_ast , BP_VAR_R TSRMLS_CC ) ;
2005-12-01 11:48:17 +00:00
} else {
2014-06-19 11:57:29 +00:00
zend_compile_expr ( result , expr_ast TSRMLS_CC ) ;
2005-12-01 11:48:17 +00:00
}
2005-09-01 10:05:32 +00:00
2014-07-28 20:03:16 +00:00
zend_emit_op ( NULL , ZEND_END_SILENCE , & silence_node , NULL TSRMLS_CC ) ;
2003-02-10 16:11:24 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2003-02-10 16:11:24 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_shell_exec ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_ast * expr_ast = ast - > child [ 0 ] ;
2003-08-03 08:21:08 +00:00
2014-06-19 11:57:29 +00:00
zval fn_name ;
2014-07-13 11:11:55 +00:00
zend_ast * name_ast , * args_ast , * call_ast ;
2014-06-19 11:57:29 +00:00
ZVAL_STRING ( & fn_name , " shell_exec " ) ;
name_ast = zend_ast_create_zval ( & fn_name ) ;
2014-08-29 18:52:26 +00:00
args_ast = zend_ast_create_list ( 1 , ZEND_AST_ARG_LIST , expr_ast ) ;
2014-07-28 16:18:47 +00:00
call_ast = zend_ast_create ( ZEND_AST_CALL , name_ast , args_ast ) ;
2014-06-19 11:57:29 +00:00
zend_compile_expr ( result , call_ast TSRMLS_CC ) ;
2014-07-25 18:24:15 +00:00
zval_ptr_dtor ( & fn_name ) ;
2005-01-22 02:29:18 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2005-01-22 02:29:18 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_array ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-06-19 11:57:29 +00:00
zend_op * opline ;
2014-08-25 19:21:16 +00:00
uint32_t i , opnum_init ;
2014-06-19 11:57:29 +00:00
zend_bool packed = 1 ;
2014-07-29 21:22:23 +00:00
if ( zend_try_ct_eval_array ( & result - > u . constant , ast TSRMLS_CC ) ) {
2007-09-28 19:52:53 +00:00
result - > op_type = IS_CONST ;
2014-07-29 21:22:23 +00:00
return ;
2007-09-28 19:52:53 +00:00
}
2014-06-19 11:57:29 +00:00
opnum_init = get_next_op_number ( CG ( active_op_array ) ) ;
2007-09-28 19:52:53 +00:00
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * elem_ast = list - > child [ i ] ;
2014-06-19 11:57:29 +00:00
zend_ast * value_ast = elem_ast - > child [ 0 ] ;
zend_ast * key_ast = elem_ast - > child [ 1 ] ;
zend_bool by_ref = elem_ast - > attr ;
2008-11-25 09:56:32 +00:00
2014-06-19 11:57:29 +00:00
znode value_node , key_node , * key_node_ptr = NULL ;
2008-11-25 09:56:32 +00:00
2014-06-19 11:57:29 +00:00
if ( key_ast ) {
zend_compile_expr ( & key_node , key_ast TSRMLS_CC ) ;
2014-08-15 15:10:06 +00:00
zend_handle_numeric_op ( & key_node TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
key_node_ptr = & key_node ;
}
2007-09-28 19:52:53 +00:00
2014-06-19 11:57:29 +00:00
if ( by_ref ) {
zend_ensure_writable_variable ( value_ast ) ;
zend_compile_var ( & value_node , value_ast , BP_VAR_W TSRMLS_CC ) ;
} else {
zend_compile_expr ( & value_node , value_ast TSRMLS_CC ) ;
2008-11-25 09:56:32 +00:00
}
2014-06-19 11:57:29 +00:00
if ( i = = 0 ) {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op_tmp ( result , ZEND_INIT_ARRAY , & value_node , key_node_ptr TSRMLS_CC ) ;
2014-07-27 20:26:06 +00:00
opline - > extended_value = list - > children < < ZEND_ARRAY_SIZE_SHIFT ;
2014-06-19 11:57:29 +00:00
} else {
2014-07-28 20:03:16 +00:00
opline = zend_emit_op ( NULL , ZEND_ADD_ARRAY_ELEMENT ,
& value_node , key_node_ptr TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
SET_NODE ( opline - > result , result ) ;
2008-11-25 09:56:32 +00:00
}
2014-06-19 11:57:29 +00:00
opline - > extended_value | = by_ref ;
2014-08-15 15:10:06 +00:00
if ( key_ast & & key_node . op_type = = IS_CONST & & Z_TYPE ( key_node . u . constant ) = = IS_STRING ) {
packed = 0 ;
2008-11-25 09:56:32 +00:00
}
2007-12-13 08:57:52 +00:00
}
2008-11-25 09:56:32 +00:00
2014-06-19 11:57:29 +00:00
/* Handle empty array */
2014-07-27 20:26:06 +00:00
if ( ! list - > children ) {
2014-07-28 20:03:16 +00:00
zend_emit_op_tmp ( result , ZEND_INIT_ARRAY , NULL , NULL TSRMLS_CC ) ;
2007-12-13 08:57:52 +00:00
}
2013-01-28 02:02:51 +00:00
2014-06-19 11:57:29 +00:00
/* Add a flag to INIT_ARRAY if we know this array cannot be packed */
if ( ! packed ) {
opline = & CG ( active_op_array ) - > opcodes [ opnum_init ] ;
opline - > extended_value | = ZEND_ARRAY_NOT_PACKED ;
2013-07-16 18:39:33 +00:00
}
2014-06-19 11:57:29 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-07-16 18:39:33 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_const ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_ast * name_ast = ast - > child [ 0 ] ;
2014-07-28 13:16:35 +00:00
zend_string * orig_name = zend_ast_get_str ( name_ast ) ;
2014-07-22 11:25:47 +00:00
zend_bool is_fully_qualified ;
2014-06-19 11:57:29 +00:00
2014-06-28 20:27:06 +00:00
zval resolved_name ;
2014-06-19 11:57:29 +00:00
zend_op * opline ;
2014-07-22 11:25:47 +00:00
ZVAL_STR ( & resolved_name , zend_resolve_const_name (
orig_name , name_ast - > attr , & is_fully_qualified TSRMLS_CC ) ) ;
2014-06-19 11:57:29 +00:00
2014-06-28 20:27:06 +00:00
if ( zend_constant_ct_subst ( result , & resolved_name , 1 TSRMLS_CC ) ) {
zval_dtor ( & resolved_name ) ;
2014-06-19 11:57:29 +00:00
return ;
2013-07-23 18:21:48 +00:00
}
2014-07-28 20:03:16 +00:00
opline = zend_emit_op_tmp ( result , ZEND_FETCH_CONSTANT , NULL , NULL TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
opline - > op2_type = IS_CONST ;
2014-06-28 20:27:06 +00:00
if ( is_fully_qualified ) {
2014-06-19 11:57:29 +00:00
opline - > op2 . constant = zend_add_const_name_literal (
2014-06-28 20:27:06 +00:00
CG ( active_op_array ) , & resolved_name , 0 TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
} else {
opline - > extended_value = IS_CONSTANT_UNQUALIFIED ;
2014-07-28 20:38:26 +00:00
if ( CG ( current_namespace ) ) {
2014-06-19 11:57:29 +00:00
opline - > extended_value | = IS_CONSTANT_IN_NAMESPACE ;
opline - > op2 . constant = zend_add_const_name_literal (
2014-06-28 20:27:06 +00:00
CG ( active_op_array ) , & resolved_name , 1 TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
} else {
opline - > op2 . constant = zend_add_const_name_literal (
2014-06-28 20:27:06 +00:00
CG ( active_op_array ) , & resolved_name , 0 TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
}
2011-07-07 23:07:14 +00:00
}
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2007-09-28 19:52:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2007-09-28 19:52:53 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_class_const ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_ast * class_ast = ast - > child [ 0 ] ;
zend_ast * const_ast = ast - > child [ 1 ] ;
2007-09-28 19:52:53 +00:00
2014-06-19 11:57:29 +00:00
znode class_node , const_node ;
zend_op * opline ;
if ( zend_is_const_default_class_ref ( class_ast ) ) {
2014-07-19 21:30:07 +00:00
class_node . op_type = IS_CONST ;
ZVAL_STR ( & class_node . u . constant , zend_resolve_class_name_ast ( class_ast TSRMLS_CC ) ) ;
2014-06-19 11:57:29 +00:00
} else {
zend_compile_class_ref ( & class_node , class_ast TSRMLS_CC ) ;
2007-09-28 19:52:53 +00:00
}
2014-06-19 11:57:29 +00:00
zend_compile_expr ( & const_node , const_ast TSRMLS_CC ) ;
2014-07-28 20:03:16 +00:00
opline = zend_emit_op_tmp ( result , ZEND_FETCH_CONSTANT , NULL , & const_node TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
zend_set_class_name_op1 ( opline , & class_node TSRMLS_CC ) ;
if ( opline - > op1_type = = IS_CONST ) {
2014-08-15 15:10:06 +00:00
zend_alloc_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2007-09-28 19:52:53 +00:00
} else {
2014-08-15 15:10:06 +00:00
zend_alloc_polymorphic_cache_slot ( opline - > op2 . constant TSRMLS_CC ) ;
2007-09-28 19:52:53 +00:00
}
2014-06-19 11:57:29 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-19 11:57:29 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_resolve_class_name ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-06-19 11:57:29 +00:00
zend_ast * name_ast = ast - > child [ 0 ] ;
2014-08-25 19:21:16 +00:00
uint32_t fetch_type = zend_get_class_fetch_type ( zend_ast_get_str ( name_ast ) ) ;
2014-06-19 11:57:29 +00:00
switch ( fetch_type ) {
case ZEND_FETCH_CLASS_SELF :
if ( ! CG ( active_class_entry ) ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" Cannot access self::class when no class scope is active " ) ;
}
result - > op_type = IS_CONST ;
2014-08-25 19:21:16 +00:00
ZVAL_STR ( & result - > u . constant , zend_string_copy ( CG ( active_class_entry ) - > name ) ) ;
2014-06-19 11:57:29 +00:00
break ;
case ZEND_FETCH_CLASS_STATIC :
case ZEND_FETCH_CLASS_PARENT :
if ( ! CG ( active_class_entry ) ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" Cannot access %s::class when no class scope is active " ,
fetch_type = = ZEND_FETCH_CLASS_STATIC ? " static " : " parent " ) ;
} else {
zval class_str_zv ;
zend_ast * class_str_ast , * class_const_ast ;
ZVAL_STRING ( & class_str_zv , " class " ) ;
class_str_ast = zend_ast_create_zval ( & class_str_zv ) ;
2014-07-28 16:18:47 +00:00
class_const_ast = zend_ast_create (
2014-06-19 11:57:29 +00:00
ZEND_AST_CLASS_CONST , name_ast , class_str_ast ) ;
2007-09-28 19:52:53 +00:00
2014-06-19 11:57:29 +00:00
zend_compile_expr ( result , class_const_ast TSRMLS_CC ) ;
2007-09-28 19:52:53 +00:00
2014-07-25 18:24:15 +00:00
zval_ptr_dtor ( & class_str_zv ) ;
2014-06-19 11:57:29 +00:00
}
break ;
case ZEND_FETCH_CLASS_DEFAULT :
2014-07-19 21:30:07 +00:00
result - > op_type = IS_CONST ;
ZVAL_STR ( & result - > u . constant , zend_resolve_class_name_ast ( name_ast TSRMLS_CC ) ) ;
2014-06-19 11:57:29 +00:00
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
2007-09-28 19:52:53 +00:00
}
2014-06-19 11:57:29 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-19 11:57:29 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_encaps_list ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-06-21 18:03:29 +00:00
2014-07-27 20:26:06 +00:00
ZEND_ASSERT ( list - > children > 0 ) ;
2007-09-28 19:52:53 +00:00
2014-06-21 18:03:29 +00:00
result - > op_type = IS_TMP_VAR ;
result - > u . op . var = get_temporary_variable ( CG ( active_op_array ) ) ;
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_ast * elem_ast = list - > child [ i ] ;
2014-06-21 18:03:29 +00:00
znode elem_node ;
zend_op * opline ;
zend_compile_expr ( & elem_node , elem_ast TSRMLS_CC ) ;
2007-10-17 10:01:22 +00:00
2014-06-28 16:03:26 +00:00
if ( elem_ast - > kind = = ZEND_AST_ZVAL ) {
2014-06-21 18:03:29 +00:00
zval * zv = & elem_node . u . constant ;
ZEND_ASSERT ( Z_TYPE_P ( zv ) = = IS_STRING ) ;
2007-11-12 15:52:22 +00:00
2014-06-21 18:03:29 +00:00
if ( Z_STRLEN_P ( zv ) > 1 ) {
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_ADD_STRING ;
} else if ( Z_STRLEN_P ( zv ) = = 1 ) {
char ch = * Z_STRVAL_P ( zv ) ;
2014-08-25 19:21:16 +00:00
zend_string_release ( Z_STR_P ( zv ) ) ;
2014-06-21 18:03:29 +00:00
ZVAL_LONG ( zv , ch ) ;
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_ADD_CHAR ;
} else {
/* String can be empty after a variable at the end of a heredoc */
2014-08-25 19:21:16 +00:00
zend_string_release ( Z_STR_P ( zv ) ) ;
2014-06-21 18:03:29 +00:00
continue ;
2007-11-12 15:52:22 +00:00
}
2014-06-21 18:03:29 +00:00
} else {
opline = get_next_op ( CG ( active_op_array ) TSRMLS_CC ) ;
opline - > opcode = ZEND_ADD_VAR ;
ZEND_ASSERT ( elem_node . op_type ! = IS_CONST ) ;
2007-10-17 10:01:22 +00:00
}
2007-11-12 15:52:22 +00:00
2014-06-21 18:03:29 +00:00
if ( i = = 0 ) {
SET_UNUSED ( opline - > op1 ) ;
} else {
SET_NODE ( opline - > op1 , result ) ;
2007-11-12 15:52:22 +00:00
}
2014-06-21 18:03:29 +00:00
SET_NODE ( opline - > op2 , & elem_node ) ;
SET_NODE ( opline - > result , result ) ;
2007-09-28 19:52:53 +00:00
}
2014-06-21 18:03:29 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-21 18:03:29 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_magic_const ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-21 16:02:31 +00:00
zend_class_entry * ce = CG ( active_class_entry ) ;
2007-09-28 19:52:53 +00:00
2014-07-29 21:22:23 +00:00
if ( zend_try_ct_eval_magic_const ( & result - > u . constant , ast TSRMLS_CC ) ) {
2014-07-21 16:02:31 +00:00
result - > op_type = IS_CONST ;
return ;
2007-09-28 19:52:53 +00:00
}
2014-07-21 16:02:31 +00:00
ZEND_ASSERT ( ast - > attr = = T_CLASS_C & & ce & & ZEND_CE_IS_TRAIT ( ce ) ) ;
{
2014-07-28 16:18:47 +00:00
zend_ast * const_ast = zend_ast_create ( ZEND_AST_CONST ,
2014-08-25 19:21:16 +00:00
zend_ast_create_zval_from_str ( zend_string_init ( " __CLASS__ " , sizeof ( " __CLASS__ " ) - 1 , 0 ) ) ) ;
2014-07-21 16:02:31 +00:00
zend_compile_const ( result , const_ast TSRMLS_CC ) ;
2014-08-25 17:46:21 +00:00
zend_ast_destroy ( const_ast ) ;
2014-07-21 16:02:31 +00:00
}
2014-07-16 21:10:16 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-07-16 21:10:16 +00:00
2014-08-29 05:05:58 +00:00
zend_bool zend_is_allowed_in_const_expr ( zend_ast_kind kind ) /* { { { */
{
2014-06-28 16:03:26 +00:00
return kind = = ZEND_AST_ZVAL | | kind = = ZEND_AST_BINARY_OP
2014-06-26 20:02:54 +00:00
| | kind = = ZEND_AST_GREATER | | kind = = ZEND_AST_GREATER_EQUAL
2014-06-26 14:03:15 +00:00
| | kind = = ZEND_AST_AND | | kind = = ZEND_AST_OR
2014-07-27 20:26:06 +00:00
| | kind = = ZEND_AST_UNARY_OP
2014-06-26 14:03:15 +00:00
| | kind = = ZEND_AST_UNARY_PLUS | | kind = = ZEND_AST_UNARY_MINUS
2014-08-16 20:08:02 +00:00
| | kind = = ZEND_AST_CONDITIONAL | | kind = = ZEND_AST_DIM
2014-06-26 14:35:30 +00:00
| | kind = = ZEND_AST_ARRAY | | kind = = ZEND_AST_ARRAY_ELEM
2014-06-26 19:44:46 +00:00
| | kind = = ZEND_AST_CONST | | kind = = ZEND_AST_CLASS_CONST
2014-07-16 21:10:16 +00:00
| | kind = = ZEND_AST_RESOLVE_CLASS_NAME | | kind = = ZEND_AST_MAGIC_CONST ;
2014-06-26 14:35:30 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-26 14:35:30 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_const_expr_class_const ( zend_ast * * ast_ptr TSRMLS_DC ) /* { { { */
{
2014-06-26 14:35:30 +00:00
zend_ast * ast = * ast_ptr ;
zend_ast * class_ast = ast - > child [ 0 ] ;
zend_ast * const_ast = ast - > child [ 1 ] ;
2014-07-28 13:16:35 +00:00
zend_string * class_name = zend_ast_get_str ( class_ast ) ;
zend_string * const_name = zend_ast_get_str ( const_ast ) ;
2014-06-26 14:35:30 +00:00
zval result ;
int fetch_type ;
2014-06-28 16:03:26 +00:00
if ( class_ast - > kind ! = ZEND_AST_ZVAL ) {
2014-06-26 14:35:30 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
" Dynamic class names are not allowed in compile-time class constant references " ) ;
2007-09-28 19:52:53 +00:00
}
2014-07-28 13:39:43 +00:00
fetch_type = zend_get_class_fetch_type ( class_name ) ;
2013-07-16 18:39:33 +00:00
2014-06-26 14:35:30 +00:00
if ( ZEND_FETCH_CLASS_STATIC = = fetch_type ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" \" static:: \" is not allowed in compile-time constants " ) ;
2014-07-19 21:30:07 +00:00
}
if ( ZEND_FETCH_CLASS_DEFAULT = = fetch_type ) {
class_name = zend_resolve_class_name_ast ( class_ast TSRMLS_CC ) ;
2013-07-16 18:39:33 +00:00
} else {
2014-08-25 19:21:16 +00:00
zend_string_addref ( class_name ) ;
2013-07-16 18:39:33 +00:00
}
2014-07-19 21:30:07 +00:00
Z_STR ( result ) = zend_concat3 (
class_name - > val , class_name - > len , " :: " , 2 , const_name - > val , const_name - > len ) ;
2014-06-26 14:35:30 +00:00
Z_TYPE_INFO ( result ) = IS_CONSTANT_EX ;
if ( IS_INTERNED ( Z_STR ( result ) ) ) {
Z_TYPE_FLAGS ( result ) & = ~ ( IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE ) ;
2013-08-25 14:21:51 +00:00
}
2014-06-26 14:35:30 +00:00
Z_CONST_FLAGS ( result ) = fetch_type ;
2013-07-16 18:39:33 +00:00
2014-06-26 14:35:30 +00:00
zend_ast_destroy ( ast ) ;
2014-08-25 19:21:16 +00:00
zend_string_release ( class_name ) ;
2013-08-24 21:53:43 +00:00
2014-06-28 16:03:26 +00:00
* ast_ptr = zend_ast_create_zval ( & result ) ;
2014-06-26 14:03:15 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-08-24 21:53:43 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_const_expr_const ( zend_ast * * ast_ptr TSRMLS_DC ) /* { { { */
{
2014-06-26 14:56:50 +00:00
zend_ast * ast = * ast_ptr ;
2014-06-28 20:27:06 +00:00
zend_ast * name_ast = ast - > child [ 0 ] ;
zval * orig_name = zend_ast_get_zval ( name_ast ) ;
2014-07-22 11:25:47 +00:00
zend_bool is_fully_qualified ;
2014-06-26 14:56:50 +00:00
2014-06-28 20:27:06 +00:00
znode result ;
zval resolved_name ;
2014-06-26 14:56:50 +00:00
2014-06-28 20:27:06 +00:00
if ( zend_constant_ct_subst ( & result , orig_name , 0 TSRMLS_CC ) ) {
2014-06-26 14:56:50 +00:00
zend_ast_destroy ( ast ) ;
2014-06-28 16:03:26 +00:00
* ast_ptr = zend_ast_create_zval ( & result . u . constant ) ;
2014-06-26 14:56:50 +00:00
return ;
}
2014-06-28 20:27:06 +00:00
ZVAL_STR ( & resolved_name , zend_resolve_const_name (
2014-07-22 11:25:47 +00:00
Z_STR_P ( orig_name ) , name_ast - > attr , & is_fully_qualified TSRMLS_CC ) ) ;
2014-06-26 14:56:50 +00:00
2014-06-28 20:27:06 +00:00
Z_TYPE_INFO ( resolved_name ) = IS_CONSTANT_EX ;
if ( ! is_fully_qualified ) {
Z_CONST_FLAGS ( resolved_name ) = IS_CONSTANT_UNQUALIFIED ;
2014-06-26 14:56:50 +00:00
}
zend_ast_destroy ( ast ) ;
2014-06-28 20:27:06 +00:00
* ast_ptr = zend_ast_create_zval ( & resolved_name ) ;
2014-06-26 14:56:50 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-08-24 21:53:43 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_const_expr_resolve_class_name ( zend_ast * * ast_ptr TSRMLS_DC ) /* { { { */
{
2014-06-26 19:44:46 +00:00
zend_ast * ast = * ast_ptr ;
zend_ast * name_ast = ast - > child [ 0 ] ;
2014-08-25 19:21:16 +00:00
uint32_t fetch_type = zend_get_class_fetch_type ( zend_ast_get_str ( name_ast ) ) ;
2014-07-19 21:30:07 +00:00
zval result ;
2013-08-24 21:53:43 +00:00
2014-06-26 19:44:46 +00:00
switch ( fetch_type ) {
case ZEND_FETCH_CLASS_SELF :
if ( ! CG ( active_class_entry ) ) {
zend_error_noreturn ( E_COMPILE_ERROR ,
" Cannot access self::class when no class scope is active " ) ;
2013-11-09 02:37:38 +00:00
}
2014-08-25 19:21:16 +00:00
ZVAL_STR ( & result , zend_string_copy ( CG ( active_class_entry ) - > name ) ) ;
2014-06-26 19:44:46 +00:00
break ;
case ZEND_FETCH_CLASS_STATIC :
case ZEND_FETCH_CLASS_PARENT :
zend_error_noreturn ( E_COMPILE_ERROR ,
" %s::class cannot be used for compile-time class name resolution " ,
fetch_type = = ZEND_FETCH_CLASS_STATIC ? " static " : " parent "
) ;
break ;
case ZEND_FETCH_CLASS_DEFAULT :
2014-07-19 21:30:07 +00:00
ZVAL_STR ( & result , zend_resolve_class_name_ast ( name_ast TSRMLS_CC ) ) ;
2014-06-26 19:44:46 +00:00
break ;
EMPTY_SWITCH_DEFAULT_CASE ( )
}
zend_ast_destroy ( ast ) ;
2014-07-19 21:30:07 +00:00
* ast_ptr = zend_ast_create_zval ( & result ) ;
2014-06-26 19:44:46 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2014-06-26 19:44:46 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_const_expr_magic_const ( zend_ast * * ast_ptr TSRMLS_DC ) /* { { { */
{
2014-07-21 16:21:13 +00:00
zend_ast * ast = * ast_ptr ;
zend_class_entry * ce = CG ( active_class_entry ) ;
2013-11-09 02:37:38 +00:00
2014-07-21 16:21:13 +00:00
/* Other cases already resolved by constant folding */
ZEND_ASSERT ( ast - > attr = = T_CLASS_C & & ce & & ZEND_CE_IS_TRAIT ( ce ) ) ;
2013-11-09 02:37:38 +00:00
2014-07-21 16:21:13 +00:00
{
zval const_zv ;
ZVAL_STRING ( & const_zv , " __CLASS__ " ) ;
Z_TYPE_INFO ( const_zv ) = IS_CONSTANT_EX ;
2013-08-24 21:53:43 +00:00
2014-07-21 16:21:13 +00:00
zend_ast_destroy ( ast ) ;
* ast_ptr = zend_ast_create_zval ( & const_zv ) ;
2013-07-16 18:39:33 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-07-16 18:39:33 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_const_expr ( zend_ast * * ast_ptr TSRMLS_DC ) /* { { { */
{
2014-06-26 14:03:15 +00:00
zend_ast * ast = * ast_ptr ;
2014-06-28 16:03:26 +00:00
if ( ast = = NULL | | ast - > kind = = ZEND_AST_ZVAL ) {
2014-06-26 14:03:15 +00:00
return ;
2013-07-23 18:21:48 +00:00
}
2014-06-26 14:03:15 +00:00
if ( ! zend_is_allowed_in_const_expr ( ast - > kind ) ) {
zend_error_noreturn ( E_COMPILE_ERROR , " Constant expression contains invalid operations " ) ;
2013-07-23 18:21:48 +00:00
}
2014-06-26 14:35:30 +00:00
switch ( ast - > kind ) {
case ZEND_AST_CLASS_CONST :
zend_compile_const_expr_class_const ( ast_ptr TSRMLS_CC ) ;
break ;
2014-06-26 14:56:50 +00:00
case ZEND_AST_CONST :
zend_compile_const_expr_const ( ast_ptr TSRMLS_CC ) ;
break ;
2014-06-26 19:44:46 +00:00
case ZEND_AST_RESOLVE_CLASS_NAME :
zend_compile_const_expr_resolve_class_name ( ast_ptr TSRMLS_CC ) ;
break ;
2014-07-21 16:21:13 +00:00
case ZEND_AST_MAGIC_CONST :
zend_compile_const_expr_magic_const ( ast_ptr TSRMLS_CC ) ;
break ;
2014-07-30 15:29:59 +00:00
default :
zend_ast_apply ( ast , zend_compile_const_expr TSRMLS_CC ) ;
break ;
2014-06-26 14:35:30 +00:00
}
2013-07-23 18:21:48 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-07-23 18:21:48 +00:00
2014-08-29 05:05:58 +00:00
void zend_const_expr_to_zval ( zval * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-30 15:44:26 +00:00
zend_ast * orig_ast = ast ;
zend_eval_const_expr ( & ast TSRMLS_CC ) ;
zend_compile_const_expr ( & ast TSRMLS_CC ) ;
if ( ast - > kind = = ZEND_AST_ZVAL ) {
ZVAL_COPY_VALUE ( result , zend_ast_get_zval ( ast ) ) ;
2007-09-28 19:52:53 +00:00
2014-07-30 15:44:26 +00:00
/* Kill this branch of the original AST, as it was already destroyed.
* It would be nice to find a better solution to this problem in the
* future . */
orig_ast - > kind = 0 ;
} else {
ZVAL_NEW_AST ( result , zend_ast_copy ( ast ) ) ;
2007-09-28 19:52:53 +00:00
}
2014-07-30 15:44:26 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2007-09-28 19:52:53 +00:00
2014-07-22 11:02:51 +00:00
/* Same as compile_stmt, but with early binding */
2014-08-29 05:05:58 +00:00
void zend_compile_top_stmt ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-22 11:02:51 +00:00
if ( ! ast ) {
return ;
2007-09-28 19:52:53 +00:00
}
2014-07-22 11:02:51 +00:00
if ( ast - > kind = = ZEND_AST_STMT_LIST ) {
2014-07-27 20:26:06 +00:00
zend_ast_list * list = zend_ast_get_list ( ast ) ;
2014-08-25 19:21:16 +00:00
uint32_t i ;
2014-07-27 20:26:06 +00:00
for ( i = 0 ; i < list - > children ; + + i ) {
zend_compile_top_stmt ( list - > child [ i ] TSRMLS_CC ) ;
2013-08-24 22:05:55 +00:00
}
2014-07-22 11:02:51 +00:00
return ;
2013-08-24 22:05:55 +00:00
}
2014-07-22 11:02:51 +00:00
zend_compile_stmt ( ast TSRMLS_CC ) ;
2007-09-28 19:52:53 +00:00
2014-07-22 13:50:23 +00:00
if ( ast - > kind ! = ZEND_AST_NAMESPACE & & ast - > kind ! = ZEND_AST_HALT_COMPILER ) {
2014-07-22 12:08:52 +00:00
zend_verify_namespace ( TSRMLS_C ) ;
}
2014-07-22 11:02:51 +00:00
if ( ast - > kind = = ZEND_AST_FUNC_DECL | | ast - > kind = = ZEND_AST_CLASS ) {
2014-07-26 16:36:57 +00:00
CG ( zend_lineno ) = ( ( zend_ast_decl * ) ast ) - > end_lineno ;
2014-07-22 11:02:51 +00:00
zend_do_early_binding ( TSRMLS_C ) ;
2008-11-25 09:56:32 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2008-11-25 09:56:32 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_stmt ( zend_ast * ast TSRMLS_DC ) /* { { { */
{
2014-07-09 21:39:21 +00:00
if ( ! ast ) {
return ;
2007-09-28 19:52:53 +00:00
}
2014-07-09 21:39:21 +00:00
2014-07-12 15:10:10 +00:00
CG ( zend_lineno ) = ast - > lineno ;
2014-07-12 12:03:42 +00:00
2014-06-07 11:06:53 +00:00
switch ( ast - > kind ) {
2014-07-09 21:39:21 +00:00
case ZEND_AST_STMT_LIST :
zend_compile_stmt_list ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-06-07 11:06:53 +00:00
case ZEND_AST_GLOBAL :
zend_compile_global_var ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-12 15:00:53 +00:00
case ZEND_AST_STATIC :
zend_compile_static_var ( ast TSRMLS_CC ) ;
break ;
2014-06-07 11:06:53 +00:00
case ZEND_AST_UNSET :
zend_compile_unset ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-07 19:06:02 +00:00
case ZEND_AST_RETURN :
zend_compile_return ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_ECHO :
2014-07-07 19:14:14 +00:00
zend_compile_echo ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_THROW :
2014-07-09 20:47:36 +00:00
zend_compile_throw ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_BREAK :
case ZEND_AST_CONTINUE :
2014-07-09 21:05:21 +00:00
zend_compile_break_continue ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_GOTO :
2014-07-09 21:11:32 +00:00
zend_compile_goto ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-09 21:46:22 +00:00
case ZEND_AST_LABEL :
zend_compile_label ( ast TSRMLS_CC ) ;
2014-07-09 22:00:48 +00:00
break ;
2014-07-10 12:35:59 +00:00
case ZEND_AST_WHILE :
zend_compile_while ( ast TSRMLS_CC ) ;
break ;
2014-07-10 12:46:22 +00:00
case ZEND_AST_DO_WHILE :
zend_compile_do_while ( ast TSRMLS_CC ) ;
break ;
2014-07-10 13:51:47 +00:00
case ZEND_AST_FOR :
zend_compile_for ( ast TSRMLS_CC ) ;
break ;
2014-07-11 10:16:21 +00:00
case ZEND_AST_FOREACH :
zend_compile_foreach ( ast TSRMLS_CC ) ;
break ;
2014-07-10 14:38:04 +00:00
case ZEND_AST_IF :
zend_compile_if ( ast TSRMLS_CC ) ;
break ;
2014-07-11 13:31:47 +00:00
case ZEND_AST_SWITCH :
zend_compile_switch ( ast TSRMLS_CC ) ;
break ;
2014-07-12 11:50:58 +00:00
case ZEND_AST_TRY :
zend_compile_try ( ast TSRMLS_CC ) ;
break ;
2014-07-22 14:11:19 +00:00
case ZEND_AST_DECLARE :
zend_compile_declare ( ast TSRMLS_CC ) ;
break ;
2014-07-15 22:06:41 +00:00
case ZEND_AST_FUNC_DECL :
2014-07-19 10:52:44 +00:00
case ZEND_AST_METHOD :
2014-07-18 12:57:00 +00:00
zend_compile_func_decl ( NULL , ast TSRMLS_CC ) ;
2014-07-15 22:06:41 +00:00
break ;
2014-07-19 12:54:56 +00:00
case ZEND_AST_PROP_DECL :
zend_compile_prop_decl ( ast TSRMLS_CC ) ;
break ;
2014-07-19 13:13:50 +00:00
case ZEND_AST_CLASS_CONST_DECL :
zend_compile_class_const_decl ( ast TSRMLS_CC ) ;
break ;
2014-07-19 20:39:01 +00:00
case ZEND_AST_USE_TRAIT :
zend_compile_use_trait ( ast TSRMLS_CC ) ;
break ;
2014-07-21 14:34:45 +00:00
case ZEND_AST_CLASS :
zend_compile_class_decl ( ast TSRMLS_CC ) ;
break ;
2014-07-21 20:49:31 +00:00
case ZEND_AST_USE :
zend_compile_use ( ast TSRMLS_CC ) ;
break ;
2014-07-22 09:55:07 +00:00
case ZEND_AST_CONST_DECL :
zend_compile_const_decl ( ast TSRMLS_CC ) ;
break ;
2014-07-22 10:45:44 +00:00
case ZEND_AST_NAMESPACE :
zend_compile_namespace ( ast TSRMLS_CC ) ;
break ;
2014-07-22 12:22:59 +00:00
case ZEND_AST_HALT_COMPILER :
zend_compile_halt_compiler ( ast TSRMLS_CC ) ;
break ;
2014-07-09 22:04:27 +00:00
default :
{
znode result ;
zend_compile_expr ( & result , ast TSRMLS_CC ) ;
zend_do_free ( & result TSRMLS_CC ) ;
}
2013-07-16 18:39:33 +00:00
}
2014-07-09 22:00:48 +00:00
if ( Z_LVAL ( CG ( declarables ) . ticks ) & & ! zend_is_unticked_stmt ( ast ) ) {
zend_emit_tick ( TSRMLS_C ) ;
2013-07-23 18:21:48 +00:00
}
2007-09-28 19:52:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2007-09-28 19:52:53 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_expr ( znode * result , zend_ast * ast TSRMLS_DC ) /* { { { */
{
/* CG(zend_lineno) = ast->lineno; */
2014-07-27 11:25:32 +00:00
CG ( zend_lineno ) = zend_ast_get_lineno ( ast ) ;
2008-11-25 09:56:32 +00:00
2014-06-07 11:06:53 +00:00
switch ( ast - > kind ) {
2014-06-28 16:03:26 +00:00
case ZEND_AST_ZVAL :
2014-06-07 11:06:53 +00:00
ZVAL_COPY ( & result - > u . constant , zend_ast_get_zval ( ast ) ) ;
result - > op_type = IS_CONST ;
return ;
case ZEND_AST_ZNODE :
* result = * zend_ast_get_znode ( ast ) ;
return ;
case ZEND_AST_VAR :
case ZEND_AST_DIM :
case ZEND_AST_PROP :
case ZEND_AST_STATIC_PROP :
case ZEND_AST_CALL :
case ZEND_AST_METHOD_CALL :
case ZEND_AST_STATIC_CALL :
zend_compile_var ( result , ast , BP_VAR_R TSRMLS_CC ) ;
return ;
case ZEND_AST_ASSIGN :
zend_compile_assign ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_ASSIGN_REF :
zend_compile_assign_ref ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_NEW :
2014-06-14 16:30:18 +00:00
zend_compile_new ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_CLONE :
2014-06-14 16:30:18 +00:00
zend_compile_clone ( result , ast TSRMLS_CC ) ;
return ;
2014-06-19 11:57:29 +00:00
case ZEND_AST_ASSIGN_OP :
2014-06-07 11:06:53 +00:00
zend_compile_compound_assign ( result , ast TSRMLS_CC ) ;
return ;
2014-06-19 11:57:29 +00:00
case ZEND_AST_BINARY_OP :
2014-06-23 19:30:57 +00:00
zend_compile_binary_op ( result , ast TSRMLS_CC ) ;
2014-06-14 16:30:18 +00:00
return ;
case ZEND_AST_GREATER :
case ZEND_AST_GREATER_EQUAL :
zend_compile_greater ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_UNARY_OP :
2014-06-14 16:30:18 +00:00
zend_compile_unary_op ( result , ast TSRMLS_CC ) ;
return ;
2014-06-26 10:43:20 +00:00
case ZEND_AST_UNARY_PLUS :
case ZEND_AST_UNARY_MINUS :
2014-06-14 16:30:18 +00:00
zend_compile_unary_pm ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_AND :
case ZEND_AST_OR :
zend_compile_short_circuiting ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_POST_INC :
case ZEND_AST_POST_DEC :
2014-06-14 16:30:18 +00:00
zend_compile_post_incdec ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_PRE_INC :
case ZEND_AST_PRE_DEC :
2014-06-14 16:30:18 +00:00
zend_compile_pre_incdec ( result , ast TSRMLS_CC ) ;
return ;
2014-06-19 11:57:29 +00:00
case ZEND_AST_CAST :
2014-06-14 16:30:18 +00:00
zend_compile_cast ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_CONDITIONAL :
zend_compile_conditional ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_PRINT :
2014-06-14 16:30:18 +00:00
zend_compile_print ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_EXIT :
2014-06-14 16:30:18 +00:00
zend_compile_exit ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_YIELD :
2014-06-14 16:30:18 +00:00
zend_compile_yield ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_INSTANCEOF :
2014-06-14 16:30:18 +00:00
zend_compile_instanceof ( result , ast TSRMLS_CC ) ;
return ;
2014-07-27 20:26:06 +00:00
case ZEND_AST_INCLUDE_OR_EVAL :
2014-06-19 11:57:29 +00:00
zend_compile_include_or_eval ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_ISSET :
case ZEND_AST_EMPTY :
zend_compile_isset_or_empty ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_SILENCE :
zend_compile_silence ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_SHELL_EXEC :
zend_compile_shell_exec ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_ARRAY :
2014-06-23 19:30:57 +00:00
zend_compile_array ( result , ast TSRMLS_CC ) ;
2014-06-19 11:57:29 +00:00
return ;
case ZEND_AST_CONST :
zend_compile_const ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_CLASS_CONST :
zend_compile_class_const ( result , ast TSRMLS_CC ) ;
return ;
case ZEND_AST_RESOLVE_CLASS_NAME :
zend_compile_resolve_class_name ( result , ast TSRMLS_CC ) ;
return ;
2014-06-21 18:03:29 +00:00
case ZEND_AST_ENCAPS_LIST :
zend_compile_encaps_list ( result , ast TSRMLS_CC ) ;
return ;
2014-07-16 21:10:16 +00:00
case ZEND_AST_MAGIC_CONST :
zend_compile_magic_const ( result , ast TSRMLS_CC ) ;
return ;
2014-07-18 10:58:24 +00:00
case ZEND_AST_CLOSURE :
2014-07-18 12:57:00 +00:00
zend_compile_func_decl ( result , ast TSRMLS_CC ) ;
2014-07-18 10:58:24 +00:00
return ;
2014-06-07 11:06:53 +00:00
default :
ZEND_ASSERT ( 0 /* not supported */ ) ;
2013-11-06 18:21:07 +00:00
}
}
2014-08-29 05:05:58 +00:00
/* }}} */
2013-11-06 18:21:07 +00:00
2014-08-29 05:05:58 +00:00
void zend_compile_var ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-06-07 11:06:53 +00:00
switch ( ast - > kind ) {
case ZEND_AST_VAR :
zend_compile_simple_var ( result , ast , type TSRMLS_CC ) ;
return ;
case ZEND_AST_DIM :
zend_compile_dim ( result , ast , type TSRMLS_CC ) ;
return ;
case ZEND_AST_PROP :
zend_compile_prop ( result , ast , type TSRMLS_CC ) ;
return ;
case ZEND_AST_STATIC_PROP :
zend_compile_static_prop ( result , ast , type TSRMLS_CC ) ;
return ;
case ZEND_AST_CALL :
zend_compile_call ( result , ast , type TSRMLS_CC ) ;
return ;
case ZEND_AST_METHOD_CALL :
zend_compile_method_call ( result , ast , type TSRMLS_CC ) ;
return ;
case ZEND_AST_STATIC_CALL :
zend_compile_static_call ( result , ast , type TSRMLS_CC ) ;
return ;
2014-08-15 15:10:06 +00:00
case ZEND_AST_ZNODE :
* result = * zend_ast_get_znode ( ast ) ;
return ;
2014-06-07 11:06:53 +00:00
default :
2014-06-19 11:57:29 +00:00
if ( type = = BP_VAR_W | | type = = BP_VAR_REF
| | type = = BP_VAR_RW | | type = = BP_VAR_UNSET
) {
/* For BC reasons =& new Foo is allowed */
2014-07-27 20:26:06 +00:00
if ( type ! = BP_VAR_REF | | ast - > kind ! = ZEND_AST_NEW ) {
2014-06-19 11:57:29 +00:00
zend_error_noreturn ( E_COMPILE_ERROR ,
" Cannot use temporary expression in write context " ) ;
}
}
2008-02-12 00:21:15 +00:00
2014-06-07 11:06:53 +00:00
zend_compile_expr ( result , ast TSRMLS_CC ) ;
return ;
2011-01-19 17:17:52 +00:00
}
2014-06-07 11:06:53 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2008-02-12 00:21:15 +00:00
2014-08-29 05:05:58 +00:00
void zend_delayed_compile_var ( znode * result , zend_ast * ast , uint32_t type TSRMLS_DC ) /* { { { */
{
2014-08-15 15:10:06 +00:00
zend_op * opline ;
switch ( ast - > kind ) {
case ZEND_AST_DIM :
opline = zend_delayed_compile_dim ( result , ast , type TSRMLS_CC ) ;
zend_adjust_for_fetch_type ( opline , type ) ;
return ;
case ZEND_AST_PROP :
opline = zend_delayed_compile_prop ( result , ast , type TSRMLS_CC ) ;
zend_adjust_for_fetch_type ( opline , type ) ;
return ;
default :
zend_compile_var ( result , ast , type TSRMLS_CC ) ;
return ;
2008-02-12 00:21:15 +00:00
}
2014-08-15 15:10:06 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2008-02-12 00:21:15 +00:00
2014-08-29 05:05:58 +00:00
void zend_eval_const_expr ( zend_ast * * ast_ptr TSRMLS_DC ) /* { { { */
{
2014-07-21 16:02:31 +00:00
zend_ast * ast = * ast_ptr ;
zval result ;
2008-02-12 00:21:15 +00:00
2014-07-30 15:29:59 +00:00
if ( ! ast ) {
2014-06-23 19:30:57 +00:00
return ;
2008-02-12 00:21:15 +00:00
}
2014-06-23 19:30:57 +00:00
switch ( ast - > kind ) {
case ZEND_AST_BINARY_OP :
2014-07-30 15:29:59 +00:00
zend_eval_const_expr ( & ast - > child [ 0 ] TSRMLS_CC ) ;
zend_eval_const_expr ( & ast - > child [ 1 ] TSRMLS_CC ) ;
2014-07-29 21:22:23 +00:00
if ( ast - > child [ 0 ] - > kind ! = ZEND_AST_ZVAL | | ast - > child [ 1 ] - > kind ! = ZEND_AST_ZVAL ) {
return ;
}
zend_ct_eval_binary_op ( & result , ast - > attr ,
zend_ast_get_zval ( ast - > child [ 0 ] ) , zend_ast_get_zval ( ast - > child [ 1 ] ) TSRMLS_CC ) ;
2014-06-23 19:30:57 +00:00
break ;
2014-06-26 10:43:20 +00:00
case ZEND_AST_GREATER :
case ZEND_AST_GREATER_EQUAL :
2014-07-30 15:29:59 +00:00
zend_eval_const_expr ( & ast - > child [ 0 ] TSRMLS_CC ) ;
zend_eval_const_expr ( & ast - > child [ 1 ] TSRMLS_CC ) ;
2014-07-29 21:22:23 +00:00
if ( ast - > child [ 0 ] - > kind ! = ZEND_AST_ZVAL | | ast - > child [ 1 ] - > kind ! = ZEND_AST_ZVAL ) {
return ;
}
zend_ct_eval_greater ( & result , ast - > kind ,
zend_ast_get_zval ( ast - > child [ 0 ] ) , zend_ast_get_zval ( ast - > child [ 1 ] ) TSRMLS_CC ) ;
2014-06-26 10:43:20 +00:00
break ;
case ZEND_AST_UNARY_PLUS :
case ZEND_AST_UNARY_MINUS :
2014-07-30 15:29:59 +00:00
zend_eval_const_expr ( & ast - > child [ 0 ] TSRMLS_CC ) ;
2014-07-29 21:22:23 +00:00
if ( ast - > child [ 0 ] - > kind ! = ZEND_AST_ZVAL ) {
return ;
}
zend_ct_eval_unary_pm ( & result , ast - > kind ,
zend_ast_get_zval ( ast - > child [ 0 ] ) TSRMLS_CC ) ;
2014-06-26 10:43:20 +00:00
break ;
2014-06-23 19:30:57 +00:00
case ZEND_AST_ARRAY :
2014-07-29 21:22:23 +00:00
if ( ! zend_try_ct_eval_array ( & result , ast TSRMLS_CC ) ) {
return ;
}
2014-06-23 19:30:57 +00:00
break ;
2014-07-21 16:02:31 +00:00
case ZEND_AST_MAGIC_CONST :
2014-07-29 21:22:23 +00:00
if ( ! zend_try_ct_eval_magic_const ( & result , ast TSRMLS_CC ) ) {
return ;
}
2014-07-21 16:02:31 +00:00
break ;
2014-08-26 09:06:19 +00:00
case ZEND_AST_CONST : {
znode result_node ;
if ( ! zend_constant_ct_subst ( & result_node , zend_ast_get_zval ( ast - > child [ 0 ] ) , 0 TSRMLS_CC ) ) {
return ;
}
zend_ast_destroy ( ast ) ;
* ast_ptr = zend_ast_create_zval ( & result_node . u . constant ) ;
return ;
}
2014-07-29 21:22:23 +00:00
default :
return ;
2008-02-12 00:21:15 +00:00
}
2014-07-29 21:22:23 +00:00
zend_ast_destroy ( ast ) ;
* ast_ptr = zend_ast_create_zval ( & result ) ;
2008-02-12 00:21:15 +00:00
}
2014-08-29 05:05:58 +00:00
/* }}} */
2008-02-12 01:17:48 +00:00
2003-02-01 01:49:15 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/