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