@@ -4956,6 +4956,79 @@ static zend_result zend_compile_func_sprintf(znode *result, zend_ast_list *args)
4956
4956
return SUCCESS ;
4957
4957
}
4958
4958
4959
+ static zend_op_array * zend_compile_func_decl (znode * result , zend_ast * ast , bool toplevel );
4960
+
4961
+ static zend_result zend_compile_func_array_map (znode * result , zend_ast_list * args ) /* {{{ */
4962
+ {
4963
+ /* Bail out if we do not have exactly two parameters. */
4964
+ if (args -> children != 2 ) {
4965
+ return FAILURE ;
4966
+ }
4967
+
4968
+ zend_eval_const_expr (& args -> child [0 ]);
4969
+ /* Bail out if the first parameter is not a Closure. */
4970
+ if (args -> child [0 ]-> kind != ZEND_AST_CLOSURE ) {
4971
+ printf ("!closure\n" );
4972
+ return FAILURE ;
4973
+ }
4974
+ zend_ast_decl * closure_ast = (zend_ast_decl * ) args -> child [0 ];
4975
+ zend_ast * uses_ast = closure_ast -> child [1 ];
4976
+ /* Bail out if the Closure is not static. */
4977
+ if (!(closure_ast -> flags & ZEND_ACC_STATIC )) {
4978
+ printf ("!static\n" );
4979
+ return FAILURE ;
4980
+ }
4981
+ /* Bail out if the Closure imports stuff from the outer scope. */
4982
+ if (uses_ast ) {
4983
+ printf ("uses\n" );
4984
+ return FAILURE ;
4985
+ }
4986
+
4987
+ znode closure ;
4988
+ zend_compile_func_decl (& closure , args -> child [0 ], 0 );
4989
+
4990
+ znode expr_node , reset_node , value_node , key_node ;
4991
+ zend_op * opline ;
4992
+ uint32_t opnum_reset , opnum_fetch ;
4993
+ zend_compile_expr (& expr_node , args -> child [1 ]);
4994
+
4995
+ opnum_reset = get_next_op_number ();
4996
+ opline = zend_emit_op (& reset_node , ZEND_FE_RESET_R , & expr_node , NULL );
4997
+
4998
+ zend_begin_loop (ZEND_FE_FREE , & reset_node , 0 );
4999
+
5000
+ opnum_fetch = get_next_op_number ();
5001
+ opline = zend_emit_op (NULL , ZEND_FE_FETCH_R , & reset_node , NULL );
5002
+
5003
+ opline -> op2_type = IS_VAR ;
5004
+ opline -> op2 .var = get_temporary_variable ();
5005
+ GET_NODE (& value_node , opline -> op2 );
5006
+ zend_emit_op (NULL , ZEND_INIT_DYNAMIC_CALL , NULL , & closure );
5007
+ uint32_t opnum_init = get_next_op_number () - 1 ;
5008
+ opline = & CG (active_op_array )-> opcodes [opnum_init ];
5009
+ opline -> extended_value = 1 ;
5010
+ opline = zend_emit_op (NULL , ZEND_SEND_VAR , & value_node , NULL );
5011
+ opline -> op2 .opline_num = 1 ;
5012
+ zend_emit_op (result , ZEND_DO_FCALL , NULL , NULL );
5013
+
5014
+ zend_emit_jump (opnum_fetch );
5015
+
5016
+ opline = & CG (active_op_array )-> opcodes [opnum_reset ];
5017
+ opline -> op2 .opline_num = get_next_op_number ();
5018
+
5019
+ opline = & CG (active_op_array )-> opcodes [opnum_fetch ];
5020
+ opline -> extended_value = get_next_op_number ();
5021
+
5022
+ zend_end_loop (opnum_fetch , & reset_node );
5023
+
5024
+ opline = zend_emit_op (NULL , ZEND_FE_FREE , & reset_node , NULL );
5025
+
5026
+ result -> op_type = IS_CONST ;
5027
+ ZVAL_LONG (& result -> u .constant , 1 );
5028
+
5029
+ return SUCCESS ;
5030
+ }
5031
+
4959
5032
static zend_result zend_try_compile_special_func_ex (znode * result , zend_string * lcname , zend_ast_list * args , zend_function * fbc , uint32_t type ) /* {{{ */
4960
5033
{
4961
5034
if (zend_string_equals_literal (lcname , "strlen" )) {
@@ -5024,6 +5097,8 @@ static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *
5024
5097
return zend_compile_func_array_key_exists (result , args );
5025
5098
} else if (zend_string_equals_literal (lcname , "sprintf" )) {
5026
5099
return zend_compile_func_sprintf (result , args );
5100
+ } else if (zend_string_equals_literal (lcname , "array_map" )) {
5101
+ return zend_compile_func_array_map (result , args );
5027
5102
} else {
5028
5103
return FAILURE ;
5029
5104
}
0 commit comments