diff --git a/Library/Compiler.php b/Library/Compiler.php index 1b77c59da1..a3e096427b 100755 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -30,7 +30,7 @@ */ class Compiler { - const VERSION = '0.5.6a'; + const VERSION = '0.5.7a'; /** * @var CompilerFile[] diff --git a/Library/Expression.php b/Library/Expression.php index 72b6ea0a6b..e76c276f78 100644 --- a/Library/Expression.php +++ b/Library/Expression.php @@ -635,6 +635,9 @@ public function compile(CompilationContext $compilationContext) $closure->setExpectReturn($this->_expecting, $this->_expectingVariable); return $closure->compile($expression, $compilationContext); + case 'closure-arrow': + return new LiteralCompiledExpression('null', null, $expression); + default: throw new CompilerException("Unknown expression: " . $type, $expression); } diff --git a/ext/php_test.h b/ext/php_test.h index 4fda9d72b2..1873cb477e 100644 --- a/ext/php_test.h +++ b/ext/php_test.h @@ -10,7 +10,7 @@ #define PHP_TEST_VERSION "1.0.0" #define PHP_TEST_EXTNAME "test" #define PHP_TEST_AUTHOR "Zephir Team and contributors" -#define PHP_TEST_ZEPVERSION "0.5.6a" +#define PHP_TEST_ZEPVERSION "0.5.7a" #define PHP_TEST_DESCRIPTION "Description test for
Test Extension" typedef struct _zephir_struct_test { diff --git a/ext/test/closures.zep.c b/ext/test/closures.zep.c index 95defbd523..00510e07d1 100644 --- a/ext/test/closures.zep.c +++ b/ext/test/closures.zep.c @@ -63,3 +63,17 @@ PHP_METHOD(Test_Closures, simple5) { } +PHP_METHOD(Test_Closures, arrow1) { + + + RETURN_NULL(); + +} + +PHP_METHOD(Test_Closures, arrow2) { + + + RETURN_NULL(); + +} + diff --git a/ext/test/closures.zep.h b/ext/test/closures.zep.h index 45bd86b4c9..a7c59008f1 100644 --- a/ext/test/closures.zep.h +++ b/ext/test/closures.zep.h @@ -8,6 +8,8 @@ PHP_METHOD(Test_Closures, simple2); PHP_METHOD(Test_Closures, simple3); PHP_METHOD(Test_Closures, simple4); PHP_METHOD(Test_Closures, simple5); +PHP_METHOD(Test_Closures, arrow1); +PHP_METHOD(Test_Closures, arrow2); ZEPHIR_INIT_FUNCS(test_closures_method_entry) { PHP_ME(Test_Closures, simple1, NULL, ZEND_ACC_PUBLIC) @@ -15,5 +17,7 @@ ZEPHIR_INIT_FUNCS(test_closures_method_entry) { PHP_ME(Test_Closures, simple3, NULL, ZEND_ACC_PUBLIC) PHP_ME(Test_Closures, simple4, NULL, ZEND_ACC_PUBLIC) PHP_ME(Test_Closures, simple5, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Test_Closures, arrow1, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Test_Closures, arrow2, NULL, ZEND_ACC_PUBLIC) PHP_FE_END }; diff --git a/parser/base.c b/parser/base.c index e71cd7753a..0629f96860 100644 --- a/parser/base.c +++ b/parser/base.c @@ -158,6 +158,10 @@ int xx_parse_program(char *program, unsigned int program_length, char *file_path state->active_file = file_path; state->active_line = 1; state->active_char = 1; + state->class_line = 0; + state->class_char = 0; + state->method_line = 0; + state->method_char = 0; state->end = state->start; @@ -359,6 +363,9 @@ int xx_parse_program(char *program, unsigned int program_length, char *file_path case XX_T_ARROW: xx_(xx_parser, XX_ARROW, NULL, parser_status); break; + case XX_T_DOUBLEARROW: + xx_(xx_parser, XX_DOUBLEARROW, NULL, parser_status); + break; case XX_T_DOUBLECOLON: xx_(xx_parser, XX_DOUBLECOLON, NULL, parser_status); break; diff --git a/parser/parser.h b/parser/parser.h index c0833e1e18..25ed45e01b 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -5,115 +5,116 @@ #define XX_SCOPED 5 #define XX_COMMA 6 #define XX_REQUIRE 7 -#define XX_QUESTION 8 -#define XX_LIKELY 9 -#define XX_UNLIKELY 10 -#define XX_OR 11 -#define XX_AND 12 -#define XX_INSTANCEOF 13 -#define XX_BITWISE_OR 14 -#define XX_BITWISE_AND 15 -#define XX_BITWISE_XOR 16 -#define XX_BITWISE_SHIFTLEFT 17 -#define XX_BITWISE_SHIFTRIGHT 18 -#define XX_EQUALS 19 -#define XX_IDENTICAL 20 -#define XX_LESS 21 -#define XX_GREATER 22 -#define XX_LESSEQUAL 23 -#define XX_GREATEREQUAL 24 -#define XX_NOTIDENTICAL 25 -#define XX_NOTEQUALS 26 -#define XX_ADD 27 -#define XX_SUB 28 -#define XX_CONCAT 29 -#define XX_MUL 30 -#define XX_DIV 31 -#define XX_MOD 32 -#define XX_ISSET 33 -#define XX_FETCH 34 -#define XX_EMPTY 35 -#define XX_TYPEOF 36 -#define XX_CLONE 37 -#define XX_NEW 38 -#define XX_NOT 39 -#define XX_PARENTHESES_CLOSE 40 -#define XX_SBRACKET_OPEN 41 -#define XX_ARROW 42 -#define XX_NAMESPACE 43 -#define XX_IDENTIFIER 44 -#define XX_DOTCOMMA 45 -#define XX_USE 46 -#define XX_AS 47 -#define XX_INTERFACE 48 -#define XX_EXTENDS 49 -#define XX_CLASS 50 -#define XX_IMPLEMENTS 51 -#define XX_ABSTRACT 52 -#define XX_FINAL 53 -#define XX_BRACKET_OPEN 54 -#define XX_BRACKET_CLOSE 55 -#define XX_COMMENT 56 -#define XX_ASSIGN 57 -#define XX_CONST 58 -#define XX_CONSTANT 59 -#define XX_FUNCTION 60 -#define XX_PARENTHESES_OPEN 61 -#define XX_INLINE 62 -#define XX_DEPRECATED 63 -#define XX_VOID 64 -#define XX_NULL 65 -#define XX_THIS 66 -#define XX_SBRACKET_CLOSE 67 -#define XX_TYPE_INTEGER 68 -#define XX_TYPE_UINTEGER 69 -#define XX_TYPE_LONG 70 -#define XX_TYPE_ULONG 71 -#define XX_TYPE_CHAR 72 -#define XX_TYPE_UCHAR 73 -#define XX_TYPE_DOUBLE 74 -#define XX_TYPE_BOOL 75 -#define XX_TYPE_STRING 76 -#define XX_TYPE_ARRAY 77 -#define XX_TYPE_VAR 78 -#define XX_TYPE_CALLABLE 79 -#define XX_TYPE_RESOURCE 80 -#define XX_TYPE_OBJECT 81 -#define XX_BREAK 82 -#define XX_CONTINUE 83 -#define XX_IF 84 -#define XX_ELSE 85 -#define XX_ELSEIF 86 -#define XX_SWITCH 87 -#define XX_CASE 88 -#define XX_COLON 89 -#define XX_DEFAULT 90 -#define XX_LOOP 91 -#define XX_WHILE 92 -#define XX_DO 93 -#define XX_TRY 94 -#define XX_CATCH 95 -#define XX_FOR 96 -#define XX_IN 97 -#define XX_REVERSE 98 -#define XX_LET 99 -#define XX_ADDASSIGN 100 -#define XX_SUBASSIGN 101 -#define XX_MULASSIGN 102 -#define XX_DIVASSIGN 103 -#define XX_CONCATASSIGN 104 -#define XX_MODASSIGN 105 -#define XX_STRING 106 -#define XX_DOUBLECOLON 107 -#define XX_INCR 108 -#define XX_DECR 109 -#define XX_ECHO 110 -#define XX_RETURN 111 -#define XX_UNSET 112 -#define XX_THROW 113 -#define XX_INTEGER 114 -#define XX_CHAR 115 -#define XX_DOUBLE 116 -#define XX_TRUE 117 -#define XX_FALSE 118 -#define XX_CBLOCK 119 +#define XX_DOUBLEARROW 8 +#define XX_QUESTION 9 +#define XX_LIKELY 10 +#define XX_UNLIKELY 11 +#define XX_OR 12 +#define XX_AND 13 +#define XX_INSTANCEOF 14 +#define XX_BITWISE_OR 15 +#define XX_BITWISE_AND 16 +#define XX_BITWISE_XOR 17 +#define XX_BITWISE_SHIFTLEFT 18 +#define XX_BITWISE_SHIFTRIGHT 19 +#define XX_EQUALS 20 +#define XX_IDENTICAL 21 +#define XX_LESS 22 +#define XX_GREATER 23 +#define XX_LESSEQUAL 24 +#define XX_GREATEREQUAL 25 +#define XX_NOTIDENTICAL 26 +#define XX_NOTEQUALS 27 +#define XX_ADD 28 +#define XX_SUB 29 +#define XX_CONCAT 30 +#define XX_MUL 31 +#define XX_DIV 32 +#define XX_MOD 33 +#define XX_ISSET 34 +#define XX_FETCH 35 +#define XX_EMPTY 36 +#define XX_TYPEOF 37 +#define XX_CLONE 38 +#define XX_NEW 39 +#define XX_NOT 40 +#define XX_PARENTHESES_CLOSE 41 +#define XX_SBRACKET_OPEN 42 +#define XX_ARROW 43 +#define XX_NAMESPACE 44 +#define XX_IDENTIFIER 45 +#define XX_DOTCOMMA 46 +#define XX_USE 47 +#define XX_AS 48 +#define XX_INTERFACE 49 +#define XX_EXTENDS 50 +#define XX_CLASS 51 +#define XX_IMPLEMENTS 52 +#define XX_ABSTRACT 53 +#define XX_FINAL 54 +#define XX_BRACKET_OPEN 55 +#define XX_BRACKET_CLOSE 56 +#define XX_COMMENT 57 +#define XX_ASSIGN 58 +#define XX_CONST 59 +#define XX_CONSTANT 60 +#define XX_FUNCTION 61 +#define XX_PARENTHESES_OPEN 62 +#define XX_INLINE 63 +#define XX_DEPRECATED 64 +#define XX_VOID 65 +#define XX_NULL 66 +#define XX_THIS 67 +#define XX_SBRACKET_CLOSE 68 +#define XX_TYPE_INTEGER 69 +#define XX_TYPE_UINTEGER 70 +#define XX_TYPE_LONG 71 +#define XX_TYPE_ULONG 72 +#define XX_TYPE_CHAR 73 +#define XX_TYPE_UCHAR 74 +#define XX_TYPE_DOUBLE 75 +#define XX_TYPE_BOOL 76 +#define XX_TYPE_STRING 77 +#define XX_TYPE_ARRAY 78 +#define XX_TYPE_VAR 79 +#define XX_TYPE_CALLABLE 80 +#define XX_TYPE_RESOURCE 81 +#define XX_TYPE_OBJECT 82 +#define XX_BREAK 83 +#define XX_CONTINUE 84 +#define XX_IF 85 +#define XX_ELSE 86 +#define XX_ELSEIF 87 +#define XX_SWITCH 88 +#define XX_CASE 89 +#define XX_COLON 90 +#define XX_DEFAULT 91 +#define XX_LOOP 92 +#define XX_WHILE 93 +#define XX_DO 94 +#define XX_TRY 95 +#define XX_CATCH 96 +#define XX_FOR 97 +#define XX_IN 98 +#define XX_REVERSE 99 +#define XX_LET 100 +#define XX_ADDASSIGN 101 +#define XX_SUBASSIGN 102 +#define XX_MULASSIGN 103 +#define XX_DIVASSIGN 104 +#define XX_CONCATASSIGN 105 +#define XX_MODASSIGN 106 +#define XX_STRING 107 +#define XX_DOUBLECOLON 108 +#define XX_INCR 109 +#define XX_DECR 110 +#define XX_ECHO 111 +#define XX_RETURN 112 +#define XX_UNSET 113 +#define XX_THROW 114 +#define XX_INTEGER 115 +#define XX_CHAR 116 +#define XX_DOUBLE 117 +#define XX_TRUE 118 +#define XX_FALSE 119 +#define XX_CBLOCK 120 diff --git a/parser/parser.lemon b/parser/parser.lemon index f006a1a36e..4eff23b7e3 100644 --- a/parser/parser.lemon +++ b/parser/parser.lemon @@ -33,6 +33,7 @@ %left COMMA . %right REQUIRE . +%right DOUBLEARROW . %right QUESTION . %right LIKELY UNLIKELY . %left OR . @@ -269,8 +270,8 @@ static json_object *xx_ret_class_definition(json_object *properties, json_object } json_object_object_add(ret, "file", json_object_new_string(state->active_file)); - json_object_object_add(ret, "line", json_object_new_int(state->active_line)); - json_object_object_add(ret, "char", json_object_new_int(state->active_char)); + json_object_object_add(ret, "line", json_object_new_int(state->class_line)); + json_object_object_add(ret, "char", json_object_new_int(state->class_char)); return ret; } @@ -383,8 +384,8 @@ static json_object *xx_ret_class_method(json_object *visibility, xx_parser_token } json_object_object_add(ret, "file", json_object_new_string(state->active_file)); - json_object_object_add(ret, "line", json_object_new_int(state->active_line)); - json_object_object_add(ret, "char", json_object_new_int(state->active_char)); + json_object_object_add(ret, "line", json_object_new_int(state->method_line)); + json_object_object_add(ret, "char", json_object_new_int(state->method_char)); return ret; } @@ -2972,6 +2973,11 @@ xx_common_expr(R) ::= FUNCTION PARENTHESES_OPEN xx_parameter_list(L) PARENTHESES R = xx_ret_expr("closure", L, S, NULL, status->scanner_state); } +/** x => x + 1 */ +xx_common_expr(R) ::= IDENTIFIER(I) DOUBLEARROW xx_common_expr(E) . { + R = xx_ret_expr("closure-arrow", xx_ret_literal(XX_T_IDENTIFIER, I, status->scanner_state), E, NULL, status->scanner_state); +} + xx_array_list(R) ::= xx_array_list(L) COMMA xx_array_item(I) . { R = xx_ret_list(L, I); } diff --git a/parser/scanner.h b/parser/scanner.h index c03354493f..6b7ba701cb 100644 --- a/parser/scanner.h +++ b/parser/scanner.h @@ -147,6 +147,7 @@ #define XX_T_MODASSIGN 418 #define XX_T_BITWISE_SHIFTLEFT 419 #define XX_T_BITWISE_SHIFTRIGHT 420 +#define XX_T_DOUBLEARROW 440 #define XX_T_CBLOCK 451 @@ -167,6 +168,10 @@ typedef struct _xx_scanner_state { int mode; unsigned int active_line; unsigned int active_char; + unsigned int class_line; + unsigned int class_char; + unsigned int method_line; + unsigned int method_char; char *active_file; } xx_scanner_state; diff --git a/parser/scanner.re b/parser/scanner.re index b718c02fb8..dde8f20224 100644 --- a/parser/scanner.re +++ b/parser/scanner.re @@ -101,6 +101,8 @@ int xx_get_token(xx_scanner_state *s, xx_scanner_token *token) { 'class' { s->active_char += sizeof("class")-1; + s->class_line = s->active_line; + s->class_char = s->active_char; token->opcode = XX_T_CLASS; return 0; } @@ -167,12 +169,16 @@ int xx_get_token(xx_scanner_state *s, xx_scanner_token *token) { 'function' { s->active_char += sizeof("function")-1; + s->method_line = s->active_line; + s->method_char = s->active_char; token->opcode = XX_T_FUNCTION; return 0; } 'fn' { s->active_char += sizeof("fn")-1; + s->method_line = s->active_line; + s->method_char = s->active_char; token->opcode = XX_T_FUNCTION; return 0; } @@ -799,6 +805,12 @@ int xx_get_token(xx_scanner_state *s, xx_scanner_token *token) { return 0; } + "=>" { + s->active_char += 2; + token->opcode = XX_T_DOUBLEARROW; + return 0; + } + "::" { s->active_char += 2; token->opcode = XX_T_DOUBLECOLON; diff --git a/test/closures.zep b/test/closures.zep index 2a990a1923..5600b085a1 100644 --- a/test/closures.zep +++ b/test/closures.zep @@ -38,4 +38,14 @@ class Closures return null; }; } + + public function arrow1() + { + return x => x + 100; + } + + public function arrow2() + { + return x => (x + 100) + (x * 150); + } } diff --git a/test/statements.zep b/test/statements.zep index 1af4d5a7a0..f3474c09f0 100644 --- a/test/statements.zep +++ b/test/statements.zep @@ -2,33 +2,33 @@ namespace Test; class Statements { - public tmp1 = "test"; + public tmp1 = "test"; - public tmp2 = "test string"; + public tmp2 = "test string"; - public function testElseIf(int num) - { - if num > 0 { - return "more"; - } elseif num == 0 { - return "equal"; - } elseif num == -1 { - return "-1"; - } else { - return "less"; - } - } + public function testElseIf(int num) + { + if num > 0 { + return "more"; + } elseif num == 0 { + return "equal"; + } elseif num == -1 { + return "-1"; + } else { + return "less"; + } + } - public function testPropertyAcccessAvoidTmpReuse() - { - var result1, result2, result3, result4; + public function testPropertyAcccessAvoidTmpReuse() + { + var result1, result2, result3, result4; - let result1 = strpos(this->tmp2, this->tmp1); + let result1 = strpos(this->tmp2, this->tmp1); - let result2 = strpos(this->tmp2, this->tmp1); + let result2 = strpos(this->tmp2, this->tmp1); - let result3 = strpos(this->tmp2, this->tmp1); + let result3 = strpos(this->tmp2, this->tmp1); - let result4 = strpos(this->tmp2, this->tmp1); - } + let result4 = strpos(this->tmp2, this->tmp1); + } }