Skip to content

Commit 90fd3e1

Browse files
author
felipe
committed
- Added class member access on instantiation (e.g. (new foo)->bar()) support
git-svn-id: http://svn.php.net/repository/php/php-src/trunk@318823 c90b9560-bf6c-de11-be94-00142212c4b1
1 parent 81db8ec commit 90fd3e1

7 files changed

+172
-2
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Testing indirect method call and exceptions
3+
--FILE--
4+
<?php
5+
6+
class foo {
7+
public function __construct() {
8+
throw new Exception('foobar');
9+
}
10+
}
11+
12+
try {
13+
$X = (new foo)->Inexistent(3);
14+
} catch (Exception $e) {
15+
var_dump($e->getMessage()); // foobar
16+
}
17+
18+
?>
19+
--EXPECT--
20+
string(6) "foobar"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Indirect method call with chaining
3+
--FILE--
4+
<?php
5+
6+
class foo {
7+
public $x = 'testing';
8+
9+
public function bar() {
10+
return "foo";
11+
}
12+
public function baz() {
13+
return new self;
14+
}
15+
static function xyz() {
16+
}
17+
}
18+
19+
var_dump((new foo())->bar()); // string(3) "foo"
20+
var_dump((new foo())->baz()->x); // string(7) "testing"
21+
var_dump((new foo())->baz()->baz()->bar()); // string(3) "foo"
22+
var_dump((new foo())->xyz()); // NULL
23+
(new foo())->www();
24+
25+
?>
26+
--EXPECTF--
27+
string(3) "foo"
28+
string(7) "testing"
29+
string(3) "foo"
30+
NULL
31+
32+
Fatal error: Call to undefined method foo::www() in %s on line %d
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Testing indirect method call
3+
--FILE--
4+
<?php
5+
6+
class foo {
7+
public $x = 1;
8+
9+
public function getX() {
10+
return $this->x;
11+
}
12+
public function setX($val) {
13+
$this->x = $val;
14+
return $this;
15+
}
16+
}
17+
18+
$X = (new foo)->setX(10)->getX();
19+
var_dump($X); // int(10)
20+
21+
?>
22+
--EXPECT--
23+
int(10)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Indirect method call and cloning
3+
--FILE--
4+
<?php
5+
6+
7+
class bar {
8+
public $z;
9+
10+
public function __construct() {
11+
$this->z = new stdclass;
12+
}
13+
public function getZ() {
14+
return $this->z;
15+
}
16+
}
17+
18+
var_dump(clone (new bar)->z);
19+
var_dump(clone (new bar)->getZ());
20+
21+
?>
22+
--EXPECTF--
23+
object(stdClass)#%d (0) {
24+
}
25+
object(stdClass)#%d (0) {
26+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Testing array dereferencing from instance with ArrayObject
3+
--FILE--
4+
<?php
5+
6+
class foo extends ArrayObject {
7+
public function __construct($arr) {
8+
parent::__construct($arr);
9+
}
10+
}
11+
12+
var_dump( (new foo( array(1, array(4, 5), 3) ))[1][0] ); // int(4)
13+
14+
?>
15+
--EXPECT--
16+
int(4)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Testing indirect property access
3+
--FILE--
4+
<?php
5+
6+
class foo {
7+
public $x = 1;
8+
}
9+
10+
class bar {
11+
public $y = 'foo';
12+
}
13+
14+
$x = 'bar';
15+
16+
$bar = new bar;
17+
18+
var_dump((new bar)->y); // foo
19+
var_dump((new $x)->y); // foo
20+
var_dump((new $bar->y)->x); // 1
21+
22+
?>
23+
--EXPECT--
24+
string(3) "foo"
25+
string(3) "foo"
26+
int(1)

Zend/zend_language_parser.y

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
5050
%}
5151

5252
%pure_parser
53-
%expect 2
53+
%expect 3
5454

5555
%token END 0 "end of file"
5656
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
@@ -694,12 +694,37 @@ non_empty_for_expr:
694694
| expr { $$ = $1; }
695695
;
696696

697+
chaining_method_or_property:
698+
chaining_method_or_property variable_property { $$.EA = $2.EA; }
699+
| variable_property { $$.EA = $1.EA; }
700+
;
701+
702+
chaining_dereference:
703+
chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
704+
| '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); }
705+
;
706+
707+
chaining_instance_call:
708+
chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; }
709+
| chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; }
710+
| chaining_method_or_property { $$ = $1; }
711+
;
712+
713+
instance_call:
714+
/* empty */ { $$ = $0; }
715+
| { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
716+
chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); }
717+
;
718+
719+
new_expr:
720+
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);}
721+
;
722+
697723
expr_without_variable:
698724
T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
699725
| variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
700726
| 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); }
701727
| 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); }
702-
| 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);}
703728
| T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
704729
| 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); }
705730
| 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_without_variable:
746771
| expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
747772
| expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
748773
| '(' expr ')' { $$ = $2; }
774+
| new_expr { $$ = $1; }
775+
| '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; }
749776
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
750777
expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
751778
expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }

0 commit comments

Comments
 (0)