diff options
author | Li Jin <dragon-fly@qq.com> | 2023-06-07 09:42:50 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2023-06-07 09:42:50 +0800 |
commit | 2a3e50752ade96c3b5d6b1103937bef0f6b31157 (patch) | |
tree | f7ae2654ac96009a9e5dbe9667e480cc920a2868 | |
parent | 738154d37dd4ec20b09acd0f9f81601d0dc069ba (diff) | |
download | yuescript-2a3e50752ade96c3b5d6b1103937bef0f6b31157.tar.gz yuescript-2a3e50752ade96c3b5d6b1103937bef0f6b31157.tar.bz2 yuescript-2a3e50752ade96c3b5d6b1103937bef0f6b31157.zip |
add new syntax of in-expression.
-rw-r--r-- | spec/inputs/in_expression.yue | 26 | ||||
-rw-r--r-- | spec/outputs/in_expression.lua | 36 | ||||
-rw-r--r-- | src/.clang-format | 39 | ||||
-rw-r--r-- | src/yuescript/ast.hpp | 3 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 138 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 188 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 21 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 10 |
8 files changed, 351 insertions, 110 deletions
diff --git a/spec/inputs/in_expression.yue b/spec/inputs/in_expression.yue new file mode 100644 index 0000000..2756fe8 --- /dev/null +++ b/spec/inputs/in_expression.yue | |||
@@ -0,0 +1,26 @@ | |||
1 | -a^2 in {1, 2, 3} |> f | ||
2 | |||
3 | a, b = x(...) not in [1, 3], 2 | ||
4 | |||
5 | d = (tb.x.y ...) not in [1, 3] | ||
6 | |||
7 | if a in {1} and b in {2, 3, 4} or c in [1, 10] | ||
8 | print a, b, c | ||
9 | |||
10 | switch val | ||
11 | when 1, 2, 3 | ||
12 | print "1, 2, 3" | ||
13 | |||
14 | when not in (0, 100] | ||
15 | print "not (0 < val <= 100)" | ||
16 | |||
17 | when in [200, 300) | ||
18 | print "200 <= val < 300)" | ||
19 | |||
20 | when not in {333, 444, 555} | ||
21 | print "not 333, 444 or 555" | ||
22 | |||
23 | do return y not in (a, b) | ||
24 | |||
25 | nil | ||
26 | |||
diff --git a/spec/outputs/in_expression.lua b/spec/outputs/in_expression.lua new file mode 100644 index 0000000..061431f --- /dev/null +++ b/spec/outputs/in_expression.lua | |||
@@ -0,0 +1,36 @@ | |||
1 | f((function() | ||
2 | local _val_0 = -a ^ 2 | ||
3 | return 1 == _val_0 or 2 == _val_0 or 3 == _val_0 | ||
4 | end)()) | ||
5 | local a, b = (function(...) | ||
6 | local _val_0 = x(...) | ||
7 | return not (1 <= _val_0 and _val_0 <= 3) | ||
8 | end)(...), 2 | ||
9 | local d | ||
10 | do | ||
11 | local _val_0 = (tb.x.y(...)) | ||
12 | d = not (1 <= _val_0 and _val_0 <= 3) | ||
13 | end | ||
14 | if (1 == a) and (2 == b or 3 == b or 4 == b) or (function() | ||
15 | local _val_0 = c | ||
16 | return 1 <= _val_0 and _val_0 <= 10 | ||
17 | end)() then | ||
18 | print(a, b, c) | ||
19 | end | ||
20 | do | ||
21 | local _exp_0 = val | ||
22 | if 1 == _exp_0 or 2 == _exp_0 or 3 == _exp_0 then | ||
23 | print("1, 2, 3") | ||
24 | elseif not (0 < _exp_0 and _exp_0 <= 100) then | ||
25 | print("not (0 < val <= 100)") | ||
26 | elseif (200 <= _exp_0 and _exp_0 < 300) then | ||
27 | print("200 <= val < 300)") | ||
28 | elseif not (333 == _exp_0 or 444 == _exp_0 or 555 == _exp_0) then | ||
29 | print("not 333, 444 or 555") | ||
30 | end | ||
31 | end | ||
32 | do | ||
33 | local _val_0 = y | ||
34 | return not (a < _val_0 and _val_0 < b) | ||
35 | end | ||
36 | return nil | ||
diff --git a/src/.clang-format b/src/.clang-format index 5d305ae..6b3ad7b 100644 --- a/src/.clang-format +++ b/src/.clang-format | |||
@@ -1,17 +1,24 @@ | |||
1 | # Format Style Options - Created with Clang Power Tools | 1 | # Format Style Options - Created with Clang Power Tools |
2 | --- | 2 | --- |
3 | BasedOnStyle: WebKit | 3 | BasedOnStyle: WebKit |
4 | AllowShortCaseLabelsOnASingleLine: true | 4 | AllowShortCaseLabelsOnASingleLine: true |
5 | AllowShortIfStatementsOnASingleLine: WithoutElse | 5 | AllowShortIfStatementsOnASingleLine: WithoutElse |
6 | AllowShortLoopsOnASingleLine: true | 6 | AllowShortLoopsOnASingleLine: true |
7 | BreakBeforeBraces: Attach | 7 | BreakBeforeBraces: Attach |
8 | Cpp11BracedListStyle: true | 8 | Cpp11BracedListStyle: true |
9 | IndentCaseLabels: true | 9 | IndentCaseLabels: true |
10 | NamespaceIndentation: None | 10 | NamespaceIndentation: None |
11 | SpaceBeforeCpp11BracedList: false | 11 | SpaceBeforeCpp11BracedList: false |
12 | TabWidth: 4 | 12 | TabWidth: 4 |
13 | AlignEscapedNewlines: DontAlign | 13 | AlignEscapedNewlines: DontAlign |
14 | AlwaysBreakBeforeMultilineStrings: true | 14 | AlwaysBreakBeforeMultilineStrings: true |
15 | FixNamespaceComments: true | 15 | FixNamespaceComments: true |
16 | UseTab: Always | 16 | UseTab: Always |
17 | ... | 17 | AlignOperands: AlignAfterOperator |
18 | AllowShortLambdasOnASingleLine: Empty | ||
19 | LambdaBodyIndentation: Signature | ||
20 | AlignAfterOpenBracket: DontAlign | ||
21 | ContinuationIndentWidth: 4 | ||
22 | ObjCBlockIndentWidth: 4 | ||
23 | ConstructorInitializerIndentWidth: 4 | ||
24 | ... | ||
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index 3443c7f..c6da312 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp | |||
@@ -21,6 +21,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||
21 | 21 | ||
22 | namespace parserlib { | 22 | namespace parserlib { |
23 | 23 | ||
24 | using namespace std::string_view_literals; | ||
25 | |||
24 | class ast_node; | 26 | class ast_node; |
25 | template <bool Required, class T> | 27 | template <bool Required, class T> |
26 | class ast_ptr; | 28 | class ast_ptr; |
@@ -50,7 +52,6 @@ struct Counter<0> { | |||
50 | enum { value = Counter<__LINE__ - 1>::value + 1 }; \ | 52 | enum { value = Counter<__LINE__ - 1>::value + 1 }; \ |
51 | } | 53 | } |
52 | 54 | ||
53 | class ast_node; | ||
54 | template <class T> | 55 | template <class T> |
55 | constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type | 56 | constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type |
56 | id(); | 57 | id(); |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 65008fb..acb7221 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -11,16 +11,17 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
11 | #include "yuescript/ast.hpp" | 11 | #include "yuescript/ast.hpp" |
12 | 12 | ||
13 | namespace parserlib { | 13 | namespace parserlib { |
14 | using namespace std::string_view_literals; | ||
15 | 14 | ||
16 | #define AST_LEAF(type) \ | 15 | #define AST_LEAF(type) \ |
17 | COUNTER_INC; \ | 16 | COUNTER_INC; \ |
17 | namespace yue { \ | ||
18 | class type##_t : public ast_node { \ | 18 | class type##_t : public ast_node { \ |
19 | public: \ | 19 | public: \ |
20 | virtual int getId() const override { return COUNTER_READ; } | 20 | virtual int getId() const override { return COUNTER_READ; } |
21 | 21 | ||
22 | #define AST_NODE(type) \ | 22 | #define AST_NODE(type) \ |
23 | COUNTER_INC; \ | 23 | COUNTER_INC; \ |
24 | namespace yue { \ | ||
24 | class type##_t : public ast_container { \ | 25 | class type##_t : public ast_container { \ |
25 | public: \ | 26 | public: \ |
26 | virtual int getId() const override { return COUNTER_READ; } | 27 | virtual int getId() const override { return COUNTER_READ; } |
@@ -34,11 +35,49 @@ using namespace std::string_view_literals; | |||
34 | virtual const std::string_view getName() const override { return name; } \ | 35 | virtual const std::string_view getName() const override { return name; } \ |
35 | } \ | 36 | } \ |
36 | ; \ | 37 | ; \ |
38 | } \ | ||
37 | template <> \ | 39 | template <> \ |
38 | constexpr int id<type##_t>() { return COUNTER_READ; } | 40 | constexpr int id<yue::type##_t>() { return COUNTER_READ; } |
39 | 41 | ||
40 | // clang-format off | 42 | // clang-format off |
41 | 43 | ||
44 | namespace yue { | ||
45 | class ExpListLow_t; | ||
46 | class TableBlock_t; | ||
47 | class Attrib_t; | ||
48 | class SimpleTable_t; | ||
49 | class TableLit_t; | ||
50 | class Assign_t; | ||
51 | class Exp_t; | ||
52 | class VariablePair_t; | ||
53 | class NormalPair_t; | ||
54 | class MetaVariablePair_t; | ||
55 | class MetaNormalPair_t; | ||
56 | class FnArgsDef_t; | ||
57 | class ChainValue_t; | ||
58 | class ExistentialOp_t; | ||
59 | class Block_t; | ||
60 | class Statement_t; | ||
61 | class Body_t; | ||
62 | class AssignableNameList_t; | ||
63 | class StarExp_t; | ||
64 | class CompInner_t; | ||
65 | class AssignableChain_t; | ||
66 | class UnaryExp_t; | ||
67 | class Parens_t; | ||
68 | class MacroName_t; | ||
69 | class String_t; | ||
70 | class ConstValue_t; | ||
71 | class ClassDecl_t; | ||
72 | class UnaryValue_t; | ||
73 | class FunLit_t; | ||
74 | class DefaultValue_t; | ||
75 | class InvokeArgs_t; | ||
76 | class TableBlockIndent_t; | ||
77 | class Macro_t; | ||
78 | class In_t; | ||
79 | } // namespace yue | ||
80 | |||
42 | AST_LEAF(Num) | 81 | AST_LEAF(Num) |
43 | AST_END(Num, "num"sv) | 82 | AST_END(Num, "num"sv) |
44 | 83 | ||
@@ -101,10 +140,6 @@ AST_NODE(NameList) | |||
101 | AST_MEMBER(NameList, &sep, &names) | 140 | AST_MEMBER(NameList, &sep, &names) |
102 | AST_END(NameList, "name_list"sv) | 141 | AST_END(NameList, "name_list"sv) |
103 | 142 | ||
104 | class ExpListLow_t; | ||
105 | class TableBlock_t; | ||
106 | class Attrib_t; | ||
107 | |||
108 | AST_NODE(LocalValues) | 143 | AST_NODE(LocalValues) |
109 | ast_ptr<true, NameList_t> nameList; | 144 | ast_ptr<true, NameList_t> nameList; |
110 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; | 145 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; |
@@ -126,10 +161,6 @@ AST_END(ConstAttrib, "const"sv) | |||
126 | AST_LEAF(CloseAttrib) | 161 | AST_LEAF(CloseAttrib) |
127 | AST_END(CloseAttrib, "close"sv) | 162 | AST_END(CloseAttrib, "close"sv) |
128 | 163 | ||
129 | class SimpleTable_t; | ||
130 | class TableLit_t; | ||
131 | class Assign_t; | ||
132 | |||
133 | AST_NODE(LocalAttrib) | 164 | AST_NODE(LocalAttrib) |
134 | ast_sel<true, ConstAttrib_t, CloseAttrib_t> attrib; | 165 | ast_sel<true, ConstAttrib_t, CloseAttrib_t> attrib; |
135 | ast_ptr<true, Seperator_t> sep; | 166 | ast_ptr<true, Seperator_t> sep; |
@@ -152,8 +183,6 @@ AST_NODE(ImportLiteral) | |||
152 | AST_MEMBER(ImportLiteral, &sep, &inners) | 183 | AST_MEMBER(ImportLiteral, &sep, &inners) |
153 | AST_END(ImportLiteral, "import_literal"sv) | 184 | AST_END(ImportLiteral, "import_literal"sv) |
154 | 185 | ||
155 | class Exp_t; | ||
156 | |||
157 | AST_NODE(ImportFrom) | 186 | AST_NODE(ImportFrom) |
158 | ast_ptr<true, Seperator_t> sep; | 187 | ast_ptr<true, Seperator_t> sep; |
159 | ast_sel_list<true, ColonImportName_t, Variable_t> names; | 188 | ast_sel_list<true, ColonImportName_t, Variable_t> names; |
@@ -161,8 +190,6 @@ AST_NODE(ImportFrom) | |||
161 | AST_MEMBER(ImportFrom, &sep, &names, &exp) | 190 | AST_MEMBER(ImportFrom, &sep, &names, &exp) |
162 | AST_END(ImportFrom, "import_from"sv) | 191 | AST_END(ImportFrom, "import_from"sv) |
163 | 192 | ||
164 | class MacroName_t; | ||
165 | |||
166 | AST_NODE(MacroNamePair) | 193 | AST_NODE(MacroNamePair) |
167 | ast_ptr<true, MacroName_t> key; | 194 | ast_ptr<true, MacroName_t> key; |
168 | ast_ptr<true, MacroName_t> value; | 195 | ast_ptr<true, MacroName_t> value; |
@@ -172,11 +199,6 @@ AST_END(MacroNamePair, "macro_name_pair"sv) | |||
172 | AST_LEAF(ImportAllMacro) | 199 | AST_LEAF(ImportAllMacro) |
173 | AST_END(ImportAllMacro, "import_all_macro"sv) | 200 | AST_END(ImportAllMacro, "import_all_macro"sv) |
174 | 201 | ||
175 | class VariablePair_t; | ||
176 | class NormalPair_t; | ||
177 | class MetaVariablePair_t; | ||
178 | class MetaNormalPair_t; | ||
179 | |||
180 | AST_NODE(ImportTabLit) | 202 | AST_NODE(ImportTabLit) |
181 | ast_ptr<true, Seperator_t> sep; | 203 | ast_ptr<true, Seperator_t> sep; |
182 | ast_sel_list<false, VariablePair_t, NormalPair_t, MacroName_t, MacroNamePair_t, ImportAllMacro_t, Exp_t, MetaVariablePair_t, MetaNormalPair_t> items; | 204 | ast_sel_list<false, VariablePair_t, NormalPair_t, MacroName_t, MacroNamePair_t, ImportAllMacro_t, Exp_t, MetaVariablePair_t, MetaNormalPair_t> items; |
@@ -209,13 +231,9 @@ AST_NODE(ShortTabAppending) | |||
209 | AST_MEMBER(ShortTabAppending, &assign) | 231 | AST_MEMBER(ShortTabAppending, &assign) |
210 | AST_END(ShortTabAppending, "short_table_appending"sv) | 232 | AST_END(ShortTabAppending, "short_table_appending"sv) |
211 | 233 | ||
212 | class FnArgsDef_t; | ||
213 | |||
214 | AST_LEAF(FnArrowBack) | 234 | AST_LEAF(FnArrowBack) |
215 | AST_END(FnArrowBack, "fn_arrow_back"sv) | 235 | AST_END(FnArrowBack, "fn_arrow_back"sv) |
216 | 236 | ||
217 | class ChainValue_t; | ||
218 | |||
219 | AST_NODE(Backcall) | 237 | AST_NODE(Backcall) |
220 | ast_ptr<false, FnArgsDef_t> argsDef; | 238 | ast_ptr<false, FnArgsDef_t> argsDef; |
221 | ast_ptr<true, FnArrowBack_t> arrow; | 239 | ast_ptr<true, FnArrowBack_t> arrow; |
@@ -235,19 +253,12 @@ AST_NODE(ExpList) | |||
235 | AST_MEMBER(ExpList, &sep, &exprs) | 253 | AST_MEMBER(ExpList, &sep, &exprs) |
236 | AST_END(ExpList, "exp_list"sv) | 254 | AST_END(ExpList, "exp_list"sv) |
237 | 255 | ||
238 | class TableBlock_t; | ||
239 | |||
240 | AST_NODE(Return) | 256 | AST_NODE(Return) |
241 | bool allowBlockMacroReturn = false; | 257 | bool allowBlockMacroReturn = false; |
242 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; | 258 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; |
243 | AST_MEMBER(Return, &valueList) | 259 | AST_MEMBER(Return, &valueList) |
244 | AST_END(Return, "return"sv) | 260 | AST_END(Return, "return"sv) |
245 | 261 | ||
246 | class ExistentialOp_t; | ||
247 | class Assign_t; | ||
248 | class Block_t; | ||
249 | class Statement_t; | ||
250 | |||
251 | AST_NODE(With) | 262 | AST_NODE(With) |
252 | ast_ptr<false, ExistentialOp_t> eop; | 263 | ast_ptr<false, ExistentialOp_t> eop; |
253 | ast_ptr<true, ExpList_t> valueList; | 264 | ast_ptr<true, ExpList_t> valueList; |
@@ -263,9 +274,9 @@ AST_NODE(SwitchList) | |||
263 | AST_END(SwitchList, "switch_list"sv) | 274 | AST_END(SwitchList, "switch_list"sv) |
264 | 275 | ||
265 | AST_NODE(SwitchCase) | 276 | AST_NODE(SwitchCase) |
266 | ast_ptr<true, SwitchList_t> valueList; | 277 | ast_sel<true, SwitchList_t, In_t> condition; |
267 | ast_sel<true, Block_t, Statement_t> body; | 278 | ast_sel<true, Block_t, Statement_t> body; |
268 | AST_MEMBER(SwitchCase, &valueList, &body) | 279 | AST_MEMBER(SwitchCase, &condition, &body) |
269 | AST_END(SwitchCase, "switch_case"sv) | 280 | AST_END(SwitchCase, "switch_case"sv) |
270 | 281 | ||
271 | AST_NODE(Switch) | 282 | AST_NODE(Switch) |
@@ -306,8 +317,6 @@ AST_NODE(While) | |||
306 | AST_MEMBER(While, &type, &condition, &body) | 317 | AST_MEMBER(While, &type, &condition, &body) |
307 | AST_END(While, "while"sv) | 318 | AST_END(While, "while"sv) |
308 | 319 | ||
309 | class Body_t; | ||
310 | |||
311 | AST_NODE(Repeat) | 320 | AST_NODE(Repeat) |
312 | ast_ptr<true, Body_t> body; | 321 | ast_ptr<true, Body_t> body; |
313 | ast_ptr<true, Exp_t> condition; | 322 | ast_ptr<true, Exp_t> condition; |
@@ -328,9 +337,6 @@ AST_NODE(For) | |||
328 | AST_MEMBER(For, &varName, &startValue, &stopValue, &stepValue, &body) | 337 | AST_MEMBER(For, &varName, &startValue, &stopValue, &stepValue, &body) |
329 | AST_END(For, "for"sv) | 338 | AST_END(For, "for"sv) |
330 | 339 | ||
331 | class AssignableNameList_t; | ||
332 | class StarExp_t; | ||
333 | |||
334 | AST_NODE(ForEach) | 340 | AST_NODE(ForEach) |
335 | ast_ptr<true, AssignableNameList_t> nameList; | 341 | ast_ptr<true, AssignableNameList_t> nameList; |
336 | ast_sel<true, StarExp_t, ExpList_t> loopValue; | 342 | ast_sel<true, StarExp_t, ExpList_t> loopValue; |
@@ -355,8 +361,6 @@ AST_NODE(Try) | |||
355 | AST_MEMBER(Try, &func, &catchBlock) | 361 | AST_MEMBER(Try, &func, &catchBlock) |
356 | AST_END(Try, "try"sv) | 362 | AST_END(Try, "try"sv) |
357 | 363 | ||
358 | class CompInner_t; | ||
359 | |||
360 | AST_NODE(Comprehension) | 364 | AST_NODE(Comprehension) |
361 | ast_sel<true, Exp_t, Statement_t> value; | 365 | ast_sel<true, Exp_t, Statement_t> value; |
362 | ast_ptr<true, CompInner_t> forLoop; | 366 | ast_ptr<true, CompInner_t> forLoop; |
@@ -400,8 +404,6 @@ AST_NODE(CompInner) | |||
400 | AST_MEMBER(CompInner, &sep, &items) | 404 | AST_MEMBER(CompInner, &sep, &items) |
401 | AST_END(CompInner, "comp_inner"sv) | 405 | AST_END(CompInner, "comp_inner"sv) |
402 | 406 | ||
403 | class TableBlock_t; | ||
404 | |||
405 | AST_NODE(Assign) | 407 | AST_NODE(Assign) |
406 | ast_ptr<true, Seperator_t> sep; | 408 | ast_ptr<true, Seperator_t> sep; |
407 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t> values; | 409 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t> values; |
@@ -423,15 +425,40 @@ AST_END(BinaryOperator, "binary_op"sv) | |||
423 | AST_LEAF(UnaryOperator) | 425 | AST_LEAF(UnaryOperator) |
424 | AST_END(UnaryOperator, "unary_op"sv) | 426 | AST_END(UnaryOperator, "unary_op"sv) |
425 | 427 | ||
426 | class AssignableChain_t; | 428 | AST_LEAF(InRangeOpen) |
429 | AST_END(InRangeOpen, "in_range_open"sv) | ||
430 | |||
431 | AST_LEAF(InRangeClose) | ||
432 | AST_END(InRangeClose, "in_range_close"sv) | ||
433 | |||
434 | AST_LEAF(NotIn) | ||
435 | AST_END(NotIn, "not_in"sv) | ||
436 | |||
437 | AST_NODE(InRange) | ||
438 | ast_sel<true, InRangeOpen_t, InRangeClose_t> open; | ||
439 | ast_ptr<true, Exp_t> openValue; | ||
440 | ast_ptr<true, Exp_t> closeValue; | ||
441 | ast_sel<true, InRangeOpen_t, InRangeClose_t> close; | ||
442 | AST_MEMBER(InRange, &open, &openValue, &closeValue, &close) | ||
443 | AST_END(InRange, "in_range"sv) | ||
444 | |||
445 | AST_NODE(InDiscrete) | ||
446 | ast_ptr<true, Seperator_t> sep; | ||
447 | ast_list<true, Exp_t> values; | ||
448 | AST_MEMBER(InDiscrete, &sep, &values) | ||
449 | AST_END(InDiscrete, "in_discrete"sv) | ||
450 | |||
451 | AST_NODE(In) | ||
452 | ast_ptr<false, NotIn_t> not_; | ||
453 | ast_sel<true, InRange_t, InDiscrete_t> item; | ||
454 | AST_MEMBER(In, ¬_, &item) | ||
455 | AST_END(In, "in"sv) | ||
427 | 456 | ||
428 | AST_NODE(Assignable) | 457 | AST_NODE(Assignable) |
429 | ast_sel<true, AssignableChain_t, Variable_t, SelfItem_t> item; | 458 | ast_sel<true, AssignableChain_t, Variable_t, SelfItem_t> item; |
430 | AST_MEMBER(Assignable, &item) | 459 | AST_MEMBER(Assignable, &item) |
431 | AST_END(Assignable, "assignable"sv) | 460 | AST_END(Assignable, "assignable"sv) |
432 | 461 | ||
433 | class UnaryExp_t; | ||
434 | |||
435 | AST_NODE(ExpOpValue) | 462 | AST_NODE(ExpOpValue) |
436 | ast_ptr<true, BinaryOperator_t> op; | 463 | ast_ptr<true, BinaryOperator_t> op; |
437 | ast_list<true, UnaryExp_t> pipeExprs; | 464 | ast_list<true, UnaryExp_t> pipeExprs; |
@@ -446,9 +473,6 @@ AST_NODE(Exp) | |||
446 | AST_MEMBER(Exp, &sep, &pipeExprs, &opValues, &nilCoalesed) | 473 | AST_MEMBER(Exp, &sep, &pipeExprs, &opValues, &nilCoalesed) |
447 | AST_END(Exp, "exp"sv) | 474 | AST_END(Exp, "exp"sv) |
448 | 475 | ||
449 | class Parens_t; | ||
450 | class MacroName_t; | ||
451 | |||
452 | AST_NODE(Callable) | 476 | AST_NODE(Callable) |
453 | ast_sel<true, Variable_t, SelfItem_t, Parens_t, MacroName_t> item; | 477 | ast_sel<true, Variable_t, SelfItem_t, Parens_t, MacroName_t> item; |
454 | AST_MEMBER(Callable, &item) | 478 | AST_MEMBER(Callable, &item) |
@@ -465,8 +489,6 @@ AST_NODE(VariablePairDef) | |||
465 | AST_MEMBER(VariablePairDef, &pair, &defVal) | 489 | AST_MEMBER(VariablePairDef, &pair, &defVal) |
466 | AST_END(VariablePairDef, "variable_pair_def"sv) | 490 | AST_END(VariablePairDef, "variable_pair_def"sv) |
467 | 491 | ||
468 | class String_t; | ||
469 | |||
470 | AST_NODE(NormalPair) | 492 | AST_NODE(NormalPair) |
471 | ast_sel<true, KeyName_t, Exp_t, String_t> key; | 493 | ast_sel<true, KeyName_t, Exp_t, String_t> key; |
472 | ast_sel<true, Exp_t, TableBlock_t> value; | 494 | ast_sel<true, Exp_t, TableBlock_t> value; |
@@ -515,11 +537,6 @@ AST_NODE(SimpleTable) | |||
515 | AST_MEMBER(SimpleTable, &sep, &pairs) | 537 | AST_MEMBER(SimpleTable, &sep, &pairs) |
516 | AST_END(SimpleTable, "simple_table"sv) | 538 | AST_END(SimpleTable, "simple_table"sv) |
517 | 539 | ||
518 | class ConstValue_t; | ||
519 | class ClassDecl_t; | ||
520 | class UnaryValue_t; | ||
521 | class FunLit_t; | ||
522 | |||
523 | AST_NODE(SimpleValue) | 540 | AST_NODE(SimpleValue) |
524 | ast_sel<true, | 541 | ast_sel<true, |
525 | TableLit_t, ConstValue_t, | 542 | TableLit_t, ConstValue_t, |
@@ -588,8 +605,6 @@ AST_NODE(ColonChainItem) | |||
588 | AST_MEMBER(ColonChainItem, &name) | 605 | AST_MEMBER(ColonChainItem, &name) |
589 | AST_END(ColonChainItem, "colon_chain_item"sv) | 606 | AST_END(ColonChainItem, "colon_chain_item"sv) |
590 | 607 | ||
591 | class DefaultValue_t; | ||
592 | |||
593 | AST_NODE(Slice) | 608 | AST_NODE(Slice) |
594 | ast_sel<true, Exp_t, DefaultValue_t> startValue; | 609 | ast_sel<true, Exp_t, DefaultValue_t> startValue; |
595 | ast_sel<true, Exp_t, DefaultValue_t> stopValue; | 610 | ast_sel<true, Exp_t, DefaultValue_t> stopValue; |
@@ -614,8 +629,6 @@ AST_END(ExistentialOp, "existential_op"sv) | |||
614 | AST_LEAF(TableAppendingOp) | 629 | AST_LEAF(TableAppendingOp) |
615 | AST_END(TableAppendingOp, "table_appending_op"sv) | 630 | AST_END(TableAppendingOp, "table_appending_op"sv) |
616 | 631 | ||
617 | class InvokeArgs_t; | ||
618 | |||
619 | AST_NODE(ChainValue) | 632 | AST_NODE(ChainValue) |
620 | ast_ptr<true, Seperator_t> sep; | 633 | ast_ptr<true, Seperator_t> sep; |
621 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t> items; | 634 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t> items; |
@@ -641,8 +654,6 @@ AST_NODE(SpreadExp) | |||
641 | AST_MEMBER(SpreadExp, &exp) | 654 | AST_MEMBER(SpreadExp, &exp) |
642 | AST_END(SpreadExp, "spread_exp"sv) | 655 | AST_END(SpreadExp, "spread_exp"sv) |
643 | 656 | ||
644 | class TableBlockIndent_t; | ||
645 | |||
646 | AST_NODE(TableLit) | 657 | AST_NODE(TableLit) |
647 | ast_ptr<true, Seperator_t> sep; | 658 | ast_ptr<true, Seperator_t> sep; |
648 | ast_sel_list<false, | 659 | ast_sel_list<false, |
@@ -704,8 +715,6 @@ AST_END(Global, "global"sv) | |||
704 | AST_LEAF(ExportDefault) | 715 | AST_LEAF(ExportDefault) |
705 | AST_END(ExportDefault, "export_default"sv) | 716 | AST_END(ExportDefault, "export_default"sv) |
706 | 717 | ||
707 | class Macro_t; | ||
708 | |||
709 | AST_NODE(Export) | 718 | AST_NODE(Export) |
710 | ast_ptr<false, ExportDefault_t> def; | 719 | ast_ptr<false, ExportDefault_t> def; |
711 | ast_sel<true, ExpList_t, Exp_t, Macro_t, DotChainItem_t> target; | 720 | ast_sel<true, ExpList_t, Exp_t, Macro_t, DotChainItem_t> target; |
@@ -799,7 +808,8 @@ AST_END(UnaryValue, "unary_value"sv) | |||
799 | AST_NODE(UnaryExp) | 808 | AST_NODE(UnaryExp) |
800 | ast_list<false, UnaryOperator_t> ops; | 809 | ast_list<false, UnaryOperator_t> ops; |
801 | ast_list<true, Value_t> expos; | 810 | ast_list<true, Value_t> expos; |
802 | AST_MEMBER(UnaryExp, &ops, &expos) | 811 | ast_ptr<false, In_t> inExp; |
812 | AST_MEMBER(UnaryExp, &ops, &expos, &inExp) | ||
803 | AST_END(UnaryExp, "unary_exp"sv) | 813 | AST_END(UnaryExp, "unary_exp"sv) |
804 | 814 | ||
805 | AST_NODE(ExpListAssign) | 815 | AST_NODE(ExpListAssign) |
@@ -869,8 +879,6 @@ AST_NODE(Statement) | |||
869 | AST_MEMBER(Statement, &sep, &comments, &content, &appendix, &needSep) | 879 | AST_MEMBER(Statement, &sep, &comments, &content, &appendix, &needSep) |
870 | AST_END(Statement, "statement"sv) | 880 | AST_END(Statement, "statement"sv) |
871 | 881 | ||
872 | class Block_t; | ||
873 | |||
874 | AST_NODE(Body) | 882 | AST_NODE(Body) |
875 | ast_sel<true, Block_t, Statement_t> content; | 883 | ast_sel<true, Block_t, Statement_t> content; |
876 | AST_MEMBER(Body, &content) | 884 | AST_MEMBER(Body, &content) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index e0ff9e9..98d19a7 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -72,7 +72,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
72 | "close"s // Lua 5.4 | 72 | "close"s // Lua 5.4 |
73 | }; | 73 | }; |
74 | 74 | ||
75 | const std::string_view version = "0.16.8"sv; | 75 | const std::string_view version = "0.17.0"sv; |
76 | const std::string_view extension = "yue"sv; | 76 | const std::string_view extension = "yue"sv; |
77 | 77 | ||
78 | class CompileError : public std::logic_error { | 78 | class CompileError : public std::logic_error { |
@@ -761,7 +761,7 @@ private: | |||
761 | } | 761 | } |
762 | case id<UnaryExp_t>(): { | 762 | case id<UnaryExp_t>(): { |
763 | auto unary = static_cast<UnaryExp_t*>(item); | 763 | auto unary = static_cast<UnaryExp_t*>(item); |
764 | if (unary->expos.size() == 1) { | 764 | if (unary->expos.size() == 1 && !unary->inExp) { |
765 | return unary; | 765 | return unary; |
766 | } | 766 | } |
767 | return nullptr; | 767 | return nullptr; |
@@ -774,7 +774,7 @@ private: | |||
774 | BREAK_IF(!exp->opValues.empty()); | 774 | BREAK_IF(!exp->opValues.empty()); |
775 | BREAK_IF(exp->pipeExprs.size() != 1); | 775 | BREAK_IF(exp->pipeExprs.size() != 1); |
776 | auto unary = static_cast<UnaryExp_t*>(exp->pipeExprs.back()); | 776 | auto unary = static_cast<UnaryExp_t*>(exp->pipeExprs.back()); |
777 | BREAK_IF(unary->expos.size() != 1); | 777 | BREAK_IF(unary->expos.size() != 1 || unary->inExp); |
778 | return unary; | 778 | return unary; |
779 | BLOCK_END | 779 | BLOCK_END |
780 | return nullptr; | 780 | return nullptr; |
@@ -1028,9 +1028,12 @@ private: | |||
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | std::string singleVariableFrom(ast_node* expList, bool accessing) { | 1030 | std::string singleVariableFrom(ast_node* expList, bool accessing) { |
1031 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; | 1031 | if (!ast_is<Exp_t, ExpList_t, Value_t>(expList)) return Empty; |
1032 | BLOCK_START | 1032 | BLOCK_START |
1033 | auto value = singleValueFrom(expList); | 1033 | auto value = ast_cast<Value_t>(expList); |
1034 | if (!value) { | ||
1035 | value = singleValueFrom(expList); | ||
1036 | } | ||
1034 | BREAK_IF(!value); | 1037 | BREAK_IF(!value); |
1035 | auto chainValue = value->item.as<ChainValue_t>(); | 1038 | auto chainValue = value->item.as<ChainValue_t>(); |
1036 | BREAK_IF(!chainValue); | 1039 | BREAK_IF(!chainValue); |
@@ -1157,6 +1160,24 @@ private: | |||
1157 | return false; | 1160 | return false; |
1158 | } | 1161 | } |
1159 | 1162 | ||
1163 | UnaryExp_t* unaryGeneratingAnonFunc(Exp_t* exp) { | ||
1164 | if (!exp) return nullptr; | ||
1165 | BLOCK_START | ||
1166 | BREAK_IF(exp->nilCoalesed); | ||
1167 | BREAK_IF(!exp->opValues.empty()); | ||
1168 | BREAK_IF(exp->pipeExprs.size() != 1); | ||
1169 | auto unary = static_cast<UnaryExp_t*>(exp->pipeExprs.back()); | ||
1170 | BREAK_IF(unary->expos.size() != 1); | ||
1171 | BREAK_IF(!unary->inExp); | ||
1172 | auto value = static_cast<Value_t*>(unary->expos.back()); | ||
1173 | auto varName = singleVariableFrom(value, false); | ||
1174 | if (varName.empty() || !isLocal(varName)) { | ||
1175 | return unary; | ||
1176 | } | ||
1177 | BLOCK_END | ||
1178 | return nullptr; | ||
1179 | } | ||
1180 | |||
1160 | void pushFunctionScope() { | 1181 | void pushFunctionScope() { |
1161 | _enableReturn.push(true); | 1182 | _enableReturn.push(true); |
1162 | _enableBreakLoop.push(false); | 1183 | _enableBreakLoop.push(false); |
@@ -1971,6 +1992,12 @@ private: | |||
1971 | auto expList = assignment->expList.get(); | 1992 | auto expList = assignment->expList.get(); |
1972 | transformNilCoalesedExp(exp, out, ExpUsage::Assignment, expList); | 1993 | transformNilCoalesedExp(exp, out, ExpUsage::Assignment, expList); |
1973 | return; | 1994 | return; |
1995 | } else if (auto unary = unaryGeneratingAnonFunc(exp)) { | ||
1996 | std::string preDefine = getPreDefineLine(assignment); | ||
1997 | auto expList = assignment->expList.get(); | ||
1998 | transformUnaryExp(unary, out, ExpUsage::Assignment, expList); | ||
1999 | out.back().insert(0, preDefine); | ||
2000 | return; | ||
1974 | } | 2001 | } |
1975 | auto singleVal = singleValueFrom(exp); | 2002 | auto singleVal = singleValueFrom(exp); |
1976 | BREAK_IF(!singleVal); | 2003 | BREAK_IF(!singleVal); |
@@ -3134,7 +3161,7 @@ private: | |||
3134 | 3161 | ||
3135 | void transform_pipe_exp(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 3162 | void transform_pipe_exp(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
3136 | if (values.size() == 1 && usage == ExpUsage::Closure) { | 3163 | if (values.size() == 1 && usage == ExpUsage::Closure) { |
3137 | transform_unary_exp(static_cast<UnaryExp_t*>(values.front()), out); | 3164 | transformUnaryExp(static_cast<UnaryExp_t*>(values.front()), out, ExpUsage::Closure); |
3138 | } else { | 3165 | } else { |
3139 | auto x = values.front(); | 3166 | auto x = values.front(); |
3140 | auto arg = newExp(static_cast<UnaryExp_t*>(x), x); | 3167 | auto arg = newExp(static_cast<UnaryExp_t*>(x), x); |
@@ -3404,7 +3431,7 @@ private: | |||
3404 | void transformSimpleValue(SimpleValue_t* simpleValue, str_list& out) { | 3431 | void transformSimpleValue(SimpleValue_t* simpleValue, str_list& out) { |
3405 | auto value = simpleValue->value.get(); | 3432 | auto value = simpleValue->value.get(); |
3406 | switch (value->getId()) { | 3433 | switch (value->getId()) { |
3407 | case id<ConstValue_t>(): transform_const_value(static_cast<ConstValue_t*>(value), out); break; | 3434 | case id<ConstValue_t>(): transformConstValue(static_cast<ConstValue_t*>(value), out); break; |
3408 | case id<If_t>(): transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break; | 3435 | case id<If_t>(): transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break; |
3409 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; | 3436 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; |
3410 | case id<With_t>(): transformWithClosure(static_cast<With_t*>(value), out); break; | 3437 | case id<With_t>(): transformWithClosure(static_cast<With_t*>(value), out); break; |
@@ -3414,7 +3441,7 @@ private: | |||
3414 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; | 3441 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; |
3415 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; | 3442 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; |
3416 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; | 3443 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; |
3417 | case id<UnaryValue_t>(): transform_unary_value(static_cast<UnaryValue_t*>(value), out); break; | 3444 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; |
3418 | case id<TblComprehension_t>(): transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break; | 3445 | case id<TblComprehension_t>(): transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break; |
3419 | case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out); break; | 3446 | case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out); break; |
3420 | case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break; | 3447 | case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break; |
@@ -4050,6 +4077,9 @@ private: | |||
4050 | } else if (isPureNilCoalesed(exp)) { | 4077 | } else if (isPureNilCoalesed(exp)) { |
4051 | transformNilCoalesedExp(exp, out, ExpUsage::Return); | 4078 | transformNilCoalesedExp(exp, out, ExpUsage::Return); |
4052 | return; | 4079 | return; |
4080 | } else if (auto unary = unaryGeneratingAnonFunc(exp)) { | ||
4081 | transformUnaryExp(unary, out, ExpUsage::Return); | ||
4082 | return; | ||
4053 | } | 4083 | } |
4054 | } | 4084 | } |
4055 | if (auto singleValue = singleValueFrom(valueList)) { | 4085 | if (auto singleValue = singleValueFrom(valueList)) { |
@@ -5363,7 +5393,7 @@ private: | |||
5363 | out.push_back('(' + join(temp, ", "sv) + ')'); | 5393 | out.push_back('(' + join(temp, ", "sv) + ')'); |
5364 | } | 5394 | } |
5365 | 5395 | ||
5366 | void transform_unary_value(UnaryValue_t* unary_value, str_list& out) { | 5396 | void transformUnaryValue(UnaryValue_t* unary_value, str_list& out) { |
5367 | str_list temp; | 5397 | str_list temp; |
5368 | for (auto _op : unary_value->ops.objects()) { | 5398 | for (auto _op : unary_value->ops.objects()) { |
5369 | std::string op = _parser.toString(_op); | 5399 | std::string op = _parser.toString(_op); |
@@ -5376,7 +5406,124 @@ private: | |||
5376 | out.push_back(join(temp)); | 5406 | out.push_back(join(temp)); |
5377 | } | 5407 | } |
5378 | 5408 | ||
5379 | void transform_unary_exp(UnaryExp_t* unary_exp, str_list& out) { | 5409 | void transformUnaryExp(UnaryExp_t* unary_exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
5410 | auto x = unary_exp; | ||
5411 | if (unary_exp->inExp) { | ||
5412 | std::string varName; | ||
5413 | if (unary_exp->ops.empty() && unary_exp->expos.size() == 1) { | ||
5414 | auto value = static_cast<Value_t*>(unary_exp->expos.back()); | ||
5415 | varName = singleVariableFrom(value, false); | ||
5416 | if (!isLocal(varName)) { | ||
5417 | varName.clear(); | ||
5418 | } | ||
5419 | } | ||
5420 | if (varName.empty()) { | ||
5421 | str_list temp; | ||
5422 | if (usage == ExpUsage::Closure) { | ||
5423 | pushFunctionScope(); | ||
5424 | pushAnonVarArg(); | ||
5425 | pushScope(); | ||
5426 | } else if (usage == ExpUsage::Assignment) { | ||
5427 | temp.push_back(indent() + "do"s + nll(x)); | ||
5428 | pushScope(); | ||
5429 | } | ||
5430 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); | ||
5431 | newUnaryExp->ops.dup(unary_exp->ops); | ||
5432 | newUnaryExp->expos.dup(unary_exp->expos); | ||
5433 | auto exp = newExp(newUnaryExp, x); | ||
5434 | auto newVar = getUnusedName("_val_"sv); | ||
5435 | auto assignExp = toAst<Exp_t>(newVar, x); | ||
5436 | auto assignment = assignmentFrom(assignExp, exp, x); | ||
5437 | transformAssignment(assignment, temp); | ||
5438 | if (auto range = unary_exp->inExp->item.as<InRange_t>()) { | ||
5439 | str_list tmp; | ||
5440 | transformExp(range->openValue, tmp, ExpUsage::Closure); | ||
5441 | transformExp(range->closeValue, tmp, ExpUsage::Closure); | ||
5442 | if (usage == ExpUsage::Assignment) { | ||
5443 | str_list tmpList; | ||
5444 | transformExp(static_cast<Exp_t*>(assignList->exprs.front()), tmpList, ExpUsage::Closure); | ||
5445 | _buf << indent() << tmpList.back() << " = "sv; | ||
5446 | } else { | ||
5447 | _buf << indent() << "return "sv; | ||
5448 | } | ||
5449 | if (unary_exp->inExp->not_) { | ||
5450 | _buf << "not ("sv; | ||
5451 | } | ||
5452 | _buf << tmp.front() << (range->open.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << newVar << " and "sv << newVar << (range->close.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << tmp.back(); | ||
5453 | if (unary_exp->inExp->not_) { | ||
5454 | _buf << ")"sv; | ||
5455 | } | ||
5456 | _buf << nll(x); | ||
5457 | temp.push_back(clearBuf()); | ||
5458 | } else { | ||
5459 | auto discrete = unary_exp->inExp->item.to<InDiscrete_t>(); | ||
5460 | str_list tmp; | ||
5461 | for (auto exp : discrete->values.objects()) { | ||
5462 | transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); | ||
5463 | } | ||
5464 | _buf << indent() << "return "sv; | ||
5465 | if (unary_exp->inExp->not_) { | ||
5466 | _buf << "not ("sv; | ||
5467 | } | ||
5468 | for (const auto& exp : tmp) { | ||
5469 | _buf << exp << " == "sv << newVar; | ||
5470 | if (exp != tmp.back()) { | ||
5471 | _buf << " or "sv; | ||
5472 | } | ||
5473 | } | ||
5474 | if (unary_exp->inExp->not_) { | ||
5475 | _buf << ")"sv; | ||
5476 | } | ||
5477 | _buf << nll(x); | ||
5478 | temp.push_back(clearBuf()); | ||
5479 | } | ||
5480 | if (usage == ExpUsage::Closure) { | ||
5481 | temp.push_front(anonFuncStart() + nll(x)); | ||
5482 | popScope(); | ||
5483 | temp.push_back(indent() + anonFuncEnd()); | ||
5484 | out.push_back(join(temp)); | ||
5485 | popAnonVarArg(); | ||
5486 | popFunctionScope(); | ||
5487 | } else if (usage == ExpUsage::Assignment) { | ||
5488 | popScope(); | ||
5489 | temp.push_back(indent() + "end"s + nll(x)); | ||
5490 | out.push_back(join(temp)); | ||
5491 | } else { | ||
5492 | out.push_back(join(temp)); | ||
5493 | } | ||
5494 | } else { | ||
5495 | if (auto range = unary_exp->inExp->item.as<InRange_t>()) { | ||
5496 | str_list tmp; | ||
5497 | transformExp(range->openValue, tmp, ExpUsage::Closure); | ||
5498 | transformExp(range->closeValue, tmp, ExpUsage::Closure); | ||
5499 | if (unary_exp->inExp->not_) { | ||
5500 | _buf << "not "sv; | ||
5501 | } | ||
5502 | _buf << '(' << tmp.front() << (range->open.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << varName << " and "sv << varName << (range->close.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << tmp.back(); | ||
5503 | _buf << ')'; | ||
5504 | out.push_back(clearBuf()); | ||
5505 | } else { | ||
5506 | auto discrete = unary_exp->inExp->item.to<InDiscrete_t>(); | ||
5507 | str_list tmp; | ||
5508 | for (auto exp : discrete->values.objects()) { | ||
5509 | transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); | ||
5510 | } | ||
5511 | if (unary_exp->inExp->not_) { | ||
5512 | _buf << "not "sv; | ||
5513 | } | ||
5514 | _buf << '('; | ||
5515 | for (const auto& exp : tmp) { | ||
5516 | _buf << exp << " == "sv << varName; | ||
5517 | if (exp != tmp.back()) { | ||
5518 | _buf << " or "sv; | ||
5519 | } | ||
5520 | } | ||
5521 | _buf << ')'; | ||
5522 | out.push_back(clearBuf()); | ||
5523 | } | ||
5524 | } | ||
5525 | return; | ||
5526 | } | ||
5380 | if (unary_exp->ops.empty() && unary_exp->expos.size() == 1) { | 5527 | if (unary_exp->ops.empty() && unary_exp->expos.size() == 1) { |
5381 | transformValue(static_cast<Value_t*>(unary_exp->expos.back()), out); | 5528 | transformValue(static_cast<Value_t*>(unary_exp->expos.back()), out); |
5382 | return; | 5529 | return; |
@@ -7322,7 +7469,7 @@ private: | |||
7322 | out.push_back(join(temp)); | 7469 | out.push_back(join(temp)); |
7323 | } | 7470 | } |
7324 | 7471 | ||
7325 | void transform_const_value(ConstValue_t* const_value, str_list& out) { | 7472 | void transformConstValue(ConstValue_t* const_value, str_list& out) { |
7326 | out.push_back(_parser.toString(const_value)); | 7473 | out.push_back(_parser.toString(const_value)); |
7327 | } | 7474 | } |
7328 | 7475 | ||
@@ -8216,7 +8363,20 @@ private: | |||
8216 | std::string tabCheckVar; | 8363 | std::string tabCheckVar; |
8217 | for (auto branch_ : branches) { | 8364 | for (auto branch_ : branches) { |
8218 | auto branch = static_cast<SwitchCase_t*>(branch_); | 8365 | auto branch = static_cast<SwitchCase_t*>(branch_); |
8219 | if (auto value = singleValueFrom(branch->valueList); | 8366 | if (auto inExp = branch->condition.as<In_t>()) { |
8367 | auto unary = branch->new_ptr<UnaryExp_t>(); | ||
8368 | unary->expos.push_back(toAst<Value_t>(objVar, branch)); | ||
8369 | unary->inExp.set(inExp); | ||
8370 | transformUnaryExp(unary, temp, ExpUsage::Closure); | ||
8371 | temp.back() = indent() + (firstBranch ? "if "s : "elseif "s) + temp.back() + " then"s + nll(branch); | ||
8372 | pushScope(); | ||
8373 | transform_plain_body(branch->body, temp, usage, assignList); | ||
8374 | popScope(); | ||
8375 | firstBranch = false; | ||
8376 | continue; | ||
8377 | } | ||
8378 | auto valueList = branch->condition.to<SwitchList_t>(); | ||
8379 | if (auto value = singleValueFrom(valueList); | ||
8220 | value && (value->item.is<SimpleTable_t>() || value->getByPath<SimpleValue_t, TableLit_t>())) { | 8380 | value && (value->item.is<SimpleTable_t>() || value->getByPath<SimpleValue_t, TableLit_t>())) { |
8221 | if (!firstBranch) { | 8381 | if (!firstBranch) { |
8222 | temp.push_back(indent() + "else"s + nll(branch)); | 8382 | temp.push_back(indent() + "else"s + nll(branch)); |
@@ -8245,7 +8405,7 @@ private: | |||
8245 | } | 8405 | } |
8246 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); | 8406 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); |
8247 | pushScope(); | 8407 | pushScope(); |
8248 | auto assignment = assignmentFrom(static_cast<Exp_t*>(branch->valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); | 8408 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); |
8249 | auto info = extractDestructureInfo(assignment, true, false); | 8409 | auto info = extractDestructureInfo(assignment, true, false); |
8250 | transformAssignment(assignment, temp, true); | 8410 | transformAssignment(assignment, temp, true); |
8251 | str_list conds; | 8411 | str_list conds; |
@@ -8283,7 +8443,7 @@ private: | |||
8283 | temp.push_back(indent() + (firstBranch ? "if"s : "elseif"s)); | 8443 | temp.push_back(indent() + (firstBranch ? "if"s : "elseif"s)); |
8284 | firstBranch = false; | 8444 | firstBranch = false; |
8285 | str_list tmp; | 8445 | str_list tmp; |
8286 | const auto& exprs = branch->valueList->exprs.objects(); | 8446 | const auto& exprs = valueList->exprs.objects(); |
8287 | for (auto exp_ : exprs) { | 8447 | for (auto exp_ : exprs) { |
8288 | auto exp = static_cast<Exp_t*>(exp_); | 8448 | auto exp = static_cast<Exp_t*>(exp_); |
8289 | transformExp(exp, tmp, ExpUsage::Closure); | 8449 | transformExp(exp, tmp, ExpUsage::Closure); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index dffdbe1..f383275 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -317,7 +317,7 @@ YueParser::YueParser() { | |||
317 | with_exp = ExpList >> -(space >> Assign); | 317 | with_exp = ExpList >> -(space >> Assign); |
318 | 318 | ||
319 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 319 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); |
320 | SwitchCase = key("when") >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); | 320 | SwitchCase = key("when") >> (disable_chain_rule(disable_arg_table_block_rule(SwitchList)) | space >> In) >> space >> body_with("then"); |
321 | switch_else = key("else") >> space >> body; | 321 | switch_else = key("else") >> space >> body; |
322 | 322 | ||
323 | switch_block = | 323 | switch_block = |
@@ -454,12 +454,19 @@ YueParser::YueParser() { | |||
454 | expo_value = exponential_operator >> *space_break >> space >> Value; | 454 | expo_value = exponential_operator >> *space_break >> space >> Value; |
455 | expo_exp = Value >> *(space >> expo_value); | 455 | expo_exp = Value >> *(space >> expo_value); |
456 | 456 | ||
457 | InRangeOpen = true_(); | ||
458 | InRangeClose = true_(); | ||
459 | NotIn = true_(); | ||
460 | InRange = ('(' >> InRangeOpen | '[' >> InRangeClose) >> space >> Exp >> space >> ',' >> space >> Exp >> space >> (')' >> InRangeOpen | ']' >> InRangeClose); | ||
461 | InDiscrete = '{' >> Seperator >> space >> Exp >> *(space >> ',' >> space >> Exp) >> space >> '}'; | ||
462 | In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InRange | InDiscrete); | ||
463 | |||
457 | UnaryOperator = | 464 | UnaryOperator = |
458 | '-' >> not_(set(">=") | space_one) | | 465 | '-' >> not_(set(">=") | space_one) | |
459 | '#' | | 466 | '#' | |
460 | '~' >> not_('=' | space_one) | | 467 | '~' >> not_('=' | space_one) | |
461 | key("not"); | 468 | key("not"); |
462 | UnaryExp = *(UnaryOperator >> space) >> expo_exp; | 469 | UnaryExp = *(UnaryOperator >> space) >> expo_exp >> -(space >> In); |
463 | 470 | ||
464 | pipe_operator = "|>"; | 471 | pipe_operator = "|>"; |
465 | pipe_value = pipe_operator >> *space_break >> space >> UnaryExp; | 472 | pipe_value = pipe_operator >> *space_break >> space >> UnaryExp; |
@@ -916,7 +923,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
916 | error_list errors; | 923 | error_list errors; |
917 | try { | 924 | try { |
918 | State state; | 925 | State state; |
919 | res.node.set(pl::parse(*(res.codes), r, errors, &state)); | 926 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); |
920 | if (state.exportCount > 0) { | 927 | if (state.exportCount > 0) { |
921 | res.moduleName = std::move(state.moduleName); | 928 | res.moduleName = std::move(state.moduleName); |
922 | res.exportDefault = state.exportDefault; | 929 | res.exportDefault = state.exportDefault; |
@@ -952,14 +959,6 @@ std::string YueParser::toString(input::iterator begin, input::iterator end) { | |||
952 | return _converter.to_bytes(std::wstring(begin, end)); | 959 | return _converter.to_bytes(std::wstring(begin, end)); |
953 | } | 960 | } |
954 | 961 | ||
955 | input YueParser::encode(std::string_view codes) { | ||
956 | return _converter.from_bytes(&codes.front(), &codes.back() + 1); | ||
957 | } | ||
958 | |||
959 | std::string YueParser::decode(const input& codes) { | ||
960 | return _converter.to_bytes(codes); | ||
961 | } | ||
962 | |||
963 | namespace Utils { | 962 | namespace Utils { |
964 | void replace(std::string& str, std::string_view from, std::string_view to) { | 963 | void replace(std::string& str, std::string_view from, std::string_view to) { |
965 | size_t start_pos = 0; | 964 | size_t start_pos = 0; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 3be50a7..d4f66eb 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -25,6 +25,7 @@ namespace yue { | |||
25 | using namespace std::string_view_literals; | 25 | using namespace std::string_view_literals; |
26 | using namespace std::string_literals; | 26 | using namespace std::string_literals; |
27 | using namespace parserlib; | 27 | using namespace parserlib; |
28 | using namespace parserlib::yue; | ||
28 | 29 | ||
29 | struct ParseInfo { | 30 | struct ParseInfo { |
30 | struct Error { | 31 | struct Error { |
@@ -86,9 +87,6 @@ public: | |||
86 | std::string toString(ast_node* node); | 87 | std::string toString(ast_node* node); |
87 | std::string toString(input::iterator begin, input::iterator end); | 88 | std::string toString(input::iterator begin, input::iterator end); |
88 | 89 | ||
89 | input encode(std::string_view input); | ||
90 | std::string decode(const input& input); | ||
91 | |||
92 | protected: | 90 | protected: |
93 | ParseInfo parse(std::string_view codes, rule& r); | 91 | ParseInfo parse(std::string_view codes, rule& r); |
94 | 92 | ||
@@ -378,6 +376,12 @@ private: | |||
378 | AST_RULE(ConstValue) | 376 | AST_RULE(ConstValue) |
379 | AST_RULE(UnaryValue) | 377 | AST_RULE(UnaryValue) |
380 | AST_RULE(UnaryExp) | 378 | AST_RULE(UnaryExp) |
379 | AST_RULE(InRangeOpen) | ||
380 | AST_RULE(InRangeClose) | ||
381 | AST_RULE(NotIn) | ||
382 | AST_RULE(InRange) | ||
383 | AST_RULE(InDiscrete) | ||
384 | AST_RULE(In) | ||
381 | AST_RULE(ExpListAssign) | 385 | AST_RULE(ExpListAssign) |
382 | AST_RULE(IfLine) | 386 | AST_RULE(IfLine) |
383 | AST_RULE(WhileLine) | 387 | AST_RULE(WhileLine) |