Back to index

php5  5.3.10
Classes | Defines | Typedefs | Functions | Variables
zend_closures.c File Reference
#include "zend.h"
#include "zend_API.h"
#include "zend_closures.h"
#include "zend_exceptions.h"
#include "zend_interfaces.h"
#include "zend_objects.h"
#include "zend_objects_API.h"
#include "zend_globals.h"

Go to the source code of this file.

Classes

struct  _zend_closure

Defines

#define ZEND_CLOSURE_PRINT_NAME   "Closure object"
#define ZEND_CLOSURE_PROPERTY_ERROR()   zend_error(E_RECOVERABLE_ERROR, "Closure object cannot have properties")

Typedefs

typedef struct _zend_closure zend_closure

Functions

 ZEND_METHOD (Closure, __invoke)
static zend_functionzend_closure_get_constructor (zval *object TSRMLS_DC)
static int zend_closure_compare_objects (zval *o1, zval *o2 TSRMLS_DC)
ZEND_API zend_functionzend_get_closure_invoke_method (zval *obj TSRMLS_DC)
ZEND_API const zend_functionzend_get_closure_method_def (zval *obj TSRMLS_DC)
static zend_functionzend_closure_get_method (zval **object_ptr, char *method_name, int method_len TSRMLS_DC)
static zval * zend_closure_read_property (zval *object, zval *member, int type TSRMLS_DC)
static void zend_closure_write_property (zval *object, zval *member, zval *value TSRMLS_DC)
static zval ** zend_closure_get_property_ptr_ptr (zval *object, zval *member TSRMLS_DC)
static int zend_closure_has_property (zval *object, zval *member, int has_set_exists TSRMLS_DC)
static void zend_closure_unset_property (zval *object, zval *member TSRMLS_DC)
static void zend_closure_free_storage (void *object TSRMLS_DC)
static zend_object_value zend_closure_new (zend_class_entry *class_type TSRMLS_DC)
int zend_closure_get_closure (zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC)
static HashTablezend_closure_get_debug_info (zval *object, int *is_temp TSRMLS_DC)
static HashTablezend_closure_get_properties (zval *obj TSRMLS_DC)
 ZEND_METHOD (Closure, __construct)
void zend_register_closure_ce (TSRMLS_D)
static int zval_copy_static_var (zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key)
ZEND_API void zend_create_closure (zval *res, zend_function *func TSRMLS_DC)

Variables

ZEND_API zend_class_entry * zend_ce_closure
static zend_object_handlers closure_handlers
static const zend_function_entry closure_functions []

Class Documentation

struct _zend_closure

Definition at line 37 of file zend_closures.c.

Collaboration diagram for _zend_closure:
Class Members
HashTable * debug_info
zend_function func
zend_object std

Define Documentation

#define ZEND_CLOSURE_PRINT_NAME   "Closure object"

Definition at line 32 of file zend_closures.c.

#define ZEND_CLOSURE_PROPERTY_ERROR ( )    zend_error(E_RECOVERABLE_ERROR, "Closure object cannot have properties")

Definition at line 34 of file zend_closures.c.


Typedef Documentation

typedef struct _zend_closure zend_closure

Function Documentation

static int zend_closure_compare_objects ( zval *  o1,
zval *o2  TSRMLS_DC 
) [static]

Definition at line 85 of file zend_closures.c.

{
       return (Z_OBJ_HANDLE_P(o1) != Z_OBJ_HANDLE_P(o2));
}

Here is the caller graph for this function:

static void zend_closure_free_storage ( void *object  TSRMLS_DC) [static]

Definition at line 168 of file zend_closures.c.

{
       zend_closure *closure = (zend_closure *)object;

       zend_object_std_dtor(&closure->std TSRMLS_CC);

       if (closure->func.type == ZEND_USER_FUNCTION) {
              zend_execute_data *ex = EG(current_execute_data);
              while (ex) {
                     if (ex->op_array == &closure->func.op_array) {
                            zend_error(E_ERROR, "Cannot destroy active lambda function");
                     }
                     ex = ex->prev_execute_data;
              }
              destroy_op_array(&closure->func.op_array TSRMLS_CC);
       }

       if (closure->debug_info != NULL) {
              zend_hash_destroy(closure->debug_info);
              efree(closure->debug_info);
       }

       efree(closure);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int zend_closure_get_closure ( zval *  obj,
zend_class_entry **  ce_ptr,
zend_function **  fptr_ptr,
zval **zobj_ptr  TSRMLS_DC 
)

Definition at line 211 of file zend_closures.c.

{
       zend_closure *closure;

       if (Z_TYPE_P(obj) != IS_OBJECT) {
              return FAILURE;
       }

       closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
       *fptr_ptr = &closure->func;

       if (zobj_ptr) {
              *zobj_ptr = NULL;
       }
       *ce_ptr = NULL;
       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static zend_function* zend_closure_get_constructor ( zval *object  TSRMLS_DC) [static]

Definition at line 78 of file zend_closures.c.

{
       zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed");
       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static HashTable* zend_closure_get_debug_info ( zval *  object,
int *is_temp  TSRMLS_DC 
) [static]

Definition at line 230 of file zend_closures.c.

{
       zend_closure *closure = (zend_closure *)zend_object_store_get_object(object TSRMLS_CC);
       zval *val;
       struct _zend_arg_info *arg_info = closure->func.common.arg_info;

       *is_temp = 0;

       if (closure->debug_info == NULL) {
              ALLOC_HASHTABLE(closure->debug_info);
              zend_hash_init(closure->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
       }
       if (closure->debug_info->nApplyCount == 0) {
              if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) {
                     HashTable *static_variables = closure->func.op_array.static_variables;
                     MAKE_STD_ZVAL(val);
                     array_init(val);
                     zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*));
                     zend_symtable_update(closure->debug_info, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL);
              }

              if (arg_info) {
                     zend_uint i, required = closure->func.common.required_num_args;

                     MAKE_STD_ZVAL(val);
                     array_init(val);

                     for (i = 0; i < closure->func.common.num_args; i++) {
                            char *name, *info;
                            int name_len, info_len;
                            if (arg_info->name) {
                                   name_len = zend_spprintf(&name, 0, "%s$%s",
                                                               arg_info->pass_by_reference ? "&" : "",
                                                               arg_info->name);
                            } else {
                                   name_len = zend_spprintf(&name, 0, "%s$param%d",
                                                               arg_info->pass_by_reference ? "&" : "",
                                                               i + 1);
                            }
                            info_len = zend_spprintf(&info, 0, "%s",
                                                        i >= required ? "<optional>" : "<required>");
                            add_assoc_stringl_ex(val, name, name_len + 1, info, info_len, 0);
                            efree(name);
                            arg_info++;
                     }
                     zend_symtable_update(closure->debug_info, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL);
              }
       }

       return closure->debug_info;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static zend_function* zend_closure_get_method ( zval **  object_ptr,
char *  method_name,
int method_len  TSRMLS_DC 
) [static]

Definition at line 114 of file zend_closures.c.

{
       char *lc_name;
       ALLOCA_FLAG(use_heap)

       lc_name = do_alloca(method_len + 1, use_heap);
       zend_str_tolower_copy(lc_name, method_name, method_len);
       if ((method_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) &&
              memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
       ) {
              free_alloca(lc_name, use_heap);
              return zend_get_closure_invoke_method(*object_ptr TSRMLS_CC);
       }
       free_alloca(lc_name, use_heap);
       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static HashTable* zend_closure_get_properties ( zval *obj  TSRMLS_DC) [static]

Definition at line 283 of file zend_closures.c.

{
       zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);       

       if (GC_G(gc_active)) {
              return (closure->func.type == ZEND_USER_FUNCTION) ? closure->func.op_array.static_variables : NULL;
       }

       return closure->std.properties;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static zval** zend_closure_get_property_ptr_ptr ( zval *  object,
zval *member  TSRMLS_DC 
) [static]

Definition at line 146 of file zend_closures.c.

Here is the caller graph for this function:

static int zend_closure_has_property ( zval *  object,
zval *  member,
int has_set_exists  TSRMLS_DC 
) [static]

Definition at line 153 of file zend_closures.c.

{
       if (has_set_exists != 2) {
              ZEND_CLOSURE_PROPERTY_ERROR();
       }
       return 0;
}

Here is the caller graph for this function:

static zend_object_value zend_closure_new ( zend_class_entry *class_type  TSRMLS_DC) [static]

Definition at line 194 of file zend_closures.c.

{
       zend_closure *closure;
       zend_object_value object;

       closure = emalloc(sizeof(zend_closure));
       memset(closure, 0, sizeof(zend_closure));

       zend_object_std_init(&closure->std, class_type TSRMLS_CC);

       object.handle = zend_objects_store_put(closure, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_closure_free_storage, NULL TSRMLS_CC);
       object.handlers = &closure_handlers;

       return object;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static zval* zend_closure_read_property ( zval *  object,
zval *  member,
int type  TSRMLS_DC 
) [static]

Definition at line 132 of file zend_closures.c.

{
       ZEND_CLOSURE_PROPERTY_ERROR();
       Z_ADDREF(EG(uninitialized_zval));
       return &EG(uninitialized_zval);
}

Here is the caller graph for this function:

static void zend_closure_unset_property ( zval *  object,
zval *member  TSRMLS_DC 
) [static]

Definition at line 162 of file zend_closures.c.

Here is the caller graph for this function:

static void zend_closure_write_property ( zval *  object,
zval *  member,
zval *value  TSRMLS_DC 
) [static]

Definition at line 140 of file zend_closures.c.

Here is the caller graph for this function:

ZEND_API void zend_create_closure ( zval *  res,
zend_function *func  TSRMLS_DC 
)

Definition at line 380 of file zend_closures.c.

{
       zend_closure *closure;

       object_init_ex(res, zend_ce_closure);

       closure = (zend_closure *)zend_object_store_get_object(res TSRMLS_CC);

       closure->func = *func;
       closure->func.common.prototype = NULL;

       if (closure->func.type == ZEND_USER_FUNCTION) {
              if (closure->func.op_array.static_variables) {
                     HashTable *static_variables = closure->func.op_array.static_variables;

                     ALLOC_HASHTABLE(closure->func.op_array.static_variables);
                     zend_hash_init(closure->func.op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
                     zend_hash_apply_with_arguments(static_variables TSRMLS_CC, (apply_func_args_t)zval_copy_static_var, 1, closure->func.op_array.static_variables);
              }
              (*closure->func.op_array.refcount)++;
       }

       closure->func.common.scope = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 91 of file zend_closures.c.

Here is the call graph for this function:

Here is the caller graph for this function:

ZEND_API const zend_function* zend_get_closure_method_def ( zval *obj  TSRMLS_DC)

Definition at line 107 of file zend_closures.c.

{
       zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);       
       return &closure->func;
}

Here is the call graph for this function:

Here is the caller graph for this function:

ZEND_METHOD ( Closure  ,
__invoke   
)

Definition at line 47 of file zend_closures.c.

{
       zend_function *func = EG(current_execute_data)->function_state.function;
       zval ***arguments;
       zval *closure_result_ptr = NULL;

       arguments = emalloc(sizeof(zval**) * ZEND_NUM_ARGS());
       if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
              efree(arguments);
              zend_error(E_RECOVERABLE_ERROR, "Cannot get arguments for calling closure");
              RETVAL_FALSE;
       } else if (call_user_function_ex(CG(function_table), NULL, this_ptr, &closure_result_ptr, ZEND_NUM_ARGS(), arguments, 1, NULL TSRMLS_CC) == FAILURE) {
              RETVAL_FALSE;
       } else if (closure_result_ptr) {
              if (Z_ISREF_P(closure_result_ptr) && return_value_ptr) {
                     if (return_value) {
                            zval_ptr_dtor(&return_value);
                     }
                     *return_value_ptr = closure_result_ptr;
              } else {
                     RETVAL_ZVAL(closure_result_ptr, 1, 1);
              }
       }
       efree(arguments);

       /* destruct the function also, then - we have allocated it in get_method */
       efree(func->internal_function.function_name);
       efree(func);
}

Here is the call graph for this function:

ZEND_METHOD ( Closure  ,
__construct   
)

Definition at line 297 of file zend_closures.c.

{
       zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed");
}

Here is the call graph for this function:

static int zval_copy_static_var ( zval **p  TSRMLS_DC,
int  num_args,
va_list  args,
zend_hash_key key 
) [static]

Definition at line 335 of file zend_closures.c.

{
       HashTable *target = va_arg(args, HashTable*);
       zend_bool is_ref;
       zval *tmp;

       if (Z_TYPE_PP(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) {
              is_ref = Z_TYPE_PP(p) & IS_LEXICAL_REF;

              if (!EG(active_symbol_table)) {
                     zend_rebuild_symbol_table(TSRMLS_C);
              }
              if (zend_hash_quick_find(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, (void **) &p) == FAILURE) {
                     if (is_ref) {
                            ALLOC_INIT_ZVAL(tmp);
                            Z_SET_ISREF_P(tmp);
                            zend_hash_quick_add(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), (void**)&p);
                     } else {
                            tmp = EG(uninitialized_zval_ptr);
                            zend_error(E_NOTICE,"Undefined variable: %s", key->arKey);
                     }
              } else {
                     if (is_ref) {
                            SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
                            tmp = *p;
                     } else if (Z_ISREF_PP(p)) {
                            ALLOC_INIT_ZVAL(tmp);
                            *tmp = **p;
                            zval_copy_ctor(tmp);
                            Z_SET_REFCOUNT_P(tmp, 0);
                            Z_UNSET_ISREF_P(tmp);
                     } else {
                            tmp = *p;
                     }
              }
       } else {
              tmp = *p;
       }
       if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), NULL) == SUCCESS) {
              Z_ADDREF_P(tmp);
       }
       return ZEND_HASH_APPLY_KEEP;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Initial value:
 {
       ZEND_ME(Closure, __construct, NULL, ZEND_ACC_PRIVATE)
       {NULL, NULL, NULL}
}

Definition at line 303 of file zend_closures.c.

zend_object_handlers closure_handlers [static]

Definition at line 45 of file zend_closures.c.

ZEND_API zend_class_entry* zend_ce_closure

Definition at line 44 of file zend_closures.c.