Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-06 Thread David Zülke

On 03.01.2009, at 15:47, Marcus Boerger wrote:


However if that is the intention, then something we might want to look
into in order to make it easier for those people is to fix something
that propbably looks wrong to them. That is binding a closure to a
property outside of the scope of the object does not bind the object
to the this_ptr as it would in case the assignment is done inside the
object scope (a class method). But once again this is somethign to be
fixed whether or not we apply the patch.


Yes, I was actually going to write another reply to one of your last  
mails about exactly that.


Could that be done? I suppose it would be a good idea. However, what  
happens if you do the assignment from inside another class? Or is that  
$this currently not bound in such a case (I suppose it isn't, because  
that would be pretty confusing, but also pretty interesting in terms  
of what you can do with it).


- David

smime.p7s
Description: S/MIME cryptographic signature


Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-04 Thread Johannes Schlüter
Hi,

On Sat, 2009-01-03 at 15:47 +0100, Marcus Boerger wrote:
  I'd say it would be good to concentrate on making 5.3 stable and then
  see how new features are accepted. If users really demand such a
  functionality, when using closures for real life development, we can
  still add it, but that should be done with the time needed to identify
  side-effects and other consequences, not in a rush during holiday season
  after a feature freeze has been announced.
 
 Stable also means stable features and semantics. And that includes trying
 to get rid of inconsistencies.

... fixing one inconsistency by introducing new inconsistencies? 

Like that one:

?php
function foo() {}

$foo = foo; $foo(); // works
$bar = function(){};  // works

$o-foo = foo;$o-foo(); // will not work
$o-bar = function(){}; $o-bar(); // will work
?

And I fear there will be more. Fixing all of them will take time so we
can delay 5.3 for another half year or so (... oh and during that time
we find another thing to change which will need proper invastigation,
too, so we delay again and then we find )

- We should really try to shorten the release cycle, not making it
longer. Which, for 5.3, means we should concentrate on fixing bugs, not
adding features and change the language.

johannes


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



Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-03 Thread Marcus Boerger
Hello Johannes,

Friday, January 2, 2009, 7:16:32 PM, you wrote:

 Hi,

 On Wed, 2008-12-31 at 17:38 +0100, Marcus Boerger wrote:
 So far it is. Yet I as much as you do not like the inconsistency. So I
 spend a little bit on providing the following patch that should do
 what
 you were looking for.

 I thought bout this issue for one day or so, there are three things to
 consider here:

 - the language design question
 - implementation-related things
 - getting 5.3 out

 For the first question I have to say that this is a major change to
 language. Bringing this feature in makes it a mixture of a class-based
 OO model and JavaScript-like class-less OO model. As I tend to read way
 more code than I write I, personally, prefer the clearer class based
 approach.

 Nonetheless there seems to be large support for this, so let's lake a
 deeper look:

 The disadvantage: Calling properties is case sensitive while calling
 methods isn't. But since this has nothign to do with this patch and
 the patch only increases consistency I am all for applying it.

 That's one of the symptoms of the underlying problem we're having: In
 our object implementation methods and properties are kept completely
 separated. Using properties now like methods will have side effects, one
 is described above. I found another one today:

 ?php
 class A {
 public $p;
 public function __construct() {
 $this-p = function() { echo 1; };
 }
 }

 class B extends A {
 private function p() {
 echo 2;
 }
 }

 $a = new A();
 $b = new B();

 $a-p();
 $b-p();
?

 What do you expect? Well, the first call, to $a-p(); works, the second
 one, to $b-p();, doesn't since where accessing the private method
 B::p().

 $ sapi/cli/php test.php
 1
 Fatal error: Call to undefined method B::p() in test.php on line 16

 Depending on your view on this that result can be correct or wrong, it
 might even be wrong in different ways, maybe overwriting $a-p with
 $b-p should be forbidden, maybe it should treat private elements like
 non-existent ones.

 The obvious thing is that it feels like the is-a relationship isn't
 enforced anymore.

First, for properties we already have that anyway. Remember you can add
properties to object instances at any time. So being able to add methods
at any time just reduces one more inconsistency between things. Also
since properties follow a mixture of class based and prototype based
object model we have to respect prototype semantics for the parts where
proptotype model is used. This means when you dynamically add a closure
then this is done in the manner of prototype semantics and needs to follow
it. Thus with a slightly different code the result is perfectly correct:

?php
class A {
// public $p;
}

class B extends A {
private function p() {
echo 2;
}
}

$a = new A();
$b = new B();

$a-p = function() { echo 1; };
$a-p();
$b-p();
?

So this raises the question what the status quo without the patch is:
class Test {
public $func;
function __construct() {
$this-func = function() {
echo __METHOD__ . ()\n;
};
}
private function func() {
echo __METHOD__ . ()\n;
}
}

$o = new Test;
$f = $o-func;
$f();// Test::{closure}()
$o-func();  // Error call to private method...

So apparently we already have the exact issue at hand and we take
precedence in the actual function which in my opinion is a good
choice. And this also is exactly the behavior your example with the
patch applies shows.

To summarize this from my point of view we only get a bit more of
consistency. But for people with a JavaScript background we get a
lot more. As we now support what they are used to and that actually
is a pretty big advantage.

However if that is the intention, then something we might want to look
into in order to make it easier for those people is to fix something
that propbably looks wrong to them. That is binding a closure to a
property outside of the scope of the object does not bind the object
to the this_ptr as it would in case the assignment is done inside the
object scope (a class method). But once again this is somethign to be
fixed whether or not we apply the patch.

 Additionally there are other areas with such conflicts: Reflection
 (ReflectionMethod doesn't work, ReflectionProperty has no hint it's
 executable, ...) and other meta-functionality are obvious, others might
 (and will) be quite hidden.

Reflection now has closure support.

 I guess the only solid way to implement that feature would be by merging
 the property and method tables into an element table so we reduce such
 conflicts -- while that's a major engine and language change. Every
 other approach will have side-effects.

That would mean a major change in language and we should not go that route.

 This leads us to the third consideration: 5.3 is around 1.5 years in
 development now with lots of new 

Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-02 Thread Marcus Boerger
Hello David,

Friday, January 2, 2009, 8:03:22 AM, you wrote:

 Marcus,

 thanks!

 Why is it
 Test::{closure}()
 {closure}()

 and not
 Test::{closure}()
 Test::{closure}()

 in that test, though? Is it because func1() was there from the  
 Engine's POV after the ctor was called? AFAICT, that's the only  
 difference between the two.

No, one is created inside the object instance and one is created outside.
So one has a bound $this pointer while the other has not. And the class
comes from the bound $this. So if there is no bound $this there is no class
and thus the closure becomes a function rather than a method.

marcus

 Cheers,

 - David



 On 01.01.2009, at 17:50, Marcus Boerger wrote:

 Hello David,

  I added test closure_037.phpt to demonstrate this.

 marcus

 Thursday, January 1, 2009, 5:23:08 PM, you wrote:

 Hi folks,

 first of all, thank you Marcus for implementing this. Very cool.

 As for the __get()/__getClosure() stuff, I don't think it's necessary
 or even an issue. One can never simply do $this-
 getOverloadPropertyWithInvoke() anyway, because if the prop is not
 there, a fatal error would be the result. An __isset() call has to be
 made first along with an (instanceof Closure ||
 method_exists('__invoke')) check in userspace code.

 Which brings me to the next question - will
 $method = 'something';
 $bar-$method();
 work? Not sure if it's necessary; just curious for the most part.

 - David


 On 01.01.2009, at 17:06, Marcus Boerger wrote:

 Hello Hannes,

 as discussed online. At the moment we should not have any __get()
 calls during method resolution. The newly updated patch does that
 now. And I think we are now safe to submit.

 In the future we could think of adding __getClosure() which would be
 called to resolve a dynamic closure. But for the moment we do not  
 need
 it badly and the patch with the increased consistency is good  
 enough.

 marcus

 Thursday, January 1, 2009, 4:09:39 PM, you wrote:

 Hello Hannes,

 Wednesday, December 31, 2008, 8:33:43 PM, you wrote:

 On Wed, Dec 31, 2008 at 20:12, Marcus Boerger he...@php.net  
 wrote:
 Hello Lars,

 Wednesday, December 31, 2008, 6:59:08 PM, you wrote:

 Hi Markus,

 have you measured the performance impact in a class with - say -
 ten
 methods? And what to do with __get() and __call()? How are the
 prioritized in the method resolve order?

 Translated into user code we now have:

 public function __zend_call($name, $args) {
 // Added property lookup
 if (isset($this-$name)) {// may call __isset
  $callable = $this-$name;   // may call __get

 Uhmm. I hope I got this wrong as:

 Well yes, there are no __isset() calls unless you call isset() of
 course.

 I have updated the patch and added a test to demonstrate it better
 (closure_036.phpt). I also added debug information to closures
 which makes
 development much easier. The next step is to fix an issue in the
 engine and
 then submit unless there is a bigger issue with this.

 class foo {
 function __isset() {
 return true;
 }
 function __get() {
 return hello world;
 }
 function __call() {
 }
 }

 $foo = new foo;
 $foo-foobar();

 will first execute __isset(), then __get() and then __call()? That
 is
 a major backwards compatibility break, and increases the
 inconsistency
 and decreases readability 10times

 -Hannes




 Best regards,
 Marcus



 Best regards,
 Marcusze2-callable-properties-5.3-20090101-b.diff.txt--
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php





 Best regards,
 Marcusze2-callable-properties-5.3-20090101-d.diff.txtze2-callable- 
 properties-6.0-20090101-d.diff.txt--
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php




Best regards,
 Marcus


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



Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-02 Thread Johannes Schlüter
Hi,

On Wed, 2008-12-31 at 17:38 +0100, Marcus Boerger wrote:
 So far it is. Yet I as much as you do not like the inconsistency. So I
 spend a little bit on providing the following patch that should do
 what
 you were looking for.

I thought bout this issue for one day or so, there are three things to
consider here:

- the language design question
- implementation-related things
- getting 5.3 out

For the first question I have to say that this is a major change to
language. Bringing this feature in makes it a mixture of a class-based
OO model and JavaScript-like class-less OO model. As I tend to read way
more code than I write I, personally, prefer the clearer class based
approach.

Nonetheless there seems to be large support for this, so let's lake a
deeper look:

 The disadvantage: Calling properties is case sensitive while calling
 methods isn't. But since this has nothign to do with this patch and
 the patch only increases consistency I am all for applying it.

That's one of the symptoms of the underlying problem we're having: In
our object implementation methods and properties are kept completely
separated. Using properties now like methods will have side effects, one
is described above. I found another one today:

?php
class A {
public $p;
public function __construct() {
$this-p = function() { echo 1; };
}
}

class B extends A {
private function p() {
echo 2;
}
}

$a = new A();
$b = new B();

$a-p();
$b-p();
?

What do you expect? Well, the first call, to $a-p(); works, the second
one, to $b-p();, doesn't since where accessing the private method
B::p().

$ sapi/cli/php test.php
1
Fatal error: Call to undefined method B::p() in test.php on line 16

Depending on your view on this that result can be correct or wrong, it
might even be wrong in different ways, maybe overwriting $a-p with
$b-p should be forbidden, maybe it should treat private elements like
non-existent ones.

The obvious thing is that it feels like the is-a relationship isn't
enforced anymore.

Additionally there are other areas with such conflicts: Reflection
(ReflectionMethod doesn't work, ReflectionProperty has no hint it's
executable, ...) and other meta-functionality are obvious, others might
(and will) be quite hidden.

I guess the only solid way to implement that feature would be by merging
the property and method tables into an element table so we reduce such
conflicts -- while that's a major engine and language change. Every
other approach will have side-effects.

This leads us to the third consideration: 5.3 is around 1.5 years in
development now with lots of new features. It was announced that we
wanted to go to a beta status to get it out soon (release early,
release often ...) 

I'd say it would be good to concentrate on making 5.3 stable and then
see how new features are accepted. If users really demand such a
functionality, when using closures for real life development, we can
still add it, but that should be done with the time needed to identify
side-effects and other consequences, not in a rush during holiday season
after a feature freeze has been announced.

johannes



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



Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-01 Thread Marcus Boerger
Hello Hannes,

  as discussed online. At the moment we should not have any __get()
calls during method resolution. The newly updated patch does that
now. And I think we are now safe to submit.

In the future we could think of adding __getClosure() which would be
called to resolve a dynamic closure. But for the moment we do not need
it badly and the patch with the increased consistency is good enough.

marcus

Thursday, January 1, 2009, 4:09:39 PM, you wrote:

 Hello Hannes,

 Wednesday, December 31, 2008, 8:33:43 PM, you wrote:

 On Wed, Dec 31, 2008 at 20:12, Marcus Boerger he...@php.net wrote:
 Hello Lars,

 Wednesday, December 31, 2008, 6:59:08 PM, you wrote:

 Hi Markus,

 have you measured the performance impact in a class with - say - ten
 methods? And what to do with __get() and __call()? How are the
 prioritized in the method resolve order?

 Translated into user code we now have:

 public function __zend_call($name, $args) {
  // Added property lookup
  if (isset($this-$name)) {// may call __isset
$callable = $this-$name;   // may call __get

 Uhmm. I hope I got this wrong as:

 Well yes, there are no __isset() calls unless you call isset() of course.

 I have updated the patch and added a test to demonstrate it better
 (closure_036.phpt). I also added debug information to closures which makes
 development much easier. The next step is to fix an issue in the engine and
 then submit unless there is a bigger issue with this.

 class foo {
 function __isset() {
 return true;
 }
 function __get() {
 return hello world;
 }
 function __call() {
 }
 }

 $foo = new foo;
 $foo-foobar();

 will first execute __isset(), then __get() and then __call()? That is
 a major backwards compatibility break, and increases the inconsistency
 and decreases readability 10times

 -Hannes




 Best regards,
  Marcus



Best regards,
 MarcusIndex: Zend/zend_closures.c
===
RCS file: /repository/ZendEngine2/zend_closures.c,v
retrieving revision 1.3.2.17
diff -u -p -d -r1.3.2.17 zend_closures.c
--- Zend/zend_closures.c31 Dec 2008 11:15:31 -  1.3.2.17
+++ Zend/zend_closures.c1 Jan 2009 16:02:14 -
@@ -14,6 +14,7 @@
+--+
| Authors: Christian Seiler chris...@gmx.net |
|  Dmitry Stogov dmi...@zend.com |
+   |  Marcus Boerger he...@php.net  |
+--+
 */
 
@@ -22,6 +23,7 @@
 #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
@@ -222,6 +224,59 @@ int zend_closure_get_closure(zval *obj, 
 }
 /* }}} */
 
+ZEND_API HashTable *zend_closure_get_debug_info(zval *object, int *is_temp 
TSRMLS_DC) /* {{{ */
+{
+   zend_closure *closure = (zend_closure 
*)zend_object_store_get_object(object TSRMLS_CC);
+   HashTable *rv;
+   zval *val;
+   struct _zend_arg_info *arg_info = closure-func.common.arg_info;
+
+   *is_temp = 1;
+   ALLOC_HASHTABLE(rv);
+   zend_hash_init(rv, 1, NULL, ZVAL_PTR_DTOR, 0);
+   val = closure-this_ptr;
+   if (!val) {
+   ALLOC_INIT_ZVAL(val);
+   } else {
+   Z_ADDREF_P(val);
+   }
+   zend_symtable_update(rv, this, sizeof(this), (void *) val, 
sizeof(zval *), NULL);
+   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(rv, static, sizeof(static), (void *) 
val, sizeof(zval *), NULL);
+   }
+
+   if (arg_info) {
+   MAKE_STD_ZVAL(val);
+   array_init(val);
+   zend_uint i, required = closure-func.common.required_num_args;
+   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);
+   }
+   

Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-01 Thread Marcus Boerger
Hello David,

  I added test closure_037.phpt to demonstrate this.

marcus

Thursday, January 1, 2009, 5:23:08 PM, you wrote:

 Hi folks,

 first of all, thank you Marcus for implementing this. Very cool.

 As for the __get()/__getClosure() stuff, I don't think it's necessary  
 or even an issue. One can never simply do $this- 
 getOverloadPropertyWithInvoke() anyway, because if the prop is not  
 there, a fatal error would be the result. An __isset() call has to be  
 made first along with an (instanceof Closure ||  
 method_exists('__invoke')) check in userspace code.

 Which brings me to the next question - will
 $method = 'something';
 $bar-$method();
 work? Not sure if it's necessary; just curious for the most part.

 - David


 On 01.01.2009, at 17:06, Marcus Boerger wrote:

 Hello Hannes,

  as discussed online. At the moment we should not have any __get()
 calls during method resolution. The newly updated patch does that
 now. And I think we are now safe to submit.

 In the future we could think of adding __getClosure() which would be
 called to resolve a dynamic closure. But for the moment we do not need
 it badly and the patch with the increased consistency is good enough.

 marcus

 Thursday, January 1, 2009, 4:09:39 PM, you wrote:

 Hello Hannes,

 Wednesday, December 31, 2008, 8:33:43 PM, you wrote:

 On Wed, Dec 31, 2008 at 20:12, Marcus Boerger he...@php.net wrote:
 Hello Lars,

 Wednesday, December 31, 2008, 6:59:08 PM, you wrote:

 Hi Markus,

 have you measured the performance impact in a class with - say -  
 ten
 methods? And what to do with __get() and __call()? How are the
 prioritized in the method resolve order?

 Translated into user code we now have:

 public function __zend_call($name, $args) {
 // Added property lookup
 if (isset($this-$name)) {// may call __isset
   $callable = $this-$name;   // may call __get

 Uhmm. I hope I got this wrong as:

 Well yes, there are no __isset() calls unless you call isset() of  
 course.

 I have updated the patch and added a test to demonstrate it better
 (closure_036.phpt). I also added debug information to closures  
 which makes
 development much easier. The next step is to fix an issue in the  
 engine and
 then submit unless there is a bigger issue with this.

 class foo {
 function __isset() {
 return true;
 }
 function __get() {
 return hello world;
 }
 function __call() {
 }
 }

 $foo = new foo;
 $foo-foobar();

 will first execute __isset(), then __get() and then __call()? That  
 is
 a major backwards compatibility break, and increases the  
 inconsistency
 and decreases readability 10times

 -Hannes




 Best regards,
 Marcus



 Best regards,
 Marcusze2-callable-properties-5.3-20090101-b.diff.txt--
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php





Best regards,
 MarcusIndex: Zend/zend_object_handlers.c
===
RCS file: /repository/ZendEngine2/zend_object_handlers.c,v
retrieving revision 1.135.2.6.2.22.2.23
diff -u -p -d -r1.135.2.6.2.22.2.23 zend_object_handlers.c
--- Zend/zend_object_handlers.c 31 Dec 2008 11:15:32 -  
1.135.2.6.2.22.2.23
+++ Zend/zend_object_handlers.c 1 Jan 2009 16:48:22 -
@@ -791,6 +791,24 @@ static union _zend_function *zend_std_ge
 
zobj = Z_OBJ_P(object);
if (zend_hash_find(zobj-ce-function_table, lc_method_name, 
method_len+1, (void **)fbc) == FAILURE) {
+   zval **callable, member;
+   zend_property_info *property_info;
+
+   ZVAL_STRINGL(member, method_name, method_len, 0);
+   property_info = zend_get_property_info(zobj-ce, member, 1 
TSRMLS_CC);
+
+   if (property_info  zend_hash_quick_find(zobj-properties, 
property_info-name, property_info-name_length+1, property_info-h, (void **) 
callable) == SUCCESS) {
+   zval *callable_obj;
+   zend_class_entry *ce_ptr;
+
+   if (Z_TYPE_PP(callable) == IS_OBJECT
+Z_OBJ_HANDLER_PP(callable, get_closure)
+Z_OBJ_HANDLER_PP(callable, get_closure)(*callable, 
ce_ptr, fbc, callable_obj TSRMLS_CC) == SUCCESS) {
+   *object_ptr = callable_obj;
+   free_alloca(lc_method_name, use_heap);
+   return fbc;
+   }
+   } 
free_alloca(lc_method_name, use_heap);
if (zobj-ce-__call) {
zend_internal_function *call_user_call = 
emalloc(sizeof(zend_internal_function));
Index: Zend/tests/closure_033.phpt
===
RCS file: Zend/tests/closure_033.phpt
diff -N Zend/tests/closure_033.phpt
--- /dev/null   1 Jan 1970 00:00:00 -
+++ Zend/tests/closure_033.phpt 1 Jan 2009 16:48:23 -
@@ -0,0 +1,122 @@
+--TEST--
+Closure 033: var_dump() of 

Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2009-01-01 Thread David Zülke

Marcus,

thanks!

Why is it
Test::{closure}()
{closure}()

and not
Test::{closure}()
Test::{closure}()

in that test, though? Is it because func1() was there from the  
Engine's POV after the ctor was called? AFAICT, that's the only  
difference between the two.


Cheers,

- David



On 01.01.2009, at 17:50, Marcus Boerger wrote:


Hello David,

 I added test closure_037.phpt to demonstrate this.

marcus

Thursday, January 1, 2009, 5:23:08 PM, you wrote:


Hi folks,



first of all, thank you Marcus for implementing this. Very cool.



As for the __get()/__getClosure() stuff, I don't think it's necessary
or even an issue. One can never simply do $this-

getOverloadPropertyWithInvoke() anyway, because if the prop is not

there, a fatal error would be the result. An __isset() call has to be
made first along with an (instanceof Closure ||
method_exists('__invoke')) check in userspace code.



Which brings me to the next question - will
$method = 'something';
$bar-$method();
work? Not sure if it's necessary; just curious for the most part.



- David




On 01.01.2009, at 17:06, Marcus Boerger wrote:



Hello Hannes,

as discussed online. At the moment we should not have any __get()
calls during method resolution. The newly updated patch does that
now. And I think we are now safe to submit.

In the future we could think of adding __getClosure() which would be
called to resolve a dynamic closure. But for the moment we do not  
need
it badly and the patch with the increased consistency is good  
enough.


marcus

Thursday, January 1, 2009, 4:09:39 PM, you wrote:


Hello Hannes,



Wednesday, December 31, 2008, 8:33:43 PM, you wrote:


On Wed, Dec 31, 2008 at 20:12, Marcus Boerger he...@php.net  
wrote:

Hello Lars,

Wednesday, December 31, 2008, 6:59:08 PM, you wrote:


Hi Markus,



have you measured the performance impact in a class with - say -
ten
methods? And what to do with __get() and __call()? How are the
prioritized in the method resolve order?


Translated into user code we now have:

public function __zend_call($name, $args) {
// Added property lookup
if (isset($this-$name)) {// may call __isset
 $callable = $this-$name;   // may call __get



Uhmm. I hope I got this wrong as:



Well yes, there are no __isset() calls unless you call isset() of
course.



I have updated the patch and added a test to demonstrate it better
(closure_036.phpt). I also added debug information to closures
which makes
development much easier. The next step is to fix an issue in the
engine and
then submit unless there is a bigger issue with this.



class foo {
function __isset() {
return true;
}
function __get() {
return hello world;
}
function __call() {
}
}



$foo = new foo;
$foo-foobar();



will first execute __isset(), then __get() and then __call()? That
is
a major backwards compatibility break, and increases the
inconsistency
and decreases readability 10times



-Hannes






Best regards,
Marcus




Best regards,
Marcusze2-callable-properties-5.3-20090101-b.diff.txt--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php






Best regards,
Marcusze2-callable-properties-5.3-20090101-d.diff.txtze2-callable- 
properties-6.0-20090101-d.diff.txt--

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



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



[PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2008-12-31 Thread Marcus Boerger
Hello David,

Tuesday, December 23, 2008, 5:02:43 PM, you wrote:

 Hi folks,

 I played with __invoke today:

 class Curry
 {
protected $callable;
protected $args;

public static function create($callable)
{
  $curry = new self($callable, array_slice(func_get_args(), 1));
  return $curry;
}

protected function __construct($callable, $args)
{
  $this-callable = $callable;
  $this-args = $args;
}

public function __invoke()
{
  return call_user_func_array($this-callable, array_merge($this- 
 args, func_get_args()));
}
 }

 However, it doesn't work consistently.

 This works fine:
$d = new DateTime();
$getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
echo $getAtom();

 This gives a fatal Call to undefined method DateTime::getAtom()
$d = new DateTime();
$d-getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
echo $d-getAtom();

 Is that intentional?

So far it is. Yet I as much as you do not like the inconsistency. So I
spend a little bit on providing the following patch that should do what
you were looking for.

The disadvantage: Calling properties is case sensitive while calling
methods isn't. But since this has nothign to do with this patch and the
patch only increases consistency I am all for applying it.

Comments? Lukas/Johannes?

Oh I hate that case insensitivity and inconsistency

 Cheers,

 David





Best regards,
 MarcusIndex: Zend/zend_object_handlers.c
===
RCS file: /repository/ZendEngine2/zend_object_handlers.c,v
retrieving revision 1.135.2.6.2.22.2.23
diff -u -p -d -r1.135.2.6.2.22.2.23 zend_object_handlers.c
--- Zend/zend_object_handlers.c 31 Dec 2008 11:15:32 -  
1.135.2.6.2.22.2.23
+++ Zend/zend_object_handlers.c 31 Dec 2008 16:26:52 -
@@ -791,6 +791,22 @@ static union _zend_function *zend_std_ge
 
zobj = Z_OBJ_P(object);
if (zend_hash_find(zobj-ce-function_table, lc_method_name, 
method_len+1, (void **)fbc) == FAILURE) {
+   if (Z_OBJ_HT_PP(object_ptr)-read_property) {
+   zval *callable, property, *callable_obj;
+   zend_class_entry *ce_ptr;
+   
+   INIT_PZVAL(property);
+   ZVAL_STRINGL(property, method_name, method_len, 0);
+   callable = 
Z_OBJ_HANDLER_PP(object_ptr,read_property)(*object_ptr, property, BP_VAR_IS 
TSRMLS_CC);
+
+   if (Z_TYPE_P(callable) == IS_OBJECT
+Z_OBJ_HANDLER_P(callable, get_closure)
+Z_OBJ_HANDLER_P(callable, get_closure)(callable, 
ce_ptr, fbc, callable_obj TSRMLS_CC) == SUCCESS) {
+   *object_ptr = callable_obj;
+   free_alloca(lc_method_name, use_heap);
+   return fbc;
+   }
+   } 
free_alloca(lc_method_name, use_heap);
if (zobj-ce-__call) {
zend_internal_function *call_user_call = 
emalloc(sizeof(zend_internal_function));
Index: Zend/tests/closure_033.phpt
===
RCS file: Zend/tests/closure_033.phpt
diff -N Zend/tests/closure_033.phpt
--- /dev/null   1 Jan 1970 00:00:00 -
+++ Zend/tests/closure_033.phpt 31 Dec 2008 16:26:52 -
@@ -0,0 +1,31 @@
+--TEST--
+Closure 033: Calling property Closure
+--FILE--
+?php
+
+class Test {
+   public $func;
+   function __construct() {
+   $this-func = function() {
+   echo __METHOD__ . ()\n;
+   };
+   }
+}
+
+$o = new Test;
+ReflectionProperty::export($o, 'func');
+var_dump($o-func);
+$f = $o-func;
+$f();
+$o-func();
+
+?
+===DONE===
+--EXPECTF--
+Property [ default public $func ]
+
+object(Closure)#%d (0) {
+}
+Test::{closure}()
+Test::{closure}()
+===DONE===
Index: Zend/tests/closure_034.phpt
===
RCS file: Zend/tests/closure_034.phpt
diff -N Zend/tests/closure_034.phpt
--- /dev/null   1 Jan 1970 00:00:00 -
+++ Zend/tests/closure_034.phpt 31 Dec 2008 16:26:52 -
@@ -0,0 +1,46 @@
+--TEST--
+Closure 034: Calling property supporting __invoke
+--FILE--
+?php
+
+class Curry
+{
+  protected $callable;
+  protected $args;
+
+  public static function create($callable)
+  {
+$curry = new self($callable, array_slice(func_get_args(), 1));
+return $curry;
+  }
+
+  protected function __construct($callable, $args)
+  {
+$this-callable = $callable;
+$this-args = $args;
+  }
+
+  public function __invoke()
+  {
+return call_user_func_array($this-callable, array_merge($this-args, 
func_get_args()));
+  }
+}
+
+$d = new DateTime();
+$getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
+var_dump(is_Callable($getAtom));
+var_dump($getAtom());
+
+$d = new 

Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2008-12-31 Thread Sebastian Bergmann
Marcus Boerger schrieb:
 Oh I hate that case insensitivity and inconsistency

 I am all for reducing inconsistencies (and not introducing new ones :-).

-- 
Sebastian Bergmann  http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69


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



Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2008-12-31 Thread Lars Strojny
Hi Markus,

have you measured the performance impact in a class with - say - ten
methods? And what to do with __get() and __call()? How are the
prioritized in the method resolve order?

cu, Lars

Am Mittwoch, den 31.12.2008, 17:38 +0100 schrieb Marcus Boerger:
 Hello David,
 
 Tuesday, December 23, 2008, 5:02:43 PM, you wrote:
 
  Hi folks,
 
  I played with __invoke today:
 
  class Curry
  {
 protected $callable;
 protected $args;
 
 public static function create($callable)
 {
   $curry = new self($callable, array_slice(func_get_args(), 1));
   return $curry;
 }
 
 protected function __construct($callable, $args)
 {
   $this-callable = $callable;
   $this-args = $args;
 }
 
 public function __invoke()
 {
   return call_user_func_array($this-callable, array_merge($this- 
  args, func_get_args()));
 }
  }
 
  However, it doesn't work consistently.
 
  This works fine:
 $d = new DateTime();
 $getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
 echo $getAtom();
 
  This gives a fatal Call to undefined method DateTime::getAtom()
 $d = new DateTime();
 $d-getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
 echo $d-getAtom();
 
  Is that intentional?
 
 So far it is. Yet I as much as you do not like the inconsistency. So I
 spend a little bit on providing the following patch that should do what
 you were looking for.
 
 The disadvantage: Calling properties is case sensitive while calling
 methods isn't. But since this has nothign to do with this patch and the
 patch only increases consistency I am all for applying it.
 
 Comments? Lukas/Johannes?
 
 Oh I hate that case insensitivity and inconsistency
 
  Cheers,
 
  David
 
 
 
 
 
 Best regards,
  Marcus
 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, 
 visit: http://www.php.net/unsub.php

-- 
   Jabber: l...@strojny.net
   Weblog: http://usrportage.de


signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil


Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2008-12-31 Thread Marcus Boerger
Hello Lars,

Wednesday, December 31, 2008, 6:59:08 PM, you wrote:

 Hi Markus,

 have you measured the performance impact in a class with - say - ten
 methods? And what to do with __get() and __call()? How are the
 prioritized in the method resolve order?

Translated into user code we now have:

public function __zend_call($name, $args) {
  // Added property lookup
  if (isset($this-$name)) {// may call __isset
$callable = $this-$name;   // may call __get
if (is_callable($callable)) {
  return call_user_func_array($callable, $args);
}
  }
  // Original behavior:
  // Check for __call
  if (method_exists($this, '__call')) {
return $this-__call($name, $args);
  }
  // error
  error_log('Function ' . __CLASS__ . '::' . $name . ' not found');
  return NULL;
}

As to the performance impact. We add one additional hash-lookup per
method call on a default class for a non found function. So whenever
we would normally call __call we add an additional lookup.

 cu, Lars

 Am Mittwoch, den 31.12.2008, 17:38 +0100 schrieb Marcus Boerger:
 Hello David,
 
 Tuesday, December 23, 2008, 5:02:43 PM, you wrote:
 
  Hi folks,
 
  I played with __invoke today:
 
  class Curry
  {
 protected $callable;
 protected $args;
 
 public static function create($callable)
 {
   $curry = new self($callable, array_slice(func_get_args(), 1));
   return $curry;
 }
 
 protected function __construct($callable, $args)
 {
   $this-callable = $callable;
   $this-args = $args;
 }
 
 public function __invoke()
 {
   return call_user_func_array($this-callable, array_merge($this- 
  args, func_get_args()));
 }
  }
 
  However, it doesn't work consistently.
 
  This works fine:
 $d = new DateTime();
 $getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
 echo $getAtom();
 
  This gives a fatal Call to undefined method DateTime::getAtom()
 $d = new DateTime();
 $d-getAtom = Curry::create(array($d, 'format'), DATE_ATOM);
 echo $d-getAtom();
 
  Is that intentional?
 
 So far it is. Yet I as much as you do not like the inconsistency. So I
 spend a little bit on providing the following patch that should do what
 you were looking for.
 
 The disadvantage: Calling properties is case sensitive while calling
 methods isn't. But since this has nothign to do with this patch and the
 patch only increases consistency I am all for applying it.
 
 Comments? Lukas/Johannes?
 
 Oh I hate that case insensitivity and inconsistency
 
  Cheers,
 
  David
 
 
 
 
 
 Best regards,
  Marcus
 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, 
 visit: http://www.php.net/unsub.php




Best regards,
 Marcus


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



Re: [PHP-DEV] [RFC] Re: [PHP-DEV] __invoke() weirdness

2008-12-31 Thread Hannes Magnusson
On Wed, Dec 31, 2008 at 20:12, Marcus Boerger he...@php.net wrote:
 Hello Lars,

 Wednesday, December 31, 2008, 6:59:08 PM, you wrote:

 Hi Markus,

 have you measured the performance impact in a class with - say - ten
 methods? And what to do with __get() and __call()? How are the
 prioritized in the method resolve order?

 Translated into user code we now have:

 public function __zend_call($name, $args) {
  // Added property lookup
  if (isset($this-$name)) {// may call __isset
$callable = $this-$name;   // may call __get

Uhmm. I hope I got this wrong as:

class foo {
function __isset() {
return true;
}
function __get() {
return hello world;
}
function __call() {
}
}

$foo = new foo;
$foo-foobar();

will first execute __isset(), then __get() and then __call()? That is
a major backwards compatibility break, and increases the inconsistency
and decreases readability 10times

-Hannes

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