Skip to content

Commit 0339ec2

Browse files
authored
Merge pull request #69 from phalcon/feature/closure-use
Added support for "use" keyword in closures
2 parents 5eb10f1 + 5b6bada commit 0339ec2

11 files changed

+6061
-3896
lines changed

.appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ init:
7373

7474
install:
7575
- ps: (new-object Net.WebClient).DownloadString($Env:PHP_AVM) | iex
76-
- ps: $ErrorActionPreference = "Continue";
76+
7777
- ps: InstallPhpSdk $Env:PHP_SDK_VERSION $Env:VC_VERSION $Env:PLATFORM
7878
- ps: InstallPhp $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM
7979
- ps: InstallPhpDevPack $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

77
## [Unreleased]
8+
### Added
9+
- Added support for "use" keyword in closures
10+
[phalcon/zephir#1848]https://github.com/phalcon/zephir/issues/1848
11+
[phalcon/zephir#888]https://github.com/phalcon/zephir/issues/888
12+
813
### Fixed
914
- Fixed unicode support in the source code
1015
[#62](https://github.com/phalcon/php-zephir-parser/issues/62),

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ namespace Acme;
109109

110110
class Greeting
111111
{
112-
public static function say() -> void
112+
public static function sayHello() -> void
113113
{
114-
echo "hello world!";
114+
echo "Hello, World!";
115115
}
116116
}
117117
EOF;

parser/parser.c

Lines changed: 4102 additions & 3882 deletions
Large diffs are not rendered by default.

parser/parser.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,29 @@ static void xx_ret_expr(zval *ret, const char *type, zval *left, zval *right, zv
147147
parser_add_int(ret, "char", state->active_char);
148148
}
149149

150+
static void xx_ret_closure(zval *ret, zval *left, zval *right, zval *use, xx_scanner_state *state)
151+
{
152+
array_init(ret);
153+
154+
parser_add_str(ret, "type", "closure");
155+
156+
if (left) {
157+
parser_add_zval(ret, "left", left);
158+
}
159+
160+
if (right) {
161+
parser_add_zval(ret, "right", right);
162+
}
163+
164+
if (use) {
165+
parser_add_zval(ret, "use", use);
166+
}
167+
168+
parser_add_str(ret, "file", state->active_file);
169+
parser_add_int(ret, "line", state->active_line);
170+
parser_add_int(ret, "char", state->active_char);
171+
}
172+
150173
static void xx_ret_array_item(zval *ret, zval *key, zval *value, xx_scanner_state *state)
151174
{
152175
array_init(ret);

parser/zephir.lemon

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@ program ::= xx_language(Q) . {
8585
}
8686

8787
%destructor xx_language {
88-
//zval_ptr_dtor($$);
89-
//efree($$);
9088
if (&$$) {
9189
zval_ptr_dtor(&$$);
9290
}
@@ -274,6 +272,8 @@ xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENTS x
274272
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
275273
}
276274

275+
/* TODO: Add internall class */
276+
277277
xx_class_body(R) ::= BRACKET_OPEN BRACKET_CLOSE . {
278278
ZVAL_UNDEF(&R);
279279
}
@@ -2091,27 +2091,78 @@ xx_call_parameter(R) ::= IDENTIFIER(I) COLON xx_common_expr(E) . {
20912091
xx_ret_call_parameter(&R, I, &E, status->scanner_state);
20922092
}
20932093

2094-
/** empty closure function () { } **/
2094+
/* empty closure function () { } */
20952095
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN PARENTHESES_CLOSE BRACKET_OPEN BRACKET_CLOSE . {
2096-
xx_ret_expr(&R, "closure", NULL, NULL, NULL, status->scanner_state);
2096+
xx_ret_closure(&R, NULL, NULL, NULL, status->scanner_state);
2097+
}
2098+
2099+
/* empty closure with "use":
2100+
function () use (a, b, c) { } */
2101+
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN PARENTHESES_CLOSE USE PARENTHESES_OPEN xx_use_parameter_list(U) PARENTHESES_CLOSE BRACKET_OPEN BRACKET_CLOSE . {
2102+
xx_ret_closure(&R, NULL, NULL, &U, status->scanner_state);
20972103
}
20982104

2099-
/** function() { ... }*/
2105+
/* function() { ... } */
21002106
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN PARENTHESES_CLOSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
2101-
xx_ret_expr(&R, "closure", NULL, &S, NULL, status->scanner_state);
2107+
xx_ret_closure(&R, NULL, &S, NULL, status->scanner_state);
2108+
}
2109+
2110+
/* function() use (a, b, c) { ... } */
2111+
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN PARENTHESES_CLOSE USE PARENTHESES_OPEN xx_use_parameter_list(U) PARENTHESES_CLOSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
2112+
xx_ret_closure(&R, NULL, &S, &U, status->scanner_state);
21022113
}
21032114

2104-
/** function(a, b, c) { }*/
2115+
/* function(a, b, c) { } */
21052116
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN xx_parameter_list(L) PARENTHESES_CLOSE BRACKET_OPEN BRACKET_CLOSE . {
2106-
xx_ret_expr(&R, "closure", &L, NULL, NULL, status->scanner_state);
2117+
xx_ret_closure(&R, &L, NULL, NULL, status->scanner_state);
2118+
}
2119+
2120+
/* function(a, b, c) use (a, b, c) { } */
2121+
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN xx_parameter_list(L) PARENTHESES_CLOSE USE PARENTHESES_OPEN xx_use_parameter_list(U) PARENTHESES_CLOSE BRACKET_OPEN BRACKET_CLOSE . {
2122+
xx_ret_closure(&R, &L, NULL, &U, status->scanner_state);
21072123
}
21082124

2109-
/** function(a, b, c) { ... }*/
2125+
/* function(a, b, c) { ... } */
21102126
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN xx_parameter_list(L) PARENTHESES_CLOSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
2111-
xx_ret_expr(&R, "closure", &L, &S, NULL, status->scanner_state);
2127+
xx_ret_closure(&R, &L, &S, NULL, status->scanner_state);
2128+
}
2129+
2130+
/* function(a, b, c) use (a, b, c) { ... } */
2131+
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN xx_parameter_list(L) PARENTHESES_CLOSE USE PARENTHESES_OPEN xx_use_parameter_list(U) PARENTHESES_CLOSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
2132+
xx_ret_closure(&R, &L, &S, &U, status->scanner_state);
2133+
}
2134+
2135+
/* xx_use_parameter_list */
2136+
2137+
xx_use_parameter_list(R) ::= xx_use_parameter_list(L) COMMA xx_use_parameter(P) . {
2138+
xx_ret_list(&R, &L, &P, status->scanner_state);
2139+
}
2140+
2141+
xx_use_parameter_list(R) ::= xx_use_parameter(P) . {
2142+
xx_ret_list(&R, NULL, &P, status->scanner_state);
2143+
}
2144+
2145+
// a
2146+
xx_use_parameter(R) ::= IDENTIFIER(I) . {
2147+
xx_ret_parameter(&R, 0, NULL, NULL, I, NULL, 0, 0, status->scanner_state);
2148+
}
2149+
2150+
// &a
2151+
xx_use_parameter(R) ::= BITWISE_AND IDENTIFIER(I) . {
2152+
xx_ret_parameter(&R, 0, NULL, NULL, I, NULL, 0, 1, status->scanner_state);
2153+
}
2154+
2155+
// const a
2156+
xx_use_parameter(R) ::= CONST IDENTIFIER(I) . {
2157+
xx_ret_parameter(&R, 1, NULL, NULL, I, NULL, 0, 0, status->scanner_state);
2158+
}
2159+
2160+
// const &a
2161+
xx_use_parameter(R) ::= CONST BITWISE_AND IDENTIFIER(I) . {
2162+
xx_ret_parameter(&R, 1, NULL, NULL, I, NULL, 0, 1, status->scanner_state);
21122163
}
21132164

2114-
/** x => x + 1 */
2165+
/* x => x + 1 */
21152166
xx_common_expr(R) ::= IDENTIFIER(I) DOUBLEARROW xx_common_expr(E) . {
21162167
{
21172168
zval identifier;
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
--TEST--
2+
Tests empty closure with "use"
3+
--SKIPIF--
4+
<?php include(__DIR__ . '/../../skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
8+
$code =<<<ZEP
9+
namespace Example;
10+
11+
class Closure
12+
{
13+
public function callback()
14+
{
15+
var abc = 42;
16+
17+
return function () use (abc) { };
18+
}
19+
}
20+
ZEP;
21+
22+
$ir = zephir_parse_file($code, '(eval code)');
23+
24+
var_dump($ir);
25+
?>
26+
--EXPECT--
27+
array(2) {
28+
[0]=>
29+
array(5) {
30+
["type"]=>
31+
string(9) "namespace"
32+
["name"]=>
33+
string(7) "Example"
34+
["file"]=>
35+
string(11) "(eval code)"
36+
["line"]=>
37+
int(3)
38+
["char"]=>
39+
int(5)
40+
}
41+
[1]=>
42+
array(8) {
43+
["type"]=>
44+
string(5) "class"
45+
["name"]=>
46+
string(7) "Closure"
47+
["abstract"]=>
48+
int(0)
49+
["final"]=>
50+
int(0)
51+
["definition"]=>
52+
array(4) {
53+
["methods"]=>
54+
array(1) {
55+
[0]=>
56+
array(8) {
57+
["visibility"]=>
58+
array(1) {
59+
[0]=>
60+
string(6) "public"
61+
}
62+
["type"]=>
63+
string(6) "method"
64+
["name"]=>
65+
string(8) "callback"
66+
["statements"]=>
67+
array(2) {
68+
[0]=>
69+
array(6) {
70+
["type"]=>
71+
string(7) "declare"
72+
["data-type"]=>
73+
string(8) "variable"
74+
["variables"]=>
75+
array(1) {
76+
[0]=>
77+
array(5) {
78+
["variable"]=>
79+
string(3) "abc"
80+
["expr"]=>
81+
array(5) {
82+
["type"]=>
83+
string(3) "int"
84+
["value"]=>
85+
string(2) "42"
86+
["file"]=>
87+
string(11) "(eval code)"
88+
["line"]=>
89+
int(7)
90+
["char"]=>
91+
int(21)
92+
}
93+
["file"]=>
94+
string(11) "(eval code)"
95+
["line"]=>
96+
int(7)
97+
["char"]=>
98+
int(21)
99+
}
100+
}
101+
["file"]=>
102+
string(11) "(eval code)"
103+
["line"]=>
104+
int(9)
105+
["char"]=>
106+
int(14)
107+
}
108+
[1]=>
109+
array(5) {
110+
["type"]=>
111+
string(6) "return"
112+
["expr"]=>
113+
array(5) {
114+
["type"]=>
115+
string(7) "closure"
116+
["use"]=>
117+
array(1) {
118+
[0]=>
119+
array(9) {
120+
["type"]=>
121+
string(9) "parameter"
122+
["name"]=>
123+
string(3) "abc"
124+
["const"]=>
125+
int(0)
126+
["data-type"]=>
127+
string(8) "variable"
128+
["mandatory"]=>
129+
int(0)
130+
["reference"]=>
131+
int(0)
132+
["file"]=>
133+
string(11) "(eval code)"
134+
["line"]=>
135+
int(9)
136+
["char"]=>
137+
int(36)
138+
}
139+
}
140+
["file"]=>
141+
string(11) "(eval code)"
142+
["line"]=>
143+
int(9)
144+
["char"]=>
145+
int(41)
146+
}
147+
["file"]=>
148+
string(11) "(eval code)"
149+
["line"]=>
150+
int(10)
151+
["char"]=>
152+
int(5)
153+
}
154+
}
155+
["file"]=>
156+
string(11) "(eval code)"
157+
["line"]=>
158+
int(9)
159+
["last-line"]=>
160+
int(11)
161+
["char"]=>
162+
int(23)
163+
}
164+
}
165+
["file"]=>
166+
string(11) "(eval code)"
167+
["line"]=>
168+
int(3)
169+
["char"]=>
170+
int(5)
171+
}
172+
["file"]=>
173+
string(11) "(eval code)"
174+
["line"]=>
175+
int(3)
176+
["char"]=>
177+
int(5)
178+
}
179+
}

0 commit comments

Comments
 (0)