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); |