felipe Sun, 06 Nov 2011 13:25:45 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=318823
Log: - Added class member access on instantiation (e.g. (new foo)->bar()) support Changed paths: U php/php-src/branches/PHP_5_4/NEWS U php/php-src/branches/PHP_5_4/UPGRADING A php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt A php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt A php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt A php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt A php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt A php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt U php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y A php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt A php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt A php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt A php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt A php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt A php/php-src/trunk/Zend/tests/indirect_property_access.phpt U php/php-src/trunk/Zend/zend_language_parser.y
Modified: php/php-src/branches/PHP_5_4/NEWS =================================================================== --- php/php-src/branches/PHP_5_4/NEWS 2011-11-06 12:13:29 UTC (rev 318822) +++ php/php-src/branches/PHP_5_4/NEWS 2011-11-06 13:25:45 UTC (rev 318823) @@ -3,6 +3,8 @@ ?? ??? 2011, PHP 5.4.0 RC1 - General improvements: . Changed silent conversion of array to string to produce a notice. (Patrick) + . Added class member access on instantiation (e.g. (new foo)->bar()) support. + (Felipe) - CLI SAPI: . Fixed bug #60112 (If URI does not contain a file, index.php is not served). Modified: php/php-src/branches/PHP_5_4/UPGRADING =================================================================== --- php/php-src/branches/PHP_5_4/UPGRADING 2011-11-06 12:13:29 UTC (rev 318822) +++ php/php-src/branches/PHP_5_4/UPGRADING 2011-11-06 13:25:45 UTC (rev 318823) @@ -461,6 +461,10 @@ $y = "o"; A::{$x.$y.$y}(); +- Class member acces on instantiation: + (new foo)->method() + (new foo)->property + (new foo)[0] =================== 13. Windows support Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_001.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,20 @@ +--TEST-- +Testing indirect method call and exceptions +--FILE-- +<?php + +class foo { + public function __construct() { + throw new Exception('foobar'); + } +} + +try { + $X = (new foo)->Inexistent(3); +} catch (Exception $e) { + var_dump($e->getMessage()); // foobar +} + +?> +--EXPECT-- +string(6) "foobar" Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_002.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,32 @@ +--TEST-- +Indirect method call with chaining +--FILE-- +<?php + +class foo { + public $x = 'testing'; + + public function bar() { + return "foo"; + } + public function baz() { + return new self; + } + static function xyz() { + } +} + +var_dump((new foo())->bar()); // string(3) "foo" +var_dump((new foo())->baz()->x); // string(7) "testing" +var_dump((new foo())->baz()->baz()->bar()); // string(3) "foo" +var_dump((new foo())->xyz()); // NULL +(new foo())->www(); + +?> +--EXPECTF-- +string(3) "foo" +string(7) "testing" +string(3) "foo" +NULL + +Fatal error: Call to undefined method foo::www() in %s on line %d Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_003.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,23 @@ +--TEST-- +Testing indirect method call +--FILE-- +<?php + +class foo { + public $x = 1; + + public function getX() { + return $this->x; + } + public function setX($val) { + $this->x = $val; + return $this; + } +} + +$X = (new foo)->setX(10)->getX(); +var_dump($X); // int(10) + +?> +--EXPECT-- +int(10) Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_004.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,26 @@ +--TEST-- +Indirect method call and cloning +--FILE-- +<?php + + +class bar { + public $z; + + public function __construct() { + $this->z = new stdclass; + } + public function getZ() { + return $this->z; + } +} + +var_dump(clone (new bar)->z); +var_dump(clone (new bar)->getZ()); + +?> +--EXPECTF-- +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_method_call_005.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,16 @@ +--TEST-- +Testing array dereferencing from instance with ArrayObject +--FILE-- +<?php + +class foo extends ArrayObject { + public function __construct($arr) { + parent::__construct($arr); + } +} + +var_dump( (new foo( array(1, array(4, 5), 3) ))[1][0] ); // int(4) + +?> +--EXPECT-- +int(4) Added: php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/indirect_property_access.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,26 @@ +--TEST-- +Testing indirect property access +--FILE-- +<?php + +class foo { + public $x = 1; +} + +class bar { + public $y = 'foo'; +} + +$x = 'bar'; + +$bar = new bar; + +var_dump((new bar)->y); // foo +var_dump((new $x)->y); // foo +var_dump((new $bar->y)->x); // 1 + +?> +--EXPECT-- +string(3) "foo" +string(3) "foo" +int(1) Modified: php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y 2011-11-06 12:13:29 UTC (rev 318822) +++ php/php-src/branches/PHP_5_4/Zend/zend_language_parser.y 2011-11-06 13:25:45 UTC (rev 318823) @@ -50,7 +50,7 @@ %} %pure_parser -%expect 2 +%expect 3 %token END 0 "end of file" %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE @@ -694,12 +694,37 @@ | expr { $$ = $1; } ; +chaining_method_or_property: + chaining_method_or_property variable_property { $$.EA = $2.EA; } + | variable_property { $$.EA = $1.EA; } +; + +chaining_dereference: + chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); } +; + +chaining_instance_call: + chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; } + | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; } + | chaining_method_or_property { $$ = $1; } +; + +instance_call: + /* empty */ { $$ = $0; } + | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); } + chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); } +; + +new_expr: + T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} +; + expr_without_variable: T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); } | variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); } | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); } | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); } - | T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); } | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); } | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); } @@ -746,6 +771,8 @@ | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); } | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); } | '(' expr ')' { $$ = $2; } + | new_expr { $$ = $1; } + | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; } | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); } expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); } Added: php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt =================================================================== --- php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/indirect_method_call_001.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,20 @@ +--TEST-- +Testing indirect method call and exceptions +--FILE-- +<?php + +class foo { + public function __construct() { + throw new Exception('foobar'); + } +} + +try { + $X = (new foo)->Inexistent(3); +} catch (Exception $e) { + var_dump($e->getMessage()); // foobar +} + +?> +--EXPECT-- +string(6) "foobar" Added: php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt =================================================================== --- php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/indirect_method_call_002.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,32 @@ +--TEST-- +Indirect method call with chaining +--FILE-- +<?php + +class foo { + public $x = 'testing'; + + public function bar() { + return "foo"; + } + public function baz() { + return new self; + } + static function xyz() { + } +} + +var_dump((new foo())->bar()); // string(3) "foo" +var_dump((new foo())->baz()->x); // string(7) "testing" +var_dump((new foo())->baz()->baz()->bar()); // string(3) "foo" +var_dump((new foo())->xyz()); // NULL +(new foo())->www(); + +?> +--EXPECTF-- +string(3) "foo" +string(7) "testing" +string(3) "foo" +NULL + +Fatal error: Call to undefined method foo::www() in %s on line %d Added: php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt =================================================================== --- php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/indirect_method_call_003.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,23 @@ +--TEST-- +Testing indirect method call +--FILE-- +<?php + +class foo { + public $x = 1; + + public function getX() { + return $this->x; + } + public function setX($val) { + $this->x = $val; + return $this; + } +} + +$X = (new foo)->setX(10)->getX(); +var_dump($X); // int(10) + +?> +--EXPECT-- +int(10) Added: php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt =================================================================== --- php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/indirect_method_call_004.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,26 @@ +--TEST-- +Indirect method call and cloning +--FILE-- +<?php + + +class bar { + public $z; + + public function __construct() { + $this->z = new stdclass; + } + public function getZ() { + return $this->z; + } +} + +var_dump(clone (new bar)->z); +var_dump(clone (new bar)->getZ()); + +?> +--EXPECTF-- +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} Added: php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt =================================================================== --- php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/indirect_method_call_005.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,16 @@ +--TEST-- +Testing array dereferencing from instance with ArrayObject +--FILE-- +<?php + +class foo extends ArrayObject { + public function __construct($arr) { + parent::__construct($arr); + } +} + +var_dump( (new foo( array(1, array(4, 5), 3) ))[1][0] ); // int(4) + +?> +--EXPECT-- +int(4) Added: php/php-src/trunk/Zend/tests/indirect_property_access.phpt =================================================================== --- php/php-src/trunk/Zend/tests/indirect_property_access.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/indirect_property_access.phpt 2011-11-06 13:25:45 UTC (rev 318823) @@ -0,0 +1,26 @@ +--TEST-- +Testing indirect property access +--FILE-- +<?php + +class foo { + public $x = 1; +} + +class bar { + public $y = 'foo'; +} + +$x = 'bar'; + +$bar = new bar; + +var_dump((new bar)->y); // foo +var_dump((new $x)->y); // foo +var_dump((new $bar->y)->x); // 1 + +?> +--EXPECT-- +string(3) "foo" +string(3) "foo" +int(1) Modified: php/php-src/trunk/Zend/zend_language_parser.y =================================================================== --- php/php-src/trunk/Zend/zend_language_parser.y 2011-11-06 12:13:29 UTC (rev 318822) +++ php/php-src/trunk/Zend/zend_language_parser.y 2011-11-06 13:25:45 UTC (rev 318823) @@ -50,7 +50,7 @@ %} %pure_parser -%expect 2 +%expect 3 %token END 0 "end of file" %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE @@ -694,12 +694,37 @@ | expr { $$ = $1; } ; +chaining_method_or_property: + chaining_method_or_property variable_property { $$.EA = $2.EA; } + | variable_property { $$.EA = $1.EA; } +; + +chaining_dereference: + chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); } +; + +chaining_instance_call: + chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; } + | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; } + | chaining_method_or_property { $$ = $1; } +; + +instance_call: + /* empty */ { $$ = $0; } + | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); } + chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); } +; + +new_expr: + T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} +; + expr_without_variable: T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); } | variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); } | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); } | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); } - | T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); } | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); } | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); } @@ -746,6 +771,8 @@ | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); } | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); } | '(' expr ')' { $$ = $2; } + | new_expr { $$ = $1; } + | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; } | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); } expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php