aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_ast.cpp27
-rw-r--r--src/yuescript/yue_ast.h34
-rw-r--r--src/yuescript/yue_compiler.cpp497
-rw-r--r--src/yuescript/yue_parser.cpp61
-rw-r--r--src/yuescript/yue_parser.h10
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}
185std::string InRangeOpen_t::to_string(void*) const {
186 return {};
187}
188std::string InRangeClose_t::to_string(void*) const {
189 return {};
190}
191std::string NotIn_t::to_string(void*) const { 185std::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}
571std::string Comprehension_t::to_string(void* ud) const { 565std::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}
575std::string CompValue_t::to_string(void* ud) const { 579std::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 {
830std::string SpreadExp_t::to_string(void* ud) const { 834std::string SpreadExp_t::to_string(void* ud) const {
831 return "..."s + exp->to_string(ud); 835 return "..."s + exp->to_string(ud);
832} 836}
837std::string SpreadListExp_t::to_string(void* ud) const {
838 return "..."s + exp->to_string(ud);
839}
833std::string TableLit_t::to_string(void* ud) const { 840std::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}
1171std::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}
1175std::string InDiscrete_t::to_string(void* ud) const { 1178std::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;
78class TableBlockIndent_t; 78class TableBlockIndent_t;
79class Macro_t; 79class Macro_t;
80class In_t; 80class In_t;
81class NormalDef_t;
82class SpreadListExp_t;
81} // namespace yue 83} // namespace yue
82 84
83AST_LEAF(Num) 85AST_LEAF(Num)
@@ -286,7 +288,7 @@ AST_NODE(SwitchList)
286AST_END(SwitchList, "switch_list"sv) 288AST_END(SwitchList, "switch_list"sv)
287 289
288AST_NODE(SwitchCase) 290AST_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)
292AST_END(SwitchCase, "switch_case"sv) 294AST_END(SwitchCase, "switch_case"sv)
@@ -374,9 +376,10 @@ AST_NODE(Try)
374AST_END(Try, "try"sv) 376AST_END(Try, "try"sv)
375 377
376AST_NODE(Comprehension) 378AST_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)
380AST_END(Comprehension, "comp"sv) 383AST_END(Comprehension, "comp"sv)
381 384
382AST_NODE(CompValue) 385AST_NODE(CompValue)
@@ -437,23 +440,9 @@ AST_END(BinaryOperator, "binary_op"sv)
437AST_LEAF(UnaryOperator) 440AST_LEAF(UnaryOperator)
438AST_END(UnaryOperator, "unary_op"sv) 441AST_END(UnaryOperator, "unary_op"sv)
439 442
440AST_LEAF(InRangeOpen)
441AST_END(InRangeOpen, "in_range_open"sv)
442
443AST_LEAF(InRangeClose)
444AST_END(InRangeClose, "in_range_close"sv)
445
446AST_LEAF(NotIn) 443AST_LEAF(NotIn)
447AST_END(NotIn, "not_in"sv) 444AST_END(NotIn, "not_in"sv)
448 445
449AST_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)
455AST_END(InRange, "in_range"sv)
456
457AST_NODE(InDiscrete) 446AST_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
463AST_NODE(In) 452AST_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, &not_, &item) 455 AST_MEMBER(In, &not_, &item)
467AST_END(In, "in"sv) 456AST_END(In, "in"sv)
468 457
@@ -666,6 +655,11 @@ AST_NODE(SpreadExp)
666 AST_MEMBER(SpreadExp, &exp) 655 AST_MEMBER(SpreadExp, &exp)
667AST_END(SpreadExp, "spread_exp"sv) 656AST_END(SpreadExp, "spread_exp"sv)
668 657
658AST_NODE(SpreadListExp)
659 ast_ptr<true, Exp_t> exp;
660 AST_MEMBER(SpreadListExp, &exp)
661AST_END(SpreadListExp, "spread_list_exp"sv)
662
669AST_NODE(TableLit) 663AST_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)
678AST_END(TableLit, "table_lit"sv) 672AST_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
77const std::string_view version = "0.19.6"sv; 78const std::string_view version = "0.20.0"sv;
78const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
79 80
80class CompileError : public std::logic_error { 81class 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);