diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_ast.cpp | 27 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 34 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 497 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 61 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 10 | 
5 files changed, 453 insertions, 176 deletions
| diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index ed34274..6126f71 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -182,12 +182,6 @@ std::string ConstValue_t::to_string(void* ud) const { | |||
| 182 | auto info = reinterpret_cast<YueFormat*>(ud); | 182 | auto info = reinterpret_cast<YueFormat*>(ud); | 
| 183 | return info->convert(this); | 183 | return info->convert(this); | 
| 184 | } | 184 | } | 
| 185 | std::string InRangeOpen_t::to_string(void*) const { | ||
| 186 | return {}; | ||
| 187 | } | ||
| 188 | std::string InRangeClose_t::to_string(void*) const { | ||
| 189 | return {}; | ||
| 190 | } | ||
| 191 | std::string NotIn_t::to_string(void*) const { | 185 | std::string NotIn_t::to_string(void*) const { | 
| 192 | return {}; | 186 | return {}; | 
| 193 | } | 187 | } | 
| @@ -569,8 +563,18 @@ std::string Try_t::to_string(void* ud) const { | |||
| 569 | return join(temp, "\n"sv); | 563 | return join(temp, "\n"sv); | 
| 570 | } | 564 | } | 
| 571 | std::string Comprehension_t::to_string(void* ud) const { | 565 | std::string Comprehension_t::to_string(void* ud) const { | 
| 572 | auto valueStr = value->to_string(ud); | 566 | str_list temp; | 
| 573 | return '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ' ' + forLoop->to_string(ud) + ']'; | 567 | for (const auto& item : items.objects()) { | 
| 568 | temp.push_back(item->to_string(ud)); | ||
| 569 | } | ||
| 570 | if (temp.size() > 0) { | ||
| 571 | temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s); | ||
| 572 | } | ||
| 573 | if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) { | ||
| 574 | return '[' + join(temp, ", "sv) + ']'; | ||
| 575 | } else { | ||
| 576 | return '[' + join(temp, " "sv) + ']'; | ||
| 577 | } | ||
| 574 | } | 578 | } | 
| 575 | std::string CompValue_t::to_string(void* ud) const { | 579 | std::string CompValue_t::to_string(void* ud) const { | 
| 576 | return value->to_string(ud); | 580 | return value->to_string(ud); | 
| @@ -830,6 +834,9 @@ std::string Invoke_t::to_string(void* ud) const { | |||
| 830 | std::string SpreadExp_t::to_string(void* ud) const { | 834 | std::string SpreadExp_t::to_string(void* ud) const { | 
| 831 | return "..."s + exp->to_string(ud); | 835 | return "..."s + exp->to_string(ud); | 
| 832 | } | 836 | } | 
| 837 | std::string SpreadListExp_t::to_string(void* ud) const { | ||
| 838 | return "..."s + exp->to_string(ud); | ||
| 839 | } | ||
| 833 | std::string TableLit_t::to_string(void* ud) const { | 840 | std::string TableLit_t::to_string(void* ud) const { | 
| 834 | auto info = reinterpret_cast<YueFormat*>(ud); | 841 | auto info = reinterpret_cast<YueFormat*>(ud); | 
| 835 | if (values.empty()) { | 842 | if (values.empty()) { | 
| @@ -1168,10 +1175,6 @@ std::string UnaryExp_t::to_string(void* ud) const { | |||
| 1168 | } | 1175 | } | 
| 1169 | return line; | 1176 | return line; | 
| 1170 | } | 1177 | } | 
| 1171 | std::string InRange_t::to_string(void* ud) const { | ||
| 1172 | auto valueStr = openValue->to_string(ud); | ||
| 1173 | return (open.is<InRangeOpen_t>() ? "("s : "["s + (valueStr[0] == '[' ? " "s : ""s)) + valueStr + ", "s + closeValue->to_string(ud) + (close.is<InRangeOpen_t>() ? ')' : ']'); | ||
| 1174 | } | ||
| 1175 | std::string InDiscrete_t::to_string(void* ud) const { | 1178 | std::string InDiscrete_t::to_string(void* ud) const { | 
| 1176 | str_list temp; | 1179 | str_list temp; | 
| 1177 | for (auto value : values.objects()) { | 1180 | for (auto value : values.objects()) { | 
| diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index a02f548..2136849 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -78,6 +78,8 @@ class InvokeArgs_t; | |||
| 78 | class TableBlockIndent_t; | 78 | class TableBlockIndent_t; | 
| 79 | class Macro_t; | 79 | class Macro_t; | 
| 80 | class In_t; | 80 | class In_t; | 
| 81 | class NormalDef_t; | ||
| 82 | class SpreadListExp_t; | ||
| 81 | } // namespace yue | 83 | } // namespace yue | 
| 82 | 84 | ||
| 83 | AST_LEAF(Num) | 85 | AST_LEAF(Num) | 
| @@ -286,7 +288,7 @@ AST_NODE(SwitchList) | |||
| 286 | AST_END(SwitchList, "switch_list"sv) | 288 | AST_END(SwitchList, "switch_list"sv) | 
| 287 | 289 | ||
| 288 | AST_NODE(SwitchCase) | 290 | AST_NODE(SwitchCase) | 
| 289 | ast_sel<true, SwitchList_t, In_t> condition; | 291 | ast_ptr<true, SwitchList_t> condition; | 
| 290 | ast_sel<true, Block_t, Statement_t> body; | 292 | ast_sel<true, Block_t, Statement_t> body; | 
| 291 | AST_MEMBER(SwitchCase, &condition, &body) | 293 | AST_MEMBER(SwitchCase, &condition, &body) | 
| 292 | AST_END(SwitchCase, "switch_case"sv) | 294 | AST_END(SwitchCase, "switch_case"sv) | 
| @@ -374,9 +376,10 @@ AST_NODE(Try) | |||
| 374 | AST_END(Try, "try"sv) | 376 | AST_END(Try, "try"sv) | 
| 375 | 377 | ||
| 376 | AST_NODE(Comprehension) | 378 | AST_NODE(Comprehension) | 
| 377 | ast_sel<true, Exp_t, /*non-syntax-rule*/ Statement_t> value; | 379 | ast_ptr<true, Seperator_t> sep; | 
| 378 | ast_ptr<true, CompInner_t> forLoop; | 380 | ast_sel_list<false, NormalDef_t, SpreadListExp_t, CompInner_t, | 
| 379 | AST_MEMBER(Comprehension, &value, &forLoop) | 381 | /*non-syntax-rule*/ Statement_t> items; | 
| 382 | AST_MEMBER(Comprehension, &sep, &items) | ||
| 380 | AST_END(Comprehension, "comp"sv) | 383 | AST_END(Comprehension, "comp"sv) | 
| 381 | 384 | ||
| 382 | AST_NODE(CompValue) | 385 | AST_NODE(CompValue) | 
| @@ -437,23 +440,9 @@ AST_END(BinaryOperator, "binary_op"sv) | |||
| 437 | AST_LEAF(UnaryOperator) | 440 | AST_LEAF(UnaryOperator) | 
| 438 | AST_END(UnaryOperator, "unary_op"sv) | 441 | AST_END(UnaryOperator, "unary_op"sv) | 
| 439 | 442 | ||
| 440 | AST_LEAF(InRangeOpen) | ||
| 441 | AST_END(InRangeOpen, "in_range_open"sv) | ||
| 442 | |||
| 443 | AST_LEAF(InRangeClose) | ||
| 444 | AST_END(InRangeClose, "in_range_close"sv) | ||
| 445 | |||
| 446 | AST_LEAF(NotIn) | 443 | AST_LEAF(NotIn) | 
| 447 | AST_END(NotIn, "not_in"sv) | 444 | AST_END(NotIn, "not_in"sv) | 
| 448 | 445 | ||
| 449 | AST_NODE(InRange) | ||
| 450 | ast_sel<true, InRangeOpen_t, InRangeClose_t> open; | ||
| 451 | ast_ptr<true, Exp_t> openValue; | ||
| 452 | ast_ptr<true, Exp_t> closeValue; | ||
| 453 | ast_sel<true, InRangeOpen_t, InRangeClose_t> close; | ||
| 454 | AST_MEMBER(InRange, &open, &openValue, &closeValue, &close) | ||
| 455 | AST_END(InRange, "in_range"sv) | ||
| 456 | |||
| 457 | AST_NODE(InDiscrete) | 446 | AST_NODE(InDiscrete) | 
| 458 | ast_ptr<true, Seperator_t> sep; | 447 | ast_ptr<true, Seperator_t> sep; | 
| 459 | ast_list<true, Exp_t> values; | 448 | ast_list<true, Exp_t> values; | 
| @@ -462,7 +451,7 @@ AST_END(InDiscrete, "in_discrete"sv) | |||
| 462 | 451 | ||
| 463 | AST_NODE(In) | 452 | AST_NODE(In) | 
| 464 | ast_ptr<false, NotIn_t> not_; | 453 | ast_ptr<false, NotIn_t> not_; | 
| 465 | ast_sel<true, InRange_t, InDiscrete_t, Exp_t> item; | 454 | ast_sel<true, InDiscrete_t, Exp_t> item; | 
| 466 | AST_MEMBER(In, ¬_, &item) | 455 | AST_MEMBER(In, ¬_, &item) | 
| 467 | AST_END(In, "in"sv) | 456 | AST_END(In, "in"sv) | 
| 468 | 457 | ||
| @@ -666,6 +655,11 @@ AST_NODE(SpreadExp) | |||
| 666 | AST_MEMBER(SpreadExp, &exp) | 655 | AST_MEMBER(SpreadExp, &exp) | 
| 667 | AST_END(SpreadExp, "spread_exp"sv) | 656 | AST_END(SpreadExp, "spread_exp"sv) | 
| 668 | 657 | ||
| 658 | AST_NODE(SpreadListExp) | ||
| 659 | ast_ptr<true, Exp_t> exp; | ||
| 660 | AST_MEMBER(SpreadListExp, &exp) | ||
| 661 | AST_END(SpreadListExp, "spread_list_exp"sv) | ||
| 662 | |||
| 669 | AST_NODE(TableLit) | 663 | AST_NODE(TableLit) | 
| 670 | ast_ptr<true, Seperator_t> sep; | 664 | ast_ptr<true, Seperator_t> sep; | 
| 671 | ast_sel_list<false, | 665 | ast_sel_list<false, | 
| @@ -673,7 +667,7 @@ AST_NODE(TableLit) | |||
| 673 | MetaVariablePairDef_t, MetaNormalPairDef_t, | 667 | MetaVariablePairDef_t, MetaNormalPairDef_t, | 
| 674 | VariablePair_t, NormalPair_t, Exp_t, | 668 | VariablePair_t, NormalPair_t, Exp_t, | 
| 675 | MetaVariablePair_t, MetaNormalPair_t, | 669 | MetaVariablePair_t, MetaNormalPair_t, | 
| 676 | /*non-syntax-rule*/ TableBlockIndent_t> values; | 670 | /*non-syntax-rule*/ TableBlockIndent_t, SpreadListExp_t> values; | 
| 677 | AST_MEMBER(TableLit, &sep, &values) | 671 | AST_MEMBER(TableLit, &sep, &values) | 
| 678 | AST_END(TableLit, "table_lit"sv) | 672 | AST_END(TableLit, "table_lit"sv) | 
| 679 | 673 | ||
| diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 5b9770d..d32d9c1 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 15 | #include <unordered_map> | 15 | #include <unordered_map> | 
| 16 | #include <unordered_set> | 16 | #include <unordered_set> | 
| 17 | #include <vector> | 17 | #include <vector> | 
| 18 | #include <variant> | ||
| 18 | 19 | ||
| 19 | #include "yuescript/yue_compiler.h" | 20 | #include "yuescript/yue_compiler.h" | 
| 20 | #include "yuescript/yue_parser.h" | 21 | #include "yuescript/yue_parser.h" | 
| @@ -74,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 74 | "close"s // Lua 5.4 | 75 | "close"s // Lua 5.4 | 
| 75 | }; | 76 | }; | 
| 76 | 77 | ||
| 77 | const std::string_view version = "0.19.6"sv; | 78 | const std::string_view version = "0.20.0"sv; | 
| 78 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; | 
| 79 | 80 | ||
| 80 | class CompileError : public std::logic_error { | 81 | class CompileError : public std::logic_error { | 
| @@ -1148,6 +1149,10 @@ private: | |||
| 1148 | auto simpleValue = static_cast<SimpleValue_t*>(item); | 1149 | auto simpleValue = static_cast<SimpleValue_t*>(item); | 
| 1149 | if (simpleValue->value.is<TableLit_t>()) { | 1150 | if (simpleValue->value.is<TableLit_t>()) { | 
| 1150 | return true; | 1151 | return true; | 
| 1152 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { | ||
| 1153 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | ||
| 1154 | return true; | ||
| 1155 | } | ||
| 1151 | } | 1156 | } | 
| 1152 | return false; | 1157 | return false; | 
| 1153 | } | 1158 | } | 
| @@ -1195,6 +1200,28 @@ private: | |||
| 1195 | return false; | 1200 | return false; | 
| 1196 | } | 1201 | } | 
| 1197 | 1202 | ||
| 1203 | bool isConditionChainingOperator(const std::string& op) { | ||
| 1204 | return op == "=="sv || op == "~="sv || op == "!="sv || | ||
| 1205 | op == "<"sv || op == "<="sv || op == ">"sv || op == ">="sv; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | bool isConditionChaining(Exp_t* exp) { | ||
| 1209 | int conditionChaining = 0; | ||
| 1210 | for (const auto& opValue_ : exp->opValues.objects()) { | ||
| 1211 | auto opValue = static_cast<ExpOpValue_t*>(opValue_); | ||
| 1212 | auto op = _parser.toString(opValue->op); | ||
| 1213 | if (isConditionChainingOperator(op)) { | ||
| 1214 | conditionChaining++; | ||
| 1215 | if (conditionChaining > 1) { | ||
| 1216 | return true; | ||
| 1217 | } | ||
| 1218 | } else { | ||
| 1219 | conditionChaining = 0; | ||
| 1220 | } | ||
| 1221 | } | ||
| 1222 | return false; | ||
| 1223 | } | ||
| 1224 | |||
| 1198 | UnaryExp_t* unaryGeneratingAnonFunc(Exp_t* exp) { | 1225 | UnaryExp_t* unaryGeneratingAnonFunc(Exp_t* exp) { | 
| 1199 | if (!exp) return nullptr; | 1226 | if (!exp) return nullptr; | 
| 1200 | BLOCK_START | 1227 | BLOCK_START | 
| @@ -1440,10 +1467,10 @@ private: | |||
| 1440 | case id<CompInner_t>(): { | 1467 | case id<CompInner_t>(): { | 
| 1441 | auto compInner = appendix->item.to<CompInner_t>(); | 1468 | auto compInner = appendix->item.to<CompInner_t>(); | 
| 1442 | auto comp = x->new_ptr<Comprehension_t>(); | 1469 | auto comp = x->new_ptr<Comprehension_t>(); | 
| 1443 | comp->forLoop.set(compInner); | ||
| 1444 | auto stmt = x->new_ptr<Statement_t>(); | 1470 | auto stmt = x->new_ptr<Statement_t>(); | 
| 1445 | stmt->content.set(statement->content); | 1471 | stmt->content.set(statement->content); | 
| 1446 | comp->value.set(stmt); | 1472 | comp->items.push_back(stmt); | 
| 1473 | comp->items.push_back(compInner); | ||
| 1447 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | 1474 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | 
| 1448 | simpleValue->value.set(comp); | 1475 | simpleValue->value.set(comp); | 
| 1449 | auto exp = newExp(simpleValue, x); | 1476 | auto exp = newExp(simpleValue, x); | 
| @@ -2032,6 +2059,10 @@ private: | |||
| 2032 | transformUnaryExp(unary, out, ExpUsage::Assignment, expList); | 2059 | transformUnaryExp(unary, out, ExpUsage::Assignment, expList); | 
| 2033 | out.back().insert(0, preDefine); | 2060 | out.back().insert(0, preDefine); | 
| 2034 | return; | 2061 | return; | 
| 2062 | } else if (isConditionChaining(exp)) { | ||
| 2063 | auto expList = assignment->expList.get(); | ||
| 2064 | transformExp(exp, out, ExpUsage::Assignment, expList); | ||
| 2065 | return; | ||
| 2035 | } | 2066 | } | 
| 2036 | auto singleVal = singleValueFrom(exp); | 2067 | auto singleVal = singleValueFrom(exp); | 
| 2037 | BREAK_IF(!singleVal); | 2068 | BREAK_IF(!singleVal); | 
| @@ -2320,12 +2351,15 @@ private: | |||
| 2320 | case id<Exp_t>(): { | 2351 | case id<Exp_t>(): { | 
| 2321 | auto item = singleValueFrom(node)->item.get(); | 2352 | auto item = singleValueFrom(node)->item.get(); | 
| 2322 | if (!item) throw CompileError("invalid destructure value"sv, node); | 2353 | if (!item) throw CompileError("invalid destructure value"sv, node); | 
| 2323 | auto tbA = item->get_by_path<TableLit_t>(); | 2354 | if (auto tbA = item->get_by_path<TableLit_t>()) { | 
| 2324 | if (tbA) { | ||
| 2325 | tableItems = &tbA->values.objects(); | 2355 | tableItems = &tbA->values.objects(); | 
| 2326 | } else { | 2356 | } else if (auto tbB = item->get_by_path<Comprehension_t>()) { | 
| 2327 | auto tbB = ast_cast<SimpleTable_t>(item); | 2357 | if (tbB->items.size() == 2 && ast_is<CompInner_t>(tbB->items.back())) { | 
| 2328 | if (tbB) tableItems = &tbB->pairs.objects(); | 2358 | throw CompileError("invalid destructure value"sv, tbB); | 
| 2359 | } | ||
| 2360 | tableItems = &tbB->items.objects(); | ||
| 2361 | } else if (auto tbC = ast_cast<SimpleTable_t>(item)) { | ||
| 2362 | tableItems = &tbC->pairs.objects(); | ||
| 2329 | } | 2363 | } | 
| 2330 | break; | 2364 | break; | 
| 2331 | } | 2365 | } | 
| @@ -2340,15 +2374,23 @@ private: | |||
| 2340 | break; | 2374 | break; | 
| 2341 | } | 2375 | } | 
| 2342 | case id<TableLit_t>(): { | 2376 | case id<TableLit_t>(): { | 
| 2343 | auto table = ast_cast<TableLit_t>(node); | 2377 | auto table = static_cast<TableLit_t*>(node); | 
| 2344 | tableItems = &table->values.objects(); | 2378 | tableItems = &table->values.objects(); | 
| 2345 | break; | 2379 | break; | 
| 2346 | } | 2380 | } | 
| 2347 | case id<SimpleTable_t>(): { | 2381 | case id<SimpleTable_t>(): { | 
| 2348 | auto table = ast_cast<SimpleTable_t>(node); | 2382 | auto table = static_cast<SimpleTable_t*>(node); | 
| 2349 | tableItems = &table->pairs.objects(); | 2383 | tableItems = &table->pairs.objects(); | 
| 2350 | break; | 2384 | break; | 
| 2351 | } | 2385 | } | 
| 2386 | case id<Comprehension_t>(): { | ||
| 2387 | auto table = static_cast<Comprehension_t*>(node); | ||
| 2388 | if (table->items.size() == 2 && ast_is<CompInner_t>(table->items.back())) { | ||
| 2389 | throw CompileError("invalid destructure value"sv, table); | ||
| 2390 | } | ||
| 2391 | tableItems = &table->items.objects(); | ||
| 2392 | break; | ||
| 2393 | } | ||
| 2352 | default: YUEE("AST node mismatch", node); break; | 2394 | default: YUEE("AST node mismatch", node); break; | 
| 2353 | } | 2395 | } | 
| 2354 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); | 2396 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); | 
| @@ -2370,8 +2412,9 @@ private: | |||
| 2370 | } | 2412 | } | 
| 2371 | auto value = singleValueFrom(pair); | 2413 | auto value = singleValueFrom(pair); | 
| 2372 | auto item = value->item.get(); | 2414 | auto item = value->item.get(); | 
| 2373 | if (ast_is<SimpleTable_t>(item) || item->get_by_path<TableLit_t>()) { | 2415 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 
| 2374 | auto subPairs = destructFromExp(pair, varDefOnly, optional); | 2416 | if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) { | 
| 2417 | auto subPairs = destructFromExp(subExp, varDefOnly, optional); | ||
| 2375 | if (!subPairs.empty()) { | 2418 | if (!subPairs.empty()) { | 
| 2376 | if (defVal) { | 2419 | if (defVal) { | 
| 2377 | throw CompileError("default value is not supported here"sv, defVal); | 2420 | throw CompileError("default value is not supported here"sv, defVal); | 
| @@ -2448,8 +2491,9 @@ private: | |||
| 2448 | if (auto exp = np->value.as<Exp_t>()) { | 2491 | if (auto exp = np->value.as<Exp_t>()) { | 
| 2449 | if (!varDefOnly && !isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp); | 2492 | if (!varDefOnly && !isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp); | 
| 2450 | auto item = singleValueFrom(exp)->item.get(); | 2493 | auto item = singleValueFrom(exp)->item.get(); | 
| 2451 | if (ast_is<SimpleTable_t>(item) || item->get_by_path<TableLit_t>()) { | 2494 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 
| 2452 | auto subPairs = destructFromExp(exp, varDefOnly, optional); | 2495 | if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) { | 
| 2496 | auto subPairs = destructFromExp(subExp, varDefOnly, optional); | ||
| 2453 | if (!subPairs.empty()) { | 2497 | if (!subPairs.empty()) { | 
| 2454 | if (defVal) { | 2498 | if (defVal) { | 
| 2455 | throw CompileError("default value is not supported here"sv, defVal); | 2499 | throw CompileError("default value is not supported here"sv, defVal); | 
| @@ -2602,8 +2646,19 @@ private: | |||
| 2602 | if (!value) { | 2646 | if (!value) { | 
| 2603 | throw CompileError("invalid destructure"sv, expr); | 2647 | throw CompileError("invalid destructure"sv, expr); | 
| 2604 | } | 2648 | } | 
| 2605 | ast_node* destructNode = value->get_by_path<SimpleValue_t, TableLit_t>(); | 2649 | ast_node* destructNode = value->item.as<SimpleTable_t>(); | 
| 2606 | if (destructNode || (destructNode = value->item.as<SimpleTable_t>())) { | 2650 | if (!destructNode) { | 
| 2651 | if (auto sVal = value->item.as<SimpleValue_t>()) { | ||
| 2652 | if (auto tab = sVal->value.as<TableLit_t>()) { | ||
| 2653 | destructNode = tab; | ||
| 2654 | } else if (auto comp = sVal->value.as<Comprehension_t>()) { | ||
| 2655 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | ||
| 2656 | destructNode = comp; | ||
| 2657 | } | ||
| 2658 | } | ||
| 2659 | } | ||
| 2660 | } | ||
| 2661 | if (destructNode) { | ||
| 2607 | if (*j != nil) { | 2662 | if (*j != nil) { | 
| 2608 | if (auto ssVal = simpleSingleValueFrom(*j)) { | 2663 | if (auto ssVal = simpleSingleValueFrom(*j)) { | 
| 2609 | switch (ssVal->value->get_id()) { | 2664 | switch (ssVal->value->get_id()) { | 
| @@ -2630,6 +2685,9 @@ private: | |||
| 2630 | case id<SimpleTable_t>(): | 2685 | case id<SimpleTable_t>(): | 
| 2631 | dlist = &static_cast<SimpleTable_t*>(destructNode)->pairs.objects(); | 2686 | dlist = &static_cast<SimpleTable_t*>(destructNode)->pairs.objects(); | 
| 2632 | break; | 2687 | break; | 
| 2688 | case id<Comprehension_t>(): | ||
| 2689 | dlist = &static_cast<Comprehension_t*>(destructNode)->items.objects(); | ||
| 2690 | break; | ||
| 2633 | default: YUEE("AST node mismatch", destructNode); break; | 2691 | default: YUEE("AST node mismatch", destructNode); break; | 
| 2634 | } | 2692 | } | 
| 2635 | if (dlist->empty()) throw CompileError("expect items to be destructured"sv, destructNode); | 2693 | if (dlist->empty()) throw CompileError("expect items to be destructured"sv, destructNode); | 
| @@ -3300,27 +3358,173 @@ private: | |||
| 3300 | transform_pipe_exp(exp->pipeExprs.objects(), out, usage, assignList); | 3358 | transform_pipe_exp(exp->pipeExprs.objects(), out, usage, assignList); | 
| 3301 | return; | 3359 | return; | 
| 3302 | } | 3360 | } | 
| 3303 | if (usage != ExpUsage::Closure) { | ||
| 3304 | YUEE("invalid expression usage", exp); | ||
| 3305 | } | ||
| 3306 | if (exp->nilCoalesed) { | 3361 | if (exp->nilCoalesed) { | 
| 3362 | if (usage != ExpUsage::Closure) { | ||
| 3363 | YUEE("invalid expression usage", exp); | ||
| 3364 | } | ||
| 3307 | transformNilCoalesedExp(exp, out, ExpUsage::Closure); | 3365 | transformNilCoalesedExp(exp, out, ExpUsage::Closure); | 
| 3308 | return; | 3366 | return; | 
| 3309 | } | 3367 | } | 
| 3310 | str_list temp; | 3368 | str_list temp; | 
| 3311 | transform_pipe_exp(exp->pipeExprs.objects(), temp, ExpUsage::Closure); | 3369 | std::list<std::pair<std::string, ast_list<true, UnaryExp_t>*>> chains; | 
| 3370 | chains.emplace_back(std::string(), &exp->pipeExprs); | ||
| 3371 | int conditionChainCount = 0; | ||
| 3372 | str_list evalLines; | ||
| 3373 | auto checkChains = [&]() { | ||
| 3374 | std::optional<str_list> result; | ||
| 3375 | if (conditionChainCount > 1) { | ||
| 3376 | bool needWrapping = false; | ||
| 3377 | str_list conds; | ||
| 3378 | str_list preDefines; | ||
| 3379 | std::list<std::variant<std::string, ast_ptr<false, Exp_t>>> stack; | ||
| 3380 | for (const auto& item : chains) { | ||
| 3381 | if (!item.first.empty()) { | ||
| 3382 | stack.push_back(item.first); | ||
| 3383 | } | ||
| 3384 | auto node = item.second->front(); | ||
| 3385 | bool checkEvalOnce = item != chains.front() && item != chains.back(); | ||
| 3386 | if (checkEvalOnce) { | ||
| 3387 | std::string varName; | ||
| 3388 | if (item.second->size() == 1) { | ||
| 3389 | if (auto unary = singleUnaryExpFrom(node)) { | ||
| 3390 | if (auto value = singleValueFrom(unary)) { | ||
| 3391 | varName = singleVariableFrom(value, true); | ||
| 3392 | } | ||
| 3393 | if (varName.empty()) { | ||
| 3394 | if (auto sval = static_cast<Value_t*>(unary->expos.front())->item.as<SimpleValue_t>()) { | ||
| 3395 | if (ast_is<ConstValue_t, Num_t>(sval->value)) { | ||
| 3396 | auto condExp = unary->new_ptr<Exp_t>(); | ||
| 3397 | condExp->pipeExprs.dup(*item.second); | ||
| 3398 | stack.push_back(condExp); | ||
| 3399 | goto reduce; | ||
| 3400 | } | ||
| 3401 | } | ||
| 3402 | } | ||
| 3403 | } | ||
| 3404 | } | ||
| 3405 | if (varName.empty() || !isLocal(varName)) { | ||
| 3406 | varName = getUnusedName("_cond_"sv); | ||
| 3407 | auto condExp = node->new_ptr<Exp_t>(); | ||
| 3408 | condExp->pipeExprs.dup(*item.second); | ||
| 3409 | auto varExp = toAst<Exp_t>(varName, node); | ||
| 3410 | auto assignment = assignmentFrom(varExp, condExp, node); | ||
| 3411 | if (!needWrapping) { | ||
| 3412 | needWrapping = true; | ||
| 3413 | if (usage == ExpUsage::Closure) { | ||
| 3414 | pushFunctionScope(); | ||
| 3415 | pushAnonVarArg(); | ||
| 3416 | pushScope(); | ||
| 3417 | } else if (usage == ExpUsage::Assignment) { | ||
| 3418 | pushScope(); | ||
| 3419 | } | ||
| 3420 | } | ||
| 3421 | transformAssignment(assignment, preDefines); | ||
| 3422 | stack.push_back(varExp); | ||
| 3423 | goto reduce; | ||
| 3424 | } | ||
| 3425 | } | ||
| 3426 | { | ||
| 3427 | auto condExp = node->new_ptr<Exp_t>(); | ||
| 3428 | condExp->pipeExprs.dup(*item.second); | ||
| 3429 | stack.push_back(condExp); | ||
| 3430 | } | ||
| 3431 | reduce: | ||
| 3432 | if (stack.size() == 3) { | ||
| 3433 | str_list tmp; | ||
| 3434 | auto one = std::get<ast_ptr<false, Exp_t>>(stack.front()).get(); | ||
| 3435 | transformExp(one, tmp, ExpUsage::Closure); | ||
| 3436 | stack.pop_front(); | ||
| 3437 | auto two = std::get<std::string>(stack.front()); | ||
| 3438 | tmp.push_back(two); | ||
| 3439 | stack.pop_front(); | ||
| 3440 | auto three = std::get<ast_ptr<false, Exp_t>>(stack.front()).get(); | ||
| 3441 | transformExp(three, tmp, ExpUsage::Closure); | ||
| 3442 | conds.push_back(join(tmp, " "sv)); | ||
| 3443 | } | ||
| 3444 | } | ||
| 3445 | auto condStr = join(conds, " and "sv); | ||
| 3446 | if (needWrapping && usage == ExpUsage::Closure) { | ||
| 3447 | str_list closureLines{anonFuncStart() + nll(exp)}; | ||
| 3448 | closureLines.insert(closureLines.end(), preDefines.begin(), preDefines.end()); | ||
| 3449 | closureLines.push_back(indent() + "return "s + condStr + nll(exp)); | ||
| 3450 | popScope(); | ||
| 3451 | closureLines.push_back(indent() + anonFuncEnd()); | ||
| 3452 | temp.push_back(join(closureLines)); | ||
| 3453 | popAnonVarArg(); | ||
| 3454 | popFunctionScope(); | ||
| 3455 | } else { | ||
| 3456 | temp.push_back(condStr); | ||
| 3457 | if (!preDefines.empty()) { | ||
| 3458 | evalLines.insert(evalLines.end(), preDefines.begin(), preDefines.end()); | ||
| 3459 | if (usage == ExpUsage::Assignment) { | ||
| 3460 | popScope(); | ||
| 3461 | } | ||
| 3462 | } | ||
| 3463 | } | ||
| 3464 | } else { | ||
| 3465 | for (const auto& item : chains) { | ||
| 3466 | if (!item.first.empty()) { | ||
| 3467 | temp.push_back(item.first); | ||
| 3468 | } | ||
| 3469 | transform_pipe_exp(item.second->objects(), temp, ExpUsage::Closure); | ||
| 3470 | } | ||
| 3471 | } | ||
| 3472 | conditionChainCount = 0; | ||
| 3473 | chains.clear(); | ||
| 3474 | }; | ||
| 3475 | str_list preDefines; | ||
| 3312 | for (auto _opValue : exp->opValues.objects()) { | 3476 | for (auto _opValue : exp->opValues.objects()) { | 
| 3313 | auto opValue = static_cast<ExpOpValue_t*>(_opValue); | 3477 | auto opValue = static_cast<ExpOpValue_t*>(_opValue); | 
| 3314 | transformBinaryOperator(opValue->op, temp); | 3478 | transformBinaryOperator(opValue->op, temp); | 
| 3315 | transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure); | 3479 | auto op = temp.back(); | 
| 3480 | temp.pop_back(); | ||
| 3481 | if (isConditionChainingOperator(op)) { | ||
| 3482 | conditionChainCount++; | ||
| 3483 | chains.emplace_back(op, &opValue->pipeExprs); | ||
| 3484 | } else { | ||
| 3485 | checkChains(); | ||
| 3486 | temp.push_back(op); | ||
| 3487 | transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure); | ||
| 3488 | } | ||
| 3489 | } | ||
| 3490 | checkChains(); | ||
| 3491 | auto condStr = join(temp, " "sv); | ||
| 3492 | switch (usage) { | ||
| 3493 | case ExpUsage::Closure: { | ||
| 3494 | out.push_back(condStr); | ||
| 3495 | break; | ||
| 3496 | } | ||
| 3497 | case ExpUsage::Assignment: { | ||
| 3498 | auto assignment = exp->new_ptr<ExpListAssign_t>(); | ||
| 3499 | assignment->expList.set(assignList); | ||
| 3500 | auto assign = exp->new_ptr<Assign_t>(); | ||
| 3501 | assign->values.push_back(toAst<Exp_t>(condStr, exp)); | ||
| 3502 | assignment->action.set(assign); | ||
| 3503 | if (evalLines.empty()) { | ||
| 3504 | transformAssignment(assignment, out); | ||
| 3505 | } else { | ||
| 3506 | evalLines.push_front(indent() + "do"s + nll(exp)); | ||
| 3507 | evalLines.push_front(getPreDefineLine(assignment)); | ||
| 3508 | pushScope(); | ||
| 3509 | transformAssignment(assignment, evalLines); | ||
| 3510 | popScope(); | ||
| 3511 | evalLines.push_back(indent() + "end"s + nlr(exp)); | ||
| 3512 | out.push_back(join(evalLines)); | ||
| 3513 | } | ||
| 3514 | break; | ||
| 3515 | } | ||
| 3516 | case ExpUsage::Return: { | ||
| 3517 | evalLines.push_back(indent() + "return "s + condStr + nll(exp)); | ||
| 3518 | out.push_back(join(evalLines)); | ||
| 3519 | break; | ||
| 3520 | } | ||
| 3521 | default: YUEE("invalid expression usage", exp); break; | ||
| 3316 | } | 3522 | } | 
| 3317 | out.push_back(join(temp, " "sv)); | ||
| 3318 | } | 3523 | } | 
| 3319 | 3524 | ||
| 3320 | void transformNilCoalesedExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool nilBranchOnly = false) { | 3525 | void transformNilCoalesedExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool nilBranchOnly = false) { | 
| 3321 | auto x = exp; | 3526 | auto x = exp; | 
| 3322 | str_list temp; | 3527 | str_list temp; | 
| 3323 | std::string prefix; | ||
| 3324 | auto left = exp->new_ptr<Exp_t>(); | 3528 | auto left = exp->new_ptr<Exp_t>(); | 
| 3325 | if (exp->opValues.empty()) { | 3529 | if (exp->opValues.empty()) { | 
| 3326 | left->pipeExprs.dup(exp->pipeExprs); | 3530 | left->pipeExprs.dup(exp->pipeExprs); | 
| @@ -3328,20 +3532,16 @@ private: | |||
| 3328 | if (usage != ExpUsage::Closure) { | 3532 | if (usage != ExpUsage::Closure) { | 
| 3329 | YUEE("invalid expression usage", exp); | 3533 | YUEE("invalid expression usage", exp); | 
| 3330 | } | 3534 | } | 
| 3331 | transform_pipe_exp(exp->pipeExprs.objects(), temp, ExpUsage::Closure); | 3535 | auto last = static_cast<ExpOpValue_t*>(exp->opValues.back()); | 
| 3332 | auto last = exp->opValues.objects().back(); | 3536 | left->pipeExprs.dup(last->pipeExprs); | 
| 3333 | for (auto _opValue : exp->opValues.objects()) { | 3537 | |
| 3334 | auto opValue = static_cast<ExpOpValue_t*>(_opValue); | 3538 | auto startExp = x->new_ptr<Exp_t>(); | 
| 3335 | transformBinaryOperator(opValue->op, temp); | 3539 | startExp->pipeExprs.dup(exp->pipeExprs); | 
| 3336 | if (opValue == last) { | 3540 | startExp->opValues.dup(exp->opValues); | 
| 3337 | left->pipeExprs.dup(opValue->pipeExprs); | 3541 | startExp->opValues.pop_back(); | 
| 3338 | } else { | 3542 | transformExp(startExp, temp, ExpUsage::Closure); | 
| 3339 | transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure); | 3543 | transformBinaryOperator(last->op, temp); | 
| 3340 | } | 3544 | temp.back() = " "s + temp.back() + " "s; | 
| 3341 | } | ||
| 3342 | prefix = join(temp, " "sv) + ' '; | ||
| 3343 | temp.clear(); | ||
| 3344 | temp.push_back(prefix); | ||
| 3345 | } | 3545 | } | 
| 3346 | std::string* funcStart = nullptr; | 3546 | std::string* funcStart = nullptr; | 
| 3347 | if (usage == ExpUsage::Closure) { | 3547 | if (usage == ExpUsage::Closure) { | 
| @@ -4303,6 +4503,9 @@ private: | |||
| 4303 | } else if (auto unary = unaryGeneratingAnonFunc(exp)) { | 4503 | } else if (auto unary = unaryGeneratingAnonFunc(exp)) { | 
| 4304 | transformUnaryExp(unary, out, ExpUsage::Return); | 4504 | transformUnaryExp(unary, out, ExpUsage::Return); | 
| 4305 | return; | 4505 | return; | 
| 4506 | } else if (isConditionChaining(exp)) { | ||
| 4507 | transformExp(exp, out, ExpUsage::Return); | ||
| 4508 | return; | ||
| 4306 | } | 4509 | } | 
| 4307 | } | 4510 | } | 
| 4308 | if (auto singleValue = singleValueFrom(valueList)) { | 4511 | if (auto singleValue = singleValueFrom(valueList)) { | 
| @@ -5791,6 +5994,24 @@ private: | |||
| 5791 | return; | 5994 | return; | 
| 5792 | } | 5995 | } | 
| 5793 | } | 5996 | } | 
| 5997 | auto discrete = unary_exp->inExp->item.to<InDiscrete_t>(); | ||
| 5998 | if (usage == ExpUsage::Closure && discrete->values.size() == 1) { | ||
| 5999 | str_list tmp; | ||
| 6000 | transformExp(static_cast<Exp_t*>(discrete->values.front()), tmp, ExpUsage::Closure); | ||
| 6001 | tmp.push_back(" == "s); | ||
| 6002 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); | ||
| 6003 | newUnaryExp->ops.dup(unary_exp->ops); | ||
| 6004 | newUnaryExp->expos.dup(unary_exp->expos); | ||
| 6005 | transformUnaryExp(newUnaryExp, tmp, ExpUsage::Closure); | ||
| 6006 | tmp.push_back(")"s); | ||
| 6007 | if (unary_exp->inExp->not_) { | ||
| 6008 | tmp.push_front("not ("s); | ||
| 6009 | } else { | ||
| 6010 | tmp.push_front("("s); | ||
| 6011 | } | ||
| 6012 | out.push_back(join(tmp)); | ||
| 6013 | return; | ||
| 6014 | } | ||
| 5794 | if (varName.empty()) { | 6015 | if (varName.empty()) { | 
| 5795 | str_list temp; | 6016 | str_list temp; | 
| 5796 | if (usage == ExpUsage::Closure) { | 6017 | if (usage == ExpUsage::Closure) { | 
| @@ -5809,54 +6030,32 @@ private: | |||
| 5809 | auto assignExp = toAst<Exp_t>(newVar, x); | 6030 | auto assignExp = toAst<Exp_t>(newVar, x); | 
| 5810 | auto assignment = assignmentFrom(assignExp, exp, x); | 6031 | auto assignment = assignmentFrom(assignExp, exp, x); | 
| 5811 | transformAssignment(assignment, temp); | 6032 | transformAssignment(assignment, temp); | 
| 5812 | if (auto range = unary_exp->inExp->item.as<InRange_t>()) { | 6033 | |
| 5813 | str_list tmp; | 6034 | str_list tmp; | 
| 5814 | transformExp(range->openValue, tmp, ExpUsage::Closure); | 6035 | for (auto exp : discrete->values.objects()) { | 
| 5815 | transformExp(range->closeValue, tmp, ExpUsage::Closure); | 6036 | transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); | 
| 5816 | if (usage == ExpUsage::Assignment) { | 6037 | } | 
| 5817 | str_list tmpList; | 6038 | if (usage == ExpUsage::Assignment) { | 
| 5818 | transformExp(static_cast<Exp_t*>(assignList->exprs.front()), tmpList, ExpUsage::Closure); | 6039 | str_list tmpList; | 
| 5819 | _buf << indent() << tmpList.back() << " = "sv; | 6040 | transformExp(static_cast<Exp_t*>(assignList->exprs.front()), tmpList, ExpUsage::Closure); | 
| 5820 | } else { | 6041 | _buf << indent() << tmpList.back() << " = "sv; | 
| 5821 | _buf << indent() << "return "sv; | ||
| 5822 | } | ||
| 5823 | if (unary_exp->inExp->not_) { | ||
| 5824 | _buf << "not ("sv; | ||
| 5825 | } | ||
| 5826 | _buf << tmp.front() << (range->open.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << newVar << " and "sv << newVar << (range->close.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << tmp.back(); | ||
| 5827 | if (unary_exp->inExp->not_) { | ||
| 5828 | _buf << ")"sv; | ||
| 5829 | } | ||
| 5830 | _buf << nll(x); | ||
| 5831 | temp.push_back(clearBuf()); | ||
| 5832 | } else { | 6042 | } else { | 
| 5833 | auto discrete = unary_exp->inExp->item.to<InDiscrete_t>(); | 6043 | _buf << indent() << "return "sv; | 
| 5834 | str_list tmp; | 6044 | } | 
| 5835 | for (auto exp : discrete->values.objects()) { | 6045 | if (unary_exp->inExp->not_) { | 
| 5836 | transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); | 6046 | _buf << "not ("sv; | 
| 5837 | } | 6047 | } | 
| 5838 | if (usage == ExpUsage::Assignment) { | 6048 | for (const auto& exp : tmp) { | 
| 5839 | str_list tmpList; | 6049 | _buf << exp << " == "sv << newVar; | 
| 5840 | transformExp(static_cast<Exp_t*>(assignList->exprs.front()), tmpList, ExpUsage::Closure); | 6050 | if (exp != tmp.back()) { | 
| 5841 | _buf << indent() << tmpList.back() << " = "sv; | 6051 | _buf << " or "sv; | 
| 5842 | } else { | ||
| 5843 | _buf << indent() << "return "sv; | ||
| 5844 | } | ||
| 5845 | if (unary_exp->inExp->not_) { | ||
| 5846 | _buf << "not ("sv; | ||
| 5847 | } | ||
| 5848 | for (const auto& exp : tmp) { | ||
| 5849 | _buf << exp << " == "sv << newVar; | ||
| 5850 | if (exp != tmp.back()) { | ||
| 5851 | _buf << " or "sv; | ||
| 5852 | } | ||
| 5853 | } | ||
| 5854 | if (unary_exp->inExp->not_) { | ||
| 5855 | _buf << ")"sv; | ||
| 5856 | } | 6052 | } | 
| 5857 | _buf << nll(x); | ||
| 5858 | temp.push_back(clearBuf()); | ||
| 5859 | } | 6053 | } | 
| 6054 | if (unary_exp->inExp->not_) { | ||
| 6055 | _buf << ")"sv; | ||
| 6056 | } | ||
| 6057 | _buf << nll(x); | ||
| 6058 | temp.push_back(clearBuf()); | ||
| 5860 | if (usage == ExpUsage::Closure) { | 6059 | if (usage == ExpUsage::Closure) { | 
| 5861 | temp.push_front(anonFuncStart() + nll(x)); | 6060 | temp.push_front(anonFuncStart() + nll(x)); | 
| 5862 | popScope(); | 6061 | popScope(); | 
| @@ -5872,35 +6071,22 @@ private: | |||
| 5872 | out.push_back(join(temp)); | 6071 | out.push_back(join(temp)); | 
| 5873 | } | 6072 | } | 
| 5874 | } else { | 6073 | } else { | 
| 5875 | if (auto range = unary_exp->inExp->item.as<InRange_t>()) { | 6074 | str_list tmp; | 
| 5876 | str_list tmp; | 6075 | for (auto exp : discrete->values.objects()) { | 
| 5877 | transformExp(range->openValue, tmp, ExpUsage::Closure); | 6076 | transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); | 
| 5878 | transformExp(range->closeValue, tmp, ExpUsage::Closure); | 6077 | } | 
| 5879 | if (unary_exp->inExp->not_) { | 6078 | if (unary_exp->inExp->not_) { | 
| 5880 | _buf << "not "sv; | 6079 | _buf << "not "sv; | 
| 5881 | } | 6080 | } | 
| 5882 | _buf << '(' << tmp.front() << (range->open.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << varName << " and "sv << varName << (range->close.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << tmp.back(); | 6081 | _buf << '('; | 
| 5883 | _buf << ')'; | 6082 | for (const auto& exp : tmp) { | 
| 5884 | out.push_back(clearBuf()); | 6083 | _buf << exp << " == "sv << varName; | 
| 5885 | } else { | 6084 | if (exp != tmp.back()) { | 
| 5886 | auto discrete = unary_exp->inExp->item.to<InDiscrete_t>(); | 6085 | _buf << " or "sv; | 
| 5887 | str_list tmp; | ||
| 5888 | for (auto exp : discrete->values.objects()) { | ||
| 5889 | transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); | ||
| 5890 | } | ||
| 5891 | if (unary_exp->inExp->not_) { | ||
| 5892 | _buf << "not "sv; | ||
| 5893 | } | ||
| 5894 | _buf << '('; | ||
| 5895 | for (const auto& exp : tmp) { | ||
| 5896 | _buf << exp << " == "sv << varName; | ||
| 5897 | if (exp != tmp.back()) { | ||
| 5898 | _buf << " or "sv; | ||
| 5899 | } | ||
| 5900 | } | 6086 | } | 
| 5901 | _buf << ')'; | ||
| 5902 | out.push_back(clearBuf()); | ||
| 5903 | } | 6087 | } | 
| 6088 | _buf << ')'; | ||
| 6089 | out.push_back(clearBuf()); | ||
| 5904 | } | 6090 | } | 
| 5905 | return; | 6091 | return; | 
| 5906 | } | 6092 | } | 
| @@ -5945,7 +6131,7 @@ private: | |||
| 5945 | 6131 | ||
| 5946 | bool hasSpreadExp(const node_container& items) { | 6132 | bool hasSpreadExp(const node_container& items) { | 
| 5947 | for (auto item : items) { | 6133 | for (auto item : items) { | 
| 5948 | if (ast_is<SpreadExp_t>(item)) return true; | 6134 | if (ast_is<SpreadExp_t, SpreadListExp_t>(item)) return true; | 
| 5949 | } | 6135 | } | 
| 5950 | return false; | 6136 | return false; | 
| 5951 | } | 6137 | } | 
| @@ -5968,11 +6154,11 @@ private: | |||
| 5968 | std::string tableVar = getUnusedName("_tab_"sv); | 6154 | std::string tableVar = getUnusedName("_tab_"sv); | 
| 5969 | forceAddToScope(tableVar); | 6155 | forceAddToScope(tableVar); | 
| 5970 | auto it = values.begin(); | 6156 | auto it = values.begin(); | 
| 5971 | if (ast_is<SpreadExp_t>(*it)) { | 6157 | if (ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { | 
| 5972 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); | 6158 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); | 
| 5973 | } else { | 6159 | } else { | 
| 5974 | auto initialTab = x->new_ptr<TableLit_t>(); | 6160 | auto initialTab = x->new_ptr<TableLit_t>(); | 
| 5975 | while (it != values.end() && !ast_is<SpreadExp_t>(*it)) { | 6161 | while (it != values.end() && !ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { | 
| 5976 | initialTab->values.push_back(*it); | 6162 | initialTab->values.push_back(*it); | 
| 5977 | ++it; | 6163 | ++it; | 
| 5978 | } | 6164 | } | 
| @@ -6007,6 +6193,28 @@ private: | |||
| 6007 | transformForEach(forEach, temp); | 6193 | transformForEach(forEach, temp); | 
| 6008 | break; | 6194 | break; | 
| 6009 | } | 6195 | } | 
| 6196 | case id<SpreadListExp_t>(): { | ||
| 6197 | auto spread = static_cast<SpreadListExp_t*>(item); | ||
| 6198 | std::string indexVar = getUnusedName("_idx_"sv); | ||
| 6199 | std::string valueVar = getUnusedName("_value_"sv); | ||
| 6200 | auto objVar = singleVariableFrom(spread->exp, true); | ||
| 6201 | if (objVar.empty()) { | ||
| 6202 | objVar = getUnusedName("_obj_"); | ||
| 6203 | auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); | ||
| 6204 | auto assign = assignment->action.to<Assign_t>(); | ||
| 6205 | assign->values.clear(); | ||
| 6206 | assign->values.push_back(spread->exp); | ||
| 6207 | transformAssignment(assignment, temp); | ||
| 6208 | } | ||
| 6209 | forceAddToScope(indexVar); | ||
| 6210 | temp.push_back(indent() + "local "s + indexVar + " = #"s + tableVar + " + 1"s + nll(item)); | ||
| 6211 | _buf << "for "sv << valueVar << " in *"sv << objVar | ||
| 6212 | << "\n\t"sv << tableVar << '[' << indexVar << "]="sv << valueVar | ||
| 6213 | << "\n\t"sv << indexVar << "+=1"sv; | ||
| 6214 | auto forEach = toAst<ForEach_t>(clearBuf(), item); | ||
| 6215 | transformForEach(forEach, temp); | ||
| 6216 | break; | ||
| 6217 | } | ||
| 6010 | case id<VariablePair_t>(): | 6218 | case id<VariablePair_t>(): | 
| 6011 | case id<VariablePairDef_t>(): { | 6219 | case id<VariablePairDef_t>(): { | 
| 6012 | if (auto pair = ast_cast<VariablePairDef_t>(item)) { | 6220 | if (auto pair = ast_cast<VariablePairDef_t>(item)) { | 
| @@ -6374,7 +6582,7 @@ private: | |||
| 6374 | void transformCompCommon(Comprehension_t* comp, str_list& out) { | 6582 | void transformCompCommon(Comprehension_t* comp, str_list& out) { | 
| 6375 | str_list temp; | 6583 | str_list temp; | 
| 6376 | auto x = comp; | 6584 | auto x = comp; | 
| 6377 | auto compInner = comp->forLoop.get(); | 6585 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); | 
| 6378 | for (auto item : compInner->items.objects()) { | 6586 | for (auto item : compInner->items.objects()) { | 
| 6379 | switch (item->get_id()) { | 6587 | switch (item->get_id()) { | 
| 6380 | case id<CompForEach_t>(): | 6588 | case id<CompForEach_t>(): | 
| @@ -6391,9 +6599,9 @@ private: | |||
| 6391 | default: YUEE("AST node mismatch", item); break; | 6599 | default: YUEE("AST node mismatch", item); break; | 
| 6392 | } | 6600 | } | 
| 6393 | } | 6601 | } | 
| 6394 | if (auto stmt = comp->value.as<Statement_t>()) { | 6602 | if (auto stmt = ast_cast<Statement_t>(comp->items.front())) { | 
| 6395 | transformStatement(stmt, temp); | 6603 | transformStatement(stmt, temp); | 
| 6396 | } else if (auto exp = comp->value.as<Exp_t>()) { | 6604 | } else if (auto exp = ast_cast<Exp_t>(comp->items.front())) { | 
| 6397 | auto expList = x->new_ptr<ExpList_t>(); | 6605 | auto expList = x->new_ptr<ExpList_t>(); | 
| 6398 | expList->exprs.push_back(exp); | 6606 | expList->exprs.push_back(exp); | 
| 6399 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | 6607 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | 
| @@ -6414,6 +6622,48 @@ private: | |||
| 6414 | 6622 | ||
| 6415 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 6623 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 
| 6416 | auto x = comp; | 6624 | auto x = comp; | 
| 6625 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | ||
| 6626 | auto tableLit = x->new_ptr<TableLit_t>(); | ||
| 6627 | tableLit->values.dup(comp->items); | ||
| 6628 | switch (usage) { | ||
| 6629 | case ExpUsage::Assignment: { | ||
| 6630 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 6631 | simpleValue->value.set(tableLit); | ||
| 6632 | auto exp = newExp(simpleValue, x); | ||
| 6633 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6634 | assignment->expList.set(assignList); | ||
| 6635 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6636 | assign->values.push_back(exp); | ||
| 6637 | assignment->action.set(assign); | ||
| 6638 | transformAssignment(assignment, out); | ||
| 6639 | break; | ||
| 6640 | } | ||
| 6641 | case ExpUsage::Return: { | ||
| 6642 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 6643 | simpleValue->value.set(tableLit); | ||
| 6644 | auto exp = newExp(simpleValue, x); | ||
| 6645 | auto returnNode = x->new_ptr<Return_t>(); | ||
| 6646 | auto expList = x->new_ptr<ExpListLow_t>(); | ||
| 6647 | expList->exprs.push_back(exp); | ||
| 6648 | returnNode->valueList.set(expList); | ||
| 6649 | transformReturn(returnNode, out); | ||
| 6650 | break; | ||
| 6651 | } | ||
| 6652 | case ExpUsage::Closure: | ||
| 6653 | transformTableLit(tableLit, out); | ||
| 6654 | break; | ||
| 6655 | default: | ||
| 6656 | YUEE("invalid comprehension usage", comp); | ||
| 6657 | break; | ||
| 6658 | } | ||
| 6659 | return; | ||
| 6660 | } | ||
| 6661 | auto def = ast_cast<NormalDef_t>(comp->items.front()); | ||
| 6662 | if (!def || def->defVal) { | ||
| 6663 | throw CompileError("invalid comprehension expression", comp->items.front()); | ||
| 6664 | } | ||
| 6665 | auto value = def->item.get(); | ||
| 6666 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); | ||
| 6417 | switch (usage) { | 6667 | switch (usage) { | 
| 6418 | case ExpUsage::Closure: | 6668 | case ExpUsage::Closure: | 
| 6419 | pushFunctionScope(); | 6669 | pushFunctionScope(); | 
| @@ -6431,7 +6681,6 @@ private: | |||
| 6431 | std::string lenVar = getUnusedName("_len_"sv); | 6681 | std::string lenVar = getUnusedName("_len_"sv); | 
| 6432 | addToScope(accumVar); | 6682 | addToScope(accumVar); | 
| 6433 | addToScope(lenVar); | 6683 | addToScope(lenVar); | 
| 6434 | auto compInner = comp->forLoop.get(); | ||
| 6435 | for (auto item : compInner->items.objects()) { | 6684 | for (auto item : compInner->items.objects()) { | 
| 6436 | switch (item->get_id()) { | 6685 | switch (item->get_id()) { | 
| 6437 | case id<CompForEach_t>(): | 6686 | case id<CompForEach_t>(): | 
| @@ -6451,7 +6700,7 @@ private: | |||
| 6451 | { | 6700 | { | 
| 6452 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 6701 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 
| 6453 | auto assign = x->new_ptr<Assign_t>(); | 6702 | auto assign = x->new_ptr<Assign_t>(); | 
| 6454 | assign->values.push_back(comp->value); | 6703 | assign->values.push_back(value); | 
| 6455 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 6704 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 
| 6456 | assignment->expList.set(assignLeft); | 6705 | assignment->expList.set(assignLeft); | 
| 6457 | assignment->action.set(assign); | 6706 | assignment->action.set(assign); | 
| @@ -8830,19 +9079,7 @@ private: | |||
| 8830 | std::string tabCheckVar; | 9079 | std::string tabCheckVar; | 
| 8831 | for (auto branch_ : branches) { | 9080 | for (auto branch_ : branches) { | 
| 8832 | auto branch = static_cast<SwitchCase_t*>(branch_); | 9081 | auto branch = static_cast<SwitchCase_t*>(branch_); | 
| 8833 | if (auto inExp = branch->condition.as<In_t>()) { | 9082 | auto valueList = static_cast<SwitchList_t*>(branch->condition.get()); | 
| 8834 | auto unary = branch->new_ptr<UnaryExp_t>(); | ||
| 8835 | unary->expos.push_back(toAst<Value_t>(objVar, branch)); | ||
| 8836 | unary->inExp.set(inExp); | ||
| 8837 | transformUnaryExp(unary, temp, ExpUsage::Closure); | ||
| 8838 | temp.back() = indent() + (firstBranch ? "if "s : "elseif "s) + temp.back() + " then"s + nll(branch); | ||
| 8839 | pushScope(); | ||
| 8840 | transform_plain_body(branch->body, temp, usage, assignList); | ||
| 8841 | popScope(); | ||
| 8842 | firstBranch = false; | ||
| 8843 | continue; | ||
| 8844 | } | ||
| 8845 | auto valueList = branch->condition.to<SwitchList_t>(); | ||
| 8846 | if (auto value = singleValueFrom(valueList); | 9083 | if (auto value = singleValueFrom(valueList); | 
| 8847 | value && (value->item.is<SimpleTable_t>() || value->get_by_path<SimpleValue_t, TableLit_t>())) { | 9084 | value && (value->item.is<SimpleTable_t>() || value->get_by_path<SimpleValue_t, TableLit_t>())) { | 
| 8848 | if (!firstBranch) { | 9085 | if (!firstBranch) { | 
| diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index c818098..8ceee9a 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -109,6 +109,11 @@ YueParser::YueParser() { | |||
| 109 | return false; | 109 | return false; | 
| 110 | }); | 110 | }); | 
| 111 | 111 | ||
| 112 | table_key_pair_error = pl::user(true_(), [](const item_t& item) { | ||
| 113 | throw ParserError("can not put hash pair in a list"sv, item.begin); | ||
| 114 | return false; | ||
| 115 | }); | ||
| 116 | |||
| 112 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut) | 117 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut) | 
| 113 | 118 | ||
| 114 | #define key(str) (expr(str) >> not_alpha_num) | 119 | #define key(str) (expr(str) >> not_alpha_num) | 
| @@ -342,7 +347,7 @@ YueParser::YueParser() { | |||
| 342 | with_exp = ExpList >> -(space >> Assign); | 347 | with_exp = ExpList >> -(space >> Assign); | 
| 343 | 348 | ||
| 344 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 349 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 
| 345 | SwitchCase = key("when") >> space >> (disable_chain_rule(disable_arg_table_block_rule(SwitchList)) | In) >> space >> body_with("then"); | 350 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); | 
| 346 | switch_else = key("else") >> space >> body; | 351 | switch_else = key("else") >> space >> body; | 
| 347 | 352 | ||
| 348 | switch_block = | 353 | switch_block = | 
| @@ -449,7 +454,37 @@ YueParser::YueParser() { | |||
| 449 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; | 454 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; | 
| 450 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; | 455 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; | 
| 451 | 456 | ||
| 452 | Comprehension = '[' >> not_('[') >> space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']'; | 457 | list_value = | 
| 458 | and_( | ||
| 459 | VariablePairDef | | ||
| 460 | NormalPairDef | | ||
| 461 | MetaVariablePairDef | | ||
| 462 | MetaNormalPairDef | ||
| 463 | ) >> table_key_pair_error | | ||
| 464 | SpreadListExp | | ||
| 465 | NormalDef; | ||
| 466 | |||
| 467 | list_value_list = +(space >> ',' >> space >> list_value); | ||
| 468 | |||
| 469 | list_lit_line = ( | ||
| 470 | push_indent_match >> (space >> list_value >> -list_value_list >> pop_indent | pop_indent) | ||
| 471 | ) | ( | ||
| 472 | space | ||
| 473 | ); | ||
| 474 | |||
| 475 | list_lit_lines = space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); | ||
| 476 | |||
| 477 | Comprehension = '[' >> not_('[') >> | ||
| 478 | Seperator >> space >> ( | ||
| 479 | disable_for_rule(list_value) >> space >> ( | ||
| 480 | CompInner >> space >> ']' | | ||
| 481 | (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> ']' | ||
| 482 | ) | | ||
| 483 | list_lit_lines >> white >> ']' | | ||
| 484 | white >> ']' >> not_(space >> '=') | ||
| 485 | ); | ||
| 486 | |||
| 487 | (space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']'); | ||
| 453 | CompValue = ',' >> space >> Exp; | 488 | CompValue = ',' >> space >> Exp; | 
| 454 | TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); | 489 | TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); | 
| 455 | 490 | ||
| @@ -479,12 +514,11 @@ YueParser::YueParser() { | |||
| 479 | expo_value = exponential_operator >> *space_break >> space >> Value; | 514 | expo_value = exponential_operator >> *space_break >> space >> Value; | 
| 480 | expo_exp = Value >> *(space >> expo_value); | 515 | expo_exp = Value >> *(space >> expo_value); | 
| 481 | 516 | ||
| 482 | InRangeOpen = true_(); | ||
| 483 | InRangeClose = true_(); | ||
| 484 | NotIn = true_(); | 517 | NotIn = true_(); | 
| 485 | InRange = ('(' >> InRangeOpen | '[' >> InRangeClose) >> space >> Exp >> space >> ',' >> space >> Exp >> space >> (')' >> InRangeOpen | ']' >> InRangeClose); | 518 | InDiscrete = | 
| 486 | InDiscrete = '{' >> Seperator >> space >> exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) >> space >> '}'; | 519 | '[' >> Seperator >> space >> exp_not_tab >> (+(space >> ',' >> space >> exp_not_tab) | space >> ',') >> space >> ']' | | 
| 487 | In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InRange | InDiscrete | and_(key("not")) >> confusing_unary_not_error | Exp); | 520 | '{' >> Seperator >> space >> exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) >> space >> '}'; | 
| 521 | In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InDiscrete | and_(key("not")) >> confusing_unary_not_error | Exp); | ||
| 488 | 522 | ||
| 489 | UnaryOperator = | 523 | UnaryOperator = | 
| 490 | '-' >> not_(set(">=") | space_one) | | 524 | '-' >> not_(set(">=") | space_one) | | 
| @@ -635,7 +669,7 @@ YueParser::YueParser() { | |||
| 635 | space >> ',' >> | 669 | space >> ',' >> | 
| 636 | space >> (Exp | DefaultValue) >> | 670 | space >> (Exp | DefaultValue) >> | 
| 637 | space >> (',' >> space >> Exp | DefaultValue) >> | 671 | space >> (',' >> space >> Exp | DefaultValue) >> | 
| 638 | space >> ']'; | 672 | space >> (']' | slice_expression_error); | 
| 639 | 673 | ||
| 640 | Invoke = Seperator >> ( | 674 | Invoke = Seperator >> ( | 
| 641 | fn_args | | 675 | fn_args | | 
| @@ -646,6 +680,7 @@ YueParser::YueParser() { | |||
| 646 | ); | 680 | ); | 
| 647 | 681 | ||
| 648 | SpreadExp = "..." >> space >> Exp; | 682 | SpreadExp = "..." >> space >> Exp; | 
| 683 | SpreadListExp = "..." >> space >> Exp; | ||
| 649 | 684 | ||
| 650 | table_value = | 685 | table_value = | 
| 651 | VariablePairDef | | 686 | VariablePairDef | | 
| @@ -667,8 +702,7 @@ YueParser::YueParser() { | |||
| 667 | 702 | ||
| 668 | TableLit = | 703 | TableLit = | 
| 669 | space >> '{' >> Seperator >> | 704 | space >> '{' >> Seperator >> | 
| 670 | -(space >> table_value_list) >> | 705 | -(space >> table_value_list >> -(space >> ',')) >> | 
| 671 | -(space >> ',') >> | ||
| 672 | -table_lit_lines >> | 706 | -table_lit_lines >> | 
| 673 | white >> '}'; | 707 | white >> '}'; | 
| 674 | 708 | ||
| @@ -834,7 +868,7 @@ YueParser::YueParser() { | |||
| 834 | }); | 868 | }); | 
| 835 | 869 | ||
| 836 | InvokeArgs = | 870 | InvokeArgs = | 
| 837 | not_(set("-~")) >> space >> Seperator >> ( | 871 | not_(set("-~") | "[]") >> space >> Seperator >> ( | 
| 838 | Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) | | 872 | Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) | | 
| 839 | arg_table_block | | 873 | arg_table_block | | 
| 840 | leading_spaces_error | 874 | leading_spaces_error | 
| @@ -852,6 +886,11 @@ YueParser::YueParser() { | |||
| 852 | return false; | 886 | return false; | 
| 853 | }); | 887 | }); | 
| 854 | 888 | ||
| 889 | slice_expression_error = pl::user(true_(), [](const item_t& item) { | ||
| 890 | throw ParserError("syntax error in slice expression"sv, item.begin); | ||
| 891 | return false; | ||
| 892 | }); | ||
| 893 | |||
| 855 | SimpleValue = | 894 | SimpleValue = | 
| 856 | TableLit | ConstValue | If | Switch | Try | With | | 895 | TableLit | ConstValue | If | Switch | Try | With | | 
| 857 | ClassDecl | ForEach | For | While | Do | | 896 | ClassDecl | ForEach | For | While | Do | | 
| diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 7864300..8156ae2 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -136,9 +136,11 @@ private: | |||
| 136 | NONE_AST_RULE(indentation_error); | 136 | NONE_AST_RULE(indentation_error); | 
| 137 | NONE_AST_RULE(braces_expression_error); | 137 | NONE_AST_RULE(braces_expression_error); | 
| 138 | NONE_AST_RULE(brackets_expression_error); | 138 | NONE_AST_RULE(brackets_expression_error); | 
| 139 | NONE_AST_RULE(slice_expression_error); | ||
| 139 | NONE_AST_RULE(export_expression_error); | 140 | NONE_AST_RULE(export_expression_error); | 
| 140 | NONE_AST_RULE(invalid_interpolation_error); | 141 | NONE_AST_RULE(invalid_interpolation_error); | 
| 141 | NONE_AST_RULE(confusing_unary_not_error); | 142 | NONE_AST_RULE(confusing_unary_not_error); | 
| 143 | NONE_AST_RULE(table_key_pair_error); | ||
| 142 | 144 | ||
| 143 | NONE_AST_RULE(inc_exp_level); | 145 | NONE_AST_RULE(inc_exp_level); | 
| 144 | NONE_AST_RULE(dec_exp_level); | 146 | NONE_AST_RULE(dec_exp_level); | 
| @@ -202,6 +204,10 @@ private: | |||
| 202 | NONE_AST_RULE(for_key); | 204 | NONE_AST_RULE(for_key); | 
| 203 | NONE_AST_RULE(for_args); | 205 | NONE_AST_RULE(for_args); | 
| 204 | NONE_AST_RULE(for_in); | 206 | NONE_AST_RULE(for_in); | 
| 207 | NONE_AST_RULE(list_value); | ||
| 208 | NONE_AST_RULE(list_value_list); | ||
| 209 | NONE_AST_RULE(list_lit_line); | ||
| 210 | NONE_AST_RULE(list_lit_lines); | ||
| 205 | NONE_AST_RULE(comp_clause); | 211 | NONE_AST_RULE(comp_clause); | 
| 206 | NONE_AST_RULE(chain); | 212 | NONE_AST_RULE(chain); | 
| 207 | NONE_AST_RULE(chain_list); | 213 | NONE_AST_RULE(chain_list); | 
| @@ -352,6 +358,7 @@ private: | |||
| 352 | AST_RULE(ExistentialOp); | 358 | AST_RULE(ExistentialOp); | 
| 353 | AST_RULE(TableAppendingOp); | 359 | AST_RULE(TableAppendingOp); | 
| 354 | AST_RULE(SpreadExp); | 360 | AST_RULE(SpreadExp); | 
| 361 | AST_RULE(SpreadListExp); | ||
| 355 | AST_RULE(TableLit); | 362 | AST_RULE(TableLit); | 
| 356 | AST_RULE(TableBlock); | 363 | AST_RULE(TableBlock); | 
| 357 | AST_RULE(TableBlockIndent); | 364 | AST_RULE(TableBlockIndent); | 
| @@ -388,10 +395,7 @@ private: | |||
| 388 | AST_RULE(ConstValue); | 395 | AST_RULE(ConstValue); | 
| 389 | AST_RULE(UnaryValue); | 396 | AST_RULE(UnaryValue); | 
| 390 | AST_RULE(UnaryExp); | 397 | AST_RULE(UnaryExp); | 
| 391 | AST_RULE(InRangeOpen); | ||
| 392 | AST_RULE(InRangeClose); | ||
| 393 | AST_RULE(NotIn); | 398 | AST_RULE(NotIn); | 
| 394 | AST_RULE(InRange); | ||
| 395 | AST_RULE(InDiscrete); | 399 | AST_RULE(InDiscrete); | 
| 396 | AST_RULE(In); | 400 | AST_RULE(In); | 
| 397 | AST_RULE(ExpListAssign); | 401 | AST_RULE(ExpListAssign); | 
