Skip to content

Commit

Permalink
Merge pull request #69 from phalcon/feature/closure-use
Browse files Browse the repository at this point in the history
Added support for "use" keyword in closures
  • Loading branch information
sergeyklay authored Apr 24, 2019
2 parents 5eb10f1 + 5b6bada commit 0339ec2
Show file tree
Hide file tree
Showing 11 changed files with 6,061 additions and 3,896 deletions.
2 changes: 1 addition & 1 deletion .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ init:

install:
- ps: (new-object Net.WebClient).DownloadString($Env:PHP_AVM) | iex
- ps: $ErrorActionPreference = "Continue";

- ps: InstallPhpSdk $Env:PHP_SDK_VERSION $Env:VC_VERSION $Env:PLATFORM
- ps: InstallPhp $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM
- ps: InstallPhpDevPack $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Added support for "use" keyword in closures
[phalcon/zephir#1848]https://github.com/phalcon/zephir/issues/1848
[phalcon/zephir#888]https://github.com/phalcon/zephir/issues/888

### Fixed
- Fixed unicode support in the source code
[#62](https://github.com/phalcon/php-zephir-parser/issues/62),
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ namespace Acme;

class Greeting
{
public static function say() -> void
public static function sayHello() -> void
{
echo "hello world!";
echo "Hello, World!";
}
}
EOF;
Expand Down
7,984 changes: 4,102 additions & 3,882 deletions parser/parser.c

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,29 @@ static void xx_ret_expr(zval *ret, const char *type, zval *left, zval *right, zv
parser_add_int(ret, "char", state->active_char);
}

static void xx_ret_closure(zval *ret, zval *left, zval *right, zval *use, xx_scanner_state *state)
{
array_init(ret);

parser_add_str(ret, "type", "closure");

if (left) {
parser_add_zval(ret, "left", left);
}

if (right) {
parser_add_zval(ret, "right", right);
}

if (use) {
parser_add_zval(ret, "use", use);
}

parser_add_str(ret, "file", state->active_file);
parser_add_int(ret, "line", state->active_line);
parser_add_int(ret, "char", state->active_char);
}

static void xx_ret_array_item(zval *ret, zval *key, zval *value, xx_scanner_state *state)
{
array_init(ret);
Expand Down
73 changes: 62 additions & 11 deletions parser/zephir.lemon
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ program ::= xx_language(Q) . {
}

%destructor xx_language {
//zval_ptr_dtor($$);
//efree($$);
if (&$$) {
zval_ptr_dtor(&$$);
}
Expand Down Expand Up @@ -274,6 +272,8 @@ xx_class_def(R) ::= FINAL CLASS IDENTIFIER(I) EXTENDS IDENTIFIER(E) IMPLEMENTS x
xx_ret_class(&R, I, &B, 0, 1, E, &L, status->scanner_state);
}

/* TODO: Add internall class */

xx_class_body(R) ::= BRACKET_OPEN BRACKET_CLOSE . {
ZVAL_UNDEF(&R);
}
Expand Down Expand Up @@ -2091,27 +2091,78 @@ xx_call_parameter(R) ::= IDENTIFIER(I) COLON xx_common_expr(E) . {
xx_ret_call_parameter(&R, I, &E, status->scanner_state);
}

/** empty closure function () { } **/
/* empty closure function () { } */
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN PARENTHESES_CLOSE BRACKET_OPEN BRACKET_CLOSE . {
xx_ret_expr(&R, "closure", NULL, NULL, NULL, status->scanner_state);
xx_ret_closure(&R, NULL, NULL, NULL, status->scanner_state);
}

/* empty closure with "use":
function () use (a, b, c) { } */
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN PARENTHESES_CLOSE USE PARENTHESES_OPEN xx_use_parameter_list(U) PARENTHESES_CLOSE BRACKET_OPEN BRACKET_CLOSE . {
xx_ret_closure(&R, NULL, NULL, &U, status->scanner_state);
}

/** function() { ... }*/
/* function() { ... } */
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN PARENTHESES_CLOSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
xx_ret_expr(&R, "closure", NULL, &S, NULL, status->scanner_state);
xx_ret_closure(&R, NULL, &S, NULL, status->scanner_state);
}

/* function() use (a, b, c) { ... } */
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 . {
xx_ret_closure(&R, NULL, &S, &U, status->scanner_state);
}

/** function(a, b, c) { }*/
/* function(a, b, c) { } */
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN xx_parameter_list(L) PARENTHESES_CLOSE BRACKET_OPEN BRACKET_CLOSE . {
xx_ret_expr(&R, "closure", &L, NULL, NULL, status->scanner_state);
xx_ret_closure(&R, &L, NULL, NULL, status->scanner_state);
}

/* function(a, b, c) use (a, b, c) { } */
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 . {
xx_ret_closure(&R, &L, NULL, &U, status->scanner_state);
}

/** function(a, b, c) { ... }*/
/* function(a, b, c) { ... } */
xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN xx_parameter_list(L) PARENTHESES_CLOSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
xx_ret_expr(&R, "closure", &L, &S, NULL, status->scanner_state);
xx_ret_closure(&R, &L, &S, NULL, status->scanner_state);
}

/* function(a, b, c) use (a, b, c) { ... } */
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 . {
xx_ret_closure(&R, &L, &S, &U, status->scanner_state);
}

/* xx_use_parameter_list */

xx_use_parameter_list(R) ::= xx_use_parameter_list(L) COMMA xx_use_parameter(P) . {
xx_ret_list(&R, &L, &P, status->scanner_state);
}

xx_use_parameter_list(R) ::= xx_use_parameter(P) . {
xx_ret_list(&R, NULL, &P, status->scanner_state);
}

// a
xx_use_parameter(R) ::= IDENTIFIER(I) . {
xx_ret_parameter(&R, 0, NULL, NULL, I, NULL, 0, 0, status->scanner_state);
}

// &a
xx_use_parameter(R) ::= BITWISE_AND IDENTIFIER(I) . {
xx_ret_parameter(&R, 0, NULL, NULL, I, NULL, 0, 1, status->scanner_state);
}

// const a
xx_use_parameter(R) ::= CONST IDENTIFIER(I) . {
xx_ret_parameter(&R, 1, NULL, NULL, I, NULL, 0, 0, status->scanner_state);
}

// const &a
xx_use_parameter(R) ::= CONST BITWISE_AND IDENTIFIER(I) . {
xx_ret_parameter(&R, 1, NULL, NULL, I, NULL, 0, 1, status->scanner_state);
}

/** x => x + 1 */
/* x => x + 1 */
xx_common_expr(R) ::= IDENTIFIER(I) DOUBLEARROW xx_common_expr(E) . {
{
zval identifier;
Expand Down
179 changes: 179 additions & 0 deletions tests/functions/closures/empty_closure.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
--TEST--
Tests empty closure with "use"
--SKIPIF--
<?php include(__DIR__ . '/../../skipif.inc'); ?>
--FILE--
<?php

$code =<<<ZEP
namespace Example;
class Closure
{
public function callback()
{
var abc = 42;
return function () use (abc) { };
}
}
ZEP;

$ir = zephir_parse_file($code, '(eval code)');

var_dump($ir);
?>
--EXPECT--
array(2) {
[0]=>
array(5) {
["type"]=>
string(9) "namespace"
["name"]=>
string(7) "Example"
["file"]=>
string(11) "(eval code)"
["line"]=>
int(3)
["char"]=>
int(5)
}
[1]=>
array(8) {
["type"]=>
string(5) "class"
["name"]=>
string(7) "Closure"
["abstract"]=>
int(0)
["final"]=>
int(0)
["definition"]=>
array(4) {
["methods"]=>
array(1) {
[0]=>
array(8) {
["visibility"]=>
array(1) {
[0]=>
string(6) "public"
}
["type"]=>
string(6) "method"
["name"]=>
string(8) "callback"
["statements"]=>
array(2) {
[0]=>
array(6) {
["type"]=>
string(7) "declare"
["data-type"]=>
string(8) "variable"
["variables"]=>
array(1) {
[0]=>
array(5) {
["variable"]=>
string(3) "abc"
["expr"]=>
array(5) {
["type"]=>
string(3) "int"
["value"]=>
string(2) "42"
["file"]=>
string(11) "(eval code)"
["line"]=>
int(7)
["char"]=>
int(21)
}
["file"]=>
string(11) "(eval code)"
["line"]=>
int(7)
["char"]=>
int(21)
}
}
["file"]=>
string(11) "(eval code)"
["line"]=>
int(9)
["char"]=>
int(14)
}
[1]=>
array(5) {
["type"]=>
string(6) "return"
["expr"]=>
array(5) {
["type"]=>
string(7) "closure"
["use"]=>
array(1) {
[0]=>
array(9) {
["type"]=>
string(9) "parameter"
["name"]=>
string(3) "abc"
["const"]=>
int(0)
["data-type"]=>
string(8) "variable"
["mandatory"]=>
int(0)
["reference"]=>
int(0)
["file"]=>
string(11) "(eval code)"
["line"]=>
int(9)
["char"]=>
int(36)
}
}
["file"]=>
string(11) "(eval code)"
["line"]=>
int(9)
["char"]=>
int(41)
}
["file"]=>
string(11) "(eval code)"
["line"]=>
int(10)
["char"]=>
int(5)
}
}
["file"]=>
string(11) "(eval code)"
["line"]=>
int(9)
["last-line"]=>
int(11)
["char"]=>
int(23)
}
}
["file"]=>
string(11) "(eval code)"
["line"]=>
int(3)
["char"]=>
int(5)
}
["file"]=>
string(11) "(eval code)"
["line"]=>
int(3)
["char"]=>
int(5)
}
}
Loading

0 comments on commit 0339ec2

Please sign in to comment.