Hi Marcus,

very nice work.

Thanks!

The only thing I don't like is the function naming
(“\0__compiled_lambda_FILENAME_N”). Can we drop the \0?

I used \0 because it is already used in two other places:

 1) create_function (run-time lambda functions) uses \0__lambda_N
 2) build_runtime_defined_function_key uses \0 to start function names.

I can drop it if you like; personally, I don't care for either solution
- it's an internal name that *may* leak to userspace in some
circumstances but is never really useful for userspace anyway..

A minor side-note here: I oriented myself at
build_runtime_defined_function_key at the time of writing but I have
noticed a slight discrepancy between function names generated by
build_runtime_defined_function_key and the normal function names: When
stored in the corresponding function_table hash, for runtime defined
function keys it is opline->op1.u.constant.value.str.len, whereas for
normal function names it is »Z_STRLEN_P(...) + 1« and thus including the
*trailing* (not preceding!) \0 in the hash key for normal function names
but not including it for runtime defined function keys. Any idea why
that is the case? [For the record: I'm refering to the code that is
already used in PHP, not to my patch!]

Or did you use the \0 prefix to prevent direct invocations?

No, direct invocations are prevented by the is_lambda == 1 &&
is_closure == 0 check.

I think the best option would be to force lambda functions being public
always.

They are. If you look at my modified version of
zend_do_begin_function_declaration, you will see that:

if (is_lambda && CG(active_class_entry)) {
        is_method = 1;
        fn_flags = ZEND_ACC_PUBLIC;
        if (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) {
                fn_flags |= ZEND_ACC_STATIC;
        }
} else if (is_lambda) {
        fn_flags = 0;
}

The only attribute that is "inherited" from the parent function is
whether that function is static or not.

The last question is about changing visibility and overriding
functions, do we want that, or should we mark lamdas as final?

Internal representations of lambda fuctions should never be overridden, so yes, ZEND_ACC_FINAL would probably be a good idea. Overriding them won't work anyway since the new opcode that "instantiates" a closure will always use the class in which the closure was defined to look it up.

I'll add that.

Actually how does it integrate with reflection?

Good question, I will investigate that and come back to you.

Comments about the implementation:

- ZendEngine2/zend_compile.c:

  Why provide forward declaration for free_filename(), simply putting the
  new function above the first user avoids it and does the same with
  increased maintainability.

  s/static void add_lexical_var (/static void add_lexical_var(/

Ok, I will fix that.

Regards,
Christian

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to