diff options
Diffstat (limited to '')
| -rwxr-xr-x | src/yuescript/yue_ast.h | 8 | ||||
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 615 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.cpp | 9 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.h | 2 |
4 files changed, 374 insertions, 260 deletions
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 571c18e..05ac5ef 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -249,8 +249,14 @@ AST_NODE(With) | |||
| 249 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) | 249 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) |
| 250 | AST_END(With, "with"sv) | 250 | AST_END(With, "with"sv) |
| 251 | 251 | ||
| 252 | AST_NODE(SwitchList) | ||
| 253 | ast_ptr<true, Seperator_t> sep; | ||
| 254 | ast_list<true, Exp_t> exprs; | ||
| 255 | AST_MEMBER(SwitchList, &sep, &exprs) | ||
| 256 | AST_END(SwitchList, "switch_list"sv) | ||
| 257 | |||
| 252 | AST_NODE(SwitchCase) | 258 | AST_NODE(SwitchCase) |
| 253 | ast_ptr<true, ExpList_t> valueList; | 259 | ast_ptr<true, SwitchList_t> valueList; |
| 254 | ast_sel<true, Block_t, Statement_t> body; | 260 | ast_sel<true, Block_t, Statement_t> body; |
| 255 | AST_MEMBER(SwitchCase, &valueList, &body) | 261 | AST_MEMBER(SwitchCase, &valueList, &body) |
| 256 | AST_END(SwitchCase, "switch_case"sv) | 262 | AST_END(SwitchCase, "switch_case"sv) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 84cbf37..468dc23 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -56,7 +56,7 @@ using namespace parserlib; | |||
| 56 | 56 | ||
| 57 | typedef std::list<std::string> str_list; | 57 | typedef std::list<std::string> str_list; |
| 58 | 58 | ||
| 59 | const std::string_view version = "0.12.0"sv; | 59 | const std::string_view version = "0.13.0"sv; |
| 60 | const std::string_view extension = "yue"sv; | 60 | const std::string_view extension = "yue"sv; |
| 61 | 61 | ||
| 62 | class YueCompilerImpl { | 62 | class YueCompilerImpl { |
| @@ -283,15 +283,15 @@ private: | |||
| 283 | }; | 283 | }; |
| 284 | 284 | ||
| 285 | struct DestructItem { | 285 | struct DestructItem { |
| 286 | bool isVariable = false; | 286 | ast_ptr<true, Exp_t> target; |
| 287 | std::string name; | 287 | std::string targetVar; |
| 288 | std::string structure; | 288 | std::string structure; |
| 289 | ast_ptr<true, Exp_t> defVal; | 289 | ast_ptr<true, Exp_t> defVal; |
| 290 | bool isMetatable = false; | ||
| 291 | }; | 290 | }; |
| 292 | 291 | ||
| 293 | struct Destructure { | 292 | struct Destructure { |
| 294 | std::string value; | 293 | ast_ptr<true, ast_node> value; |
| 294 | std::string valueVar; | ||
| 295 | std::list<DestructItem> items; | 295 | std::list<DestructItem> items; |
| 296 | }; | 296 | }; |
| 297 | 297 | ||
| @@ -562,6 +562,13 @@ private: | |||
| 562 | } | 562 | } |
| 563 | break; | 563 | break; |
| 564 | } | 564 | } |
| 565 | case id<SwitchList_t>(): { | ||
| 566 | auto expList = static_cast<SwitchList_t*>(item); | ||
| 567 | if (expList->exprs.size() == 1) { | ||
| 568 | exp = static_cast<Exp_t*>(expList->exprs.front()); | ||
| 569 | } | ||
| 570 | break; | ||
| 571 | } | ||
| 565 | case id<unary_exp_t>(): { | 572 | case id<unary_exp_t>(): { |
| 566 | auto unary = static_cast<unary_exp_t*>(item); | 573 | auto unary = static_cast<unary_exp_t*>(item); |
| 567 | if (unary->expos.size() == 1) { | 574 | if (unary->expos.size() == 1) { |
| @@ -800,7 +807,7 @@ private: | |||
| 800 | return Empty; | 807 | return Empty; |
| 801 | } | 808 | } |
| 802 | 809 | ||
| 803 | std::string singleVariableFrom(ast_node* expList) { | 810 | std::string singleVariableFrom(ast_node* expList, bool accessing) { |
| 804 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; | 811 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; |
| 805 | BLOCK_START | 812 | BLOCK_START |
| 806 | auto value = singleValueFrom(expList); | 813 | auto value = singleValueFrom(expList); |
| @@ -809,9 +816,16 @@ private: | |||
| 809 | BREAK_IF(!chainValue); | 816 | BREAK_IF(!chainValue); |
| 810 | BREAK_IF(chainValue->items.size() != 1); | 817 | BREAK_IF(chainValue->items.size() != 1); |
| 811 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | 818 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); |
| 812 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); | 819 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t, self_t>())); |
| 813 | str_list tmp; | 820 | str_list tmp; |
| 814 | transformCallable(callable, tmp); | 821 | if (accessing) { |
| 822 | transformCallable(callable, tmp); | ||
| 823 | } else { | ||
| 824 | bool lintGlobal = _config.lintGlobalVariable; | ||
| 825 | _config.lintGlobalVariable = false; | ||
| 826 | transformCallable(callable, tmp); | ||
| 827 | _config.lintGlobalVariable = lintGlobal; | ||
| 828 | } | ||
| 815 | return tmp.back(); | 829 | return tmp.back(); |
| 816 | BLOCK_END | 830 | BLOCK_END |
| 817 | return Empty; | 831 | return Empty; |
| @@ -1173,7 +1187,7 @@ private: | |||
| 1173 | _config.lintGlobalVariable = false; | 1187 | _config.lintGlobalVariable = false; |
| 1174 | if (!assignment->action.is<Assign_t>()) return vars; | 1188 | if (!assignment->action.is<Assign_t>()) return vars; |
| 1175 | for (auto exp : assignment->expList->exprs.objects()) { | 1189 | for (auto exp : assignment->expList->exprs.objects()) { |
| 1176 | auto var = singleVariableFrom(exp); | 1190 | auto var = singleVariableFrom(exp, true); |
| 1177 | vars.push_back(var.empty() ? Empty : var); | 1191 | vars.push_back(var.empty() ? Empty : var); |
| 1178 | } | 1192 | } |
| 1179 | _config.lintGlobalVariable = lintGlobal; | 1193 | _config.lintGlobalVariable = lintGlobal; |
| @@ -1185,7 +1199,7 @@ private: | |||
| 1185 | bool lintGlobal = _config.lintGlobalVariable; | 1199 | bool lintGlobal = _config.lintGlobalVariable; |
| 1186 | _config.lintGlobalVariable = false; | 1200 | _config.lintGlobalVariable = false; |
| 1187 | for (auto exp : with->valueList->exprs.objects()) { | 1201 | for (auto exp : with->valueList->exprs.objects()) { |
| 1188 | auto var = singleVariableFrom(exp); | 1202 | auto var = singleVariableFrom(exp, true); |
| 1189 | vars.push_back(var.empty() ? Empty : var); | 1203 | vars.push_back(var.empty() ? Empty : var); |
| 1190 | } | 1204 | } |
| 1191 | _config.lintGlobalVariable = lintGlobal; | 1205 | _config.lintGlobalVariable = lintGlobal; |
| @@ -1241,13 +1255,15 @@ private: | |||
| 1241 | } | 1255 | } |
| 1242 | 1256 | ||
| 1243 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 1257 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
| 1244 | auto info = extractDestructureInfo(assignment, true); | 1258 | auto info = extractDestructureInfo(assignment, true, false); |
| 1245 | if (!info.first.empty()) { | 1259 | if (!info.first.empty()) { |
| 1246 | for (const auto& destruct : info.first) { | 1260 | for (const auto& destruct : info.first) { |
| 1247 | str_list defs; | 1261 | str_list defs; |
| 1248 | for (const auto& item : destruct.items) { | 1262 | for (const auto& item : destruct.items) { |
| 1249 | if (item.isVariable && addToScope(item.name)) { | 1263 | if (!item.targetVar.empty()) { |
| 1250 | defs.push_back(item.name); | 1264 | if (addToScope(item.targetVar)) { |
| 1265 | defs.push_back(item.targetVar); | ||
| 1266 | } | ||
| 1251 | } | 1267 | } |
| 1252 | } | 1268 | } |
| 1253 | if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv); | 1269 | if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv); |
| @@ -1282,7 +1298,18 @@ private: | |||
| 1282 | return nullptr; | 1298 | return nullptr; |
| 1283 | } | 1299 | } |
| 1284 | 1300 | ||
| 1285 | void transformAssignment(ExpListAssign_t* assignment, str_list& out) { | 1301 | ast_ptr<false, ExpListAssign_t> assignmentFrom(Exp_t* target, ast_node* value, ast_node* x) { |
| 1302 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 1303 | auto assignList = x->new_ptr<ExpList_t>(); | ||
| 1304 | assignList->exprs.push_back(target); | ||
| 1305 | assignment->expList.set(assignList); | ||
| 1306 | auto assign = x->new_ptr<Assign_t>(); | ||
| 1307 | assign->values.push_back(value); | ||
| 1308 | assignment->action.set(assign); | ||
| 1309 | return assignment; | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | ||
| 1286 | checkAssignable(assignment->expList); | 1313 | checkAssignable(assignment->expList); |
| 1287 | BLOCK_START | 1314 | BLOCK_START |
| 1288 | auto assign = ast_cast<Assign_t>(assignment->action); | 1315 | auto assign = ast_cast<Assign_t>(assignment->action); |
| @@ -1516,7 +1543,7 @@ private: | |||
| 1516 | } | 1543 | } |
| 1517 | } | 1544 | } |
| 1518 | BLOCK_END | 1545 | BLOCK_END |
| 1519 | auto info = extractDestructureInfo(assignment, false); | 1546 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
| 1520 | if (info.first.empty()) { | 1547 | if (info.first.empty()) { |
| 1521 | transformAssignmentCommon(assignment, out); | 1548 | transformAssignmentCommon(assignment, out); |
| 1522 | } else { | 1549 | } else { |
| @@ -1524,126 +1551,165 @@ private: | |||
| 1524 | if (info.second) { | 1551 | if (info.second) { |
| 1525 | transformAssignmentCommon(info.second, temp); | 1552 | transformAssignmentCommon(info.second, temp); |
| 1526 | } | 1553 | } |
| 1554 | auto x = assignment; | ||
| 1527 | for (auto& destruct : info.first) { | 1555 | for (auto& destruct : info.first) { |
| 1528 | std::list<std::pair<std::string, std::string>> leftPairs; | 1556 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; |
| 1557 | bool extraScope = false; | ||
| 1529 | if (destruct.items.size() == 1) { | 1558 | if (destruct.items.size() == 1) { |
| 1530 | auto& pair = destruct.items.front(); | 1559 | auto& pair = destruct.items.front(); |
| 1531 | if (!pair.isVariable && pair.defVal) { | 1560 | if (pair.targetVar.empty() && pair.defVal) { |
| 1532 | auto objVar = getUnusedName("_obj_"sv); | 1561 | extraScope = true; |
| 1533 | leftPairs.push_back({pair.name, objVar}); | 1562 | auto objVar = getUnusedName("_tmp_"sv); |
| 1534 | pair.name = objVar; | 1563 | auto objExp = toAst<Exp_t>(objVar, pair.target); |
| 1535 | pair.isVariable = true; | 1564 | leftPairs.push_back({pair.target, objExp.get()}); |
| 1536 | } | 1565 | pair.target.set(objExp); |
| 1537 | if (pair.isMetatable) { | 1566 | pair.targetVar = objVar; |
| 1538 | if (pair.isVariable) { | 1567 | } else if (auto val = singleValueFrom(destruct.value); val->item.is<ChainValue_t>()) { |
| 1539 | checkConst(pair.name, assignment); | 1568 | auto chainValue = static_cast<ChainValue_t*>(val->item.get()); |
| 1540 | if (addToScope(pair.name)) { | 1569 | int added = 0; |
| 1541 | _buf << indent() << "local "sv << pair.name << nll(assignment); | 1570 | if (!pair.structure.empty()) { |
| 1571 | auto appendChain = toAst<ChainValue_t>("x"s + pair.structure, x); | ||
| 1572 | appendChain->items.pop_front(); | ||
| 1573 | for (auto item : appendChain->items.objects()) { | ||
| 1574 | chainValue->items.push_back(item); | ||
| 1575 | added++; | ||
| 1542 | } | 1576 | } |
| 1543 | } | 1577 | } |
| 1544 | bool isLocalValue = isLocal(destruct.value); | 1578 | auto newAssignment = assignmentFrom(pair.target, destruct.value, x); |
| 1545 | std::string objVar; | 1579 | transformAssignment(newAssignment, temp); |
| 1546 | if (isLocalValue) { | 1580 | while (added > 0) { |
| 1547 | objVar = destruct.value; | 1581 | chainValue->items.pop_back(); |
| 1548 | } else { | 1582 | added--; |
| 1549 | _buf << indent() << "do"sv << nll(assignment); | ||
| 1550 | pushScope(); | ||
| 1551 | objVar = getUnusedName("_obj_"sv); | ||
| 1552 | addToScope(objVar); | ||
| 1553 | _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment); | ||
| 1554 | temp.push_back(clearBuf()); | ||
| 1555 | } | 1583 | } |
| 1556 | auto valueExp = toAst<Exp_t>(objVar + pair.structure, assignment); | 1584 | if (pair.defVal) { |
| 1557 | transformExp(valueExp, temp, ExpUsage::Closure); | 1585 | auto stmt = toAst<Statement_t>(pair.targetVar + "=nil if "s + pair.targetVar + "==nil", pair.defVal); |
| 1558 | _buf << indent() << pair.name << " = "sv << temp.back() << nll(assignment); | 1586 | auto defAssign = stmt->content.as<ExpListAssign_t>(); |
| 1559 | if (!isLocalValue) { | 1587 | auto assign = defAssign->action.as<Assign_t>(); |
| 1560 | popScope(); | 1588 | assign->values.clear(); |
| 1561 | _buf << indent() << "end"sv << nlr(assignment); | 1589 | assign->values.push_back(pair.defVal); |
| 1590 | transformStatement(stmt, temp); | ||
| 1562 | } | 1591 | } |
| 1563 | temp.back() = clearBuf(); | 1592 | continue; |
| 1564 | } else { | ||
| 1565 | _buf << indent(); | ||
| 1566 | if (pair.isVariable) { | ||
| 1567 | checkConst(pair.name, assignment); | ||
| 1568 | if (addToScope(pair.name)) _buf << "local "sv; | ||
| 1569 | } | ||
| 1570 | _buf << pair.name << " = "sv << destruct.value << pair.structure << nll(assignment); | ||
| 1571 | temp.push_back(clearBuf()); | ||
| 1572 | } | 1593 | } |
| 1573 | } else if (_parser.match<Name_t>(destruct.value) && isLocal(destruct.value)) { | 1594 | if (extraScope) { |
| 1574 | str_list defs, names, values; | 1595 | temp.push_back(indent() + "do"s + nll(x)); |
| 1575 | bool isMetatable = false; | 1596 | pushScope(); |
| 1576 | for (auto& item : destruct.items) { | 1597 | } |
| 1577 | if (item.isVariable) { | 1598 | if (!pair.targetVar.empty()) { |
| 1578 | checkConst(item.name, assignment); | 1599 | checkConst(pair.targetVar, x); |
| 1579 | if (addToScope(item.name)) defs.push_back(item.name); | 1600 | if (addToScope(pair.targetVar)) { |
| 1580 | } else if (item.defVal) { | 1601 | _buf << indent() << "local "sv << pair.targetVar << nll(x); |
| 1581 | auto objVar = getUnusedName("_obj_"sv); | 1602 | temp.push_back(clearBuf()); |
| 1582 | addToScope(objVar); | ||
| 1583 | defs.push_back(objVar); | ||
| 1584 | leftPairs.push_back({item.name, objVar}); | ||
| 1585 | item.name = objVar; | ||
| 1586 | } | 1603 | } |
| 1587 | if (item.isMetatable) isMetatable = true; | ||
| 1588 | names.push_back(item.name); | ||
| 1589 | values.push_back(item.structure); | ||
| 1590 | } | 1604 | } |
| 1591 | for (auto& v : values) v.insert(0, destruct.value); | 1605 | bool isLocalValue = isLocal(destruct.valueVar); |
| 1592 | if (isMetatable) { | 1606 | std::string objVar; |
| 1593 | auto newExpList = toAst<ExpList_t>(join(values, ","sv), assignment); | 1607 | if (isLocalValue) { |
| 1594 | transformExpList(newExpList, temp); | 1608 | objVar = destruct.valueVar; |
| 1595 | } else { | 1609 | } else { |
| 1596 | temp.push_back(join(values, ", "sv)); | 1610 | temp.push_back(indent() + "do"s + nll(x)); |
| 1611 | pushScope(); | ||
| 1612 | objVar = getUnusedName("_obj_"sv); | ||
| 1613 | auto newAssignment = assignmentFrom(toAst<Exp_t>(objVar, x), destruct.value, x); | ||
| 1614 | transformAssignment(newAssignment, temp); | ||
| 1597 | } | 1615 | } |
| 1598 | if (defs.empty()) { | 1616 | auto valueExp = toAst<Exp_t>(objVar + pair.structure, x); |
| 1599 | _buf << indent() << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment); | 1617 | auto newAssignment = assignmentFrom(pair.target, valueExp, x); |
| 1600 | } else { | 1618 | transformAssignment(newAssignment, temp); |
| 1601 | _buf << indent() << "local "sv; | 1619 | if (!isLocalValue) { |
| 1602 | if (defs.size() != names.size()) { | 1620 | popScope(); |
| 1603 | _buf << join(defs, ", "sv) << nll(assignment) << indent(); | 1621 | _buf << indent() << "end"sv << nlr(x); |
| 1604 | } | 1622 | temp.push_back(clearBuf()); |
| 1605 | _buf << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment); | ||
| 1606 | } | 1623 | } |
| 1607 | temp.back() = clearBuf(); | ||
| 1608 | } else { | 1624 | } else { |
| 1609 | str_list defs, names, values; | 1625 | str_list values, defs; |
| 1610 | bool isMetatable = false; | 1626 | std::list<Exp_t*> names; |
| 1627 | pushScope(); | ||
| 1611 | for (auto& item : destruct.items) { | 1628 | for (auto& item : destruct.items) { |
| 1612 | if (item.isVariable) { | 1629 | if (!item.targetVar.empty()) { |
| 1613 | checkConst(item.name, assignment); | 1630 | if (!isDefined(item.targetVar)) { |
| 1614 | if (addToScope(item.name)) defs.push_back(item.name); | 1631 | defs.push_back(item.targetVar); |
| 1632 | } | ||
| 1615 | } else if (item.defVal) { | 1633 | } else if (item.defVal) { |
| 1616 | auto objVar = getUnusedName("_obj_"sv); | 1634 | extraScope = true; |
| 1635 | auto objVar = getUnusedName("_tmp_"sv); | ||
| 1617 | addToScope(objVar); | 1636 | addToScope(objVar); |
| 1618 | defs.push_back(objVar); | 1637 | auto objExp = toAst<Exp_t>(objVar, item.target); |
| 1619 | leftPairs.push_back({item.name, objVar}); | 1638 | leftPairs.push_back({item.target, objExp.get()}); |
| 1620 | item.name = objVar; | 1639 | item.target.set(objExp); |
| 1640 | item.targetVar = objVar; | ||
| 1621 | } | 1641 | } |
| 1622 | if (item.isMetatable) isMetatable = true; | 1642 | names.push_back(item.target); |
| 1623 | names.push_back(item.name); | ||
| 1624 | values.push_back(item.structure); | 1643 | values.push_back(item.structure); |
| 1625 | } | 1644 | } |
| 1626 | if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv) << nll(assignment); | 1645 | popScope(); |
| 1627 | _buf << indent() << "do"sv << nll(assignment); | 1646 | if (_parser.match<Name_t>(destruct.valueVar) && isLocal(destruct.valueVar)) { |
| 1628 | pushScope(); | 1647 | for (auto& v : values) { |
| 1629 | auto objVar = getUnusedName("_obj_"sv); | 1648 | v.insert(0, destruct.valueVar); |
| 1630 | addToScope(objVar); | 1649 | } |
| 1631 | for (auto& v : values) v.insert(0, objVar); | 1650 | if (extraScope) { |
| 1632 | if (isMetatable) { | 1651 | if (!defs.empty()) { |
| 1633 | auto newExpList = toAst<ExpList_t>(join(values, ","sv), assignment); | 1652 | for (const auto& def : defs) { |
| 1634 | transformExpList(newExpList, temp); | 1653 | checkConst(def, x); |
| 1654 | addToScope(def); | ||
| 1655 | } | ||
| 1656 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | ||
| 1657 | } | ||
| 1658 | temp.push_back(indent() + "do"s + nll(x)); | ||
| 1659 | pushScope(); | ||
| 1660 | } | ||
| 1635 | } else { | 1661 | } else { |
| 1636 | temp.push_back(join(values, ", "sv)); | 1662 | if (!defs.empty()) { |
| 1663 | for (const auto& def : defs) { | ||
| 1664 | checkConst(def, x); | ||
| 1665 | addToScope(def); | ||
| 1666 | } | ||
| 1667 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | ||
| 1668 | } | ||
| 1669 | extraScope = true; | ||
| 1670 | temp.push_back(indent() + "do"s + nll(x)); | ||
| 1671 | pushScope(); | ||
| 1672 | auto valVar = getUnusedName("_obj_"sv); | ||
| 1673 | auto targetVar = toAst<Exp_t>(valVar, destruct.value); | ||
| 1674 | auto newAssignment = assignmentFrom(targetVar, destruct.value, destruct.value); | ||
| 1675 | transformAssignment(newAssignment, temp); | ||
| 1676 | for (auto& v : values) { | ||
| 1677 | v.insert(0, valVar); | ||
| 1678 | } | ||
| 1679 | } | ||
| 1680 | if (optionalDestruct) { | ||
| 1681 | while (!names.empty()) { | ||
| 1682 | auto name = names.front(); | ||
| 1683 | names.pop_front(); | ||
| 1684 | auto value = values.front(); | ||
| 1685 | values.pop_front(); | ||
| 1686 | auto valueList = toAst<ExpList_t>(value, x); | ||
| 1687 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
| 1688 | auto assignList = x->new_ptr<ExpList_t>(); | ||
| 1689 | assignList->exprs.push_back(name); | ||
| 1690 | newAssignment->expList.set(assignList); | ||
| 1691 | auto assign = x->new_ptr<Assign_t>(); | ||
| 1692 | assign->values.dup(valueList->exprs); | ||
| 1693 | newAssignment->action.set(assign); | ||
| 1694 | transformAssignment(newAssignment, temp); | ||
| 1695 | } | ||
| 1696 | } else { | ||
| 1697 | auto valueList = toAst<ExpList_t>(join(values, ","sv), x); | ||
| 1698 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
| 1699 | auto assignList = x->new_ptr<ExpList_t>(); | ||
| 1700 | for (auto name : names) { | ||
| 1701 | assignList->exprs.push_back(name); | ||
| 1702 | } | ||
| 1703 | newAssignment->expList.set(assignList); | ||
| 1704 | auto assign = x->new_ptr<Assign_t>(); | ||
| 1705 | assign->values.dup(valueList->exprs); | ||
| 1706 | newAssignment->action.set(assign); | ||
| 1707 | transformAssignment(newAssignment, temp); | ||
| 1637 | } | 1708 | } |
| 1638 | _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment); | ||
| 1639 | _buf << indent() << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment); | ||
| 1640 | popScope(); | ||
| 1641 | _buf << indent() << "end"sv << nll(assignment); | ||
| 1642 | temp.back() = clearBuf(); | ||
| 1643 | } | 1709 | } |
| 1644 | for (const auto& item : destruct.items) { | 1710 | for (const auto& item : destruct.items) { |
| 1645 | if (item.defVal) { | 1711 | if (item.defVal) { |
| 1646 | auto stmt = toAst<Statement_t>(item.name + "=nil if "s + item.name + "==nil", item.defVal); | 1712 | auto stmt = toAst<Statement_t>(item.targetVar + "=nil if "s + item.targetVar + "==nil", item.defVal); |
| 1647 | auto defAssign = stmt->content.as<ExpListAssign_t>(); | 1713 | auto defAssign = stmt->content.as<ExpListAssign_t>(); |
| 1648 | auto assign = defAssign->action.as<Assign_t>(); | 1714 | auto assign = defAssign->action.as<Assign_t>(); |
| 1649 | assign->values.clear(); | 1715 | assign->values.clear(); |
| @@ -1652,9 +1718,14 @@ private: | |||
| 1652 | } | 1718 | } |
| 1653 | } | 1719 | } |
| 1654 | for (const auto& item : leftPairs) { | 1720 | for (const auto& item : leftPairs) { |
| 1655 | _buf << indent() << item.first << " = "sv << item.second << nll(assignment); | 1721 | auto newAssignment = assignmentFrom(item.first, item.second, x); |
| 1722 | transformAssignment(newAssignment, temp); | ||
| 1723 | } | ||
| 1724 | if (extraScope) { | ||
| 1725 | popScope(); | ||
| 1726 | _buf << indent() << "end"sv << nlr(x); | ||
| 1727 | temp.push_back(clearBuf()); | ||
| 1656 | } | 1728 | } |
| 1657 | temp.push_back(clearBuf()); | ||
| 1658 | } | 1729 | } |
| 1659 | out.push_back(join(temp)); | 1730 | out.push_back(join(temp)); |
| 1660 | } | 1731 | } |
| @@ -1671,8 +1742,9 @@ private: | |||
| 1671 | } | 1742 | } |
| 1672 | } | 1743 | } |
| 1673 | 1744 | ||
| 1674 | std::list<DestructItem> destructFromExp(ast_node* node) { | 1745 | std::list<DestructItem> destructFromExp(ast_node* node, bool optional) { |
| 1675 | const node_container* tableItems = nullptr; | 1746 | const node_container* tableItems = nullptr; |
| 1747 | auto sep = optional ? "?"s : Empty; | ||
| 1676 | switch (node->getId()) { | 1748 | switch (node->getId()) { |
| 1677 | case id<Exp_t>(): { | 1749 | case id<Exp_t>(): { |
| 1678 | auto item = singleValueFrom(node)->item.get(); | 1750 | auto item = singleValueFrom(node)->item.get(); |
| @@ -1713,27 +1785,18 @@ private: | |||
| 1713 | auto item = value->item.get(); | 1785 | auto item = value->item.get(); |
| 1714 | if (ast_is<simple_table_t>(item) || | 1786 | if (ast_is<simple_table_t>(item) || |
| 1715 | item->getByPath<TableLit_t>()) { | 1787 | item->getByPath<TableLit_t>()) { |
| 1716 | auto subPairs = destructFromExp(pair); | 1788 | auto subPairs = destructFromExp(pair, optional); |
| 1717 | for (auto& p : subPairs) { | 1789 | for (auto& p : subPairs) { |
| 1718 | pairs.push_back({p.isVariable, p.name, | 1790 | pairs.push_back({p.target, p.targetVar, |
| 1719 | '[' + std::to_string(index) + ']' + p.structure, | 1791 | '[' + std::to_string(index) + ']' + sep + p.structure, |
| 1720 | p.defVal, p.isMetatable}); | 1792 | p.defVal}); |
| 1721 | } | 1793 | } |
| 1722 | } else { | 1794 | } else { |
| 1723 | bool lintGlobal = _config.lintGlobalVariable; | ||
| 1724 | _config.lintGlobalVariable = false; | ||
| 1725 | auto exp = static_cast<Exp_t*>(pair); | 1795 | auto exp = static_cast<Exp_t*>(pair); |
| 1726 | auto varName = singleVariableFrom(exp); | 1796 | auto varName = singleVariableFrom(exp, false); |
| 1727 | if (varName == "_"sv) break; | 1797 | if (varName == "_"sv) break; |
| 1728 | bool isVariable = !varName.empty(); | ||
| 1729 | if (!isVariable) { | ||
| 1730 | str_list temp; | ||
| 1731 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1732 | varName = std::move(temp.back()); | ||
| 1733 | } | ||
| 1734 | _config.lintGlobalVariable = lintGlobal; | ||
| 1735 | pairs.push_back({ | 1798 | pairs.push_back({ |
| 1736 | isVariable, | 1799 | exp, |
| 1737 | varName, | 1800 | varName, |
| 1738 | '[' + std::to_string(index) + ']', | 1801 | '[' + std::to_string(index) + ']', |
| 1739 | nullptr | 1802 | nullptr |
| @@ -1744,11 +1807,7 @@ private: | |||
| 1744 | case id<variable_pair_t>(): { | 1807 | case id<variable_pair_t>(): { |
| 1745 | auto vp = static_cast<variable_pair_t*>(pair); | 1808 | auto vp = static_cast<variable_pair_t*>(pair); |
| 1746 | auto name = _parser.toString(vp->name); | 1809 | auto name = _parser.toString(vp->name); |
| 1747 | if (LuaKeywords.find(name) != LuaKeywords.end()) { | 1810 | pairs.push_back({toAst<Exp_t>(name, vp).get(), name, '.' + name, nullptr}); |
| 1748 | pairs.push_back({true, name, "[\""s + name + "\"]"s, nullptr}); | ||
| 1749 | } else { | ||
| 1750 | pairs.push_back({true, name, '.' + name, nullptr}); | ||
| 1751 | } | ||
| 1752 | break; | 1811 | break; |
| 1753 | } | 1812 | } |
| 1754 | case id<normal_pair_t>(): { | 1813 | case id<normal_pair_t>(): { |
| @@ -1769,29 +1828,19 @@ private: | |||
| 1769 | auto item = singleValueFrom(exp)->item.get(); | 1828 | auto item = singleValueFrom(exp)->item.get(); |
| 1770 | if (ast_is<simple_table_t>(item) || | 1829 | if (ast_is<simple_table_t>(item) || |
| 1771 | item->getByPath<TableLit_t>()) { | 1830 | item->getByPath<TableLit_t>()) { |
| 1772 | auto subPairs = destructFromExp(exp); | 1831 | auto subPairs = destructFromExp(exp, optional); |
| 1773 | for (auto& p : subPairs) { | 1832 | for (auto& p : subPairs) { |
| 1774 | pairs.push_back({ | 1833 | pairs.push_back({ |
| 1775 | p.isVariable, | 1834 | p.target, |
| 1776 | p.name, | 1835 | p.targetVar, |
| 1777 | keyName + p.structure, | 1836 | keyName + sep + p.structure, |
| 1778 | p.defVal, | 1837 | p.defVal |
| 1779 | p.isMetatable | ||
| 1780 | }); | 1838 | }); |
| 1781 | } | 1839 | } |
| 1782 | } else { | 1840 | } else { |
| 1783 | bool lintGlobal = _config.lintGlobalVariable; | 1841 | auto varName = singleVariableFrom(exp, false); |
| 1784 | _config.lintGlobalVariable = false; | ||
| 1785 | auto varName = singleVariableFrom(exp); | ||
| 1786 | bool isVariable = !varName.empty(); | ||
| 1787 | if (!isVariable) { | ||
| 1788 | str_list temp; | ||
| 1789 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1790 | varName = std::move(temp.back()); | ||
| 1791 | } | ||
| 1792 | _config.lintGlobalVariable = lintGlobal; | ||
| 1793 | pairs.push_back({ | 1842 | pairs.push_back({ |
| 1794 | isVariable, | 1843 | exp, |
| 1795 | varName, | 1844 | varName, |
| 1796 | keyName, | 1845 | keyName, |
| 1797 | nullptr | 1846 | nullptr |
| @@ -1800,14 +1849,13 @@ private: | |||
| 1800 | break; | 1849 | break; |
| 1801 | } | 1850 | } |
| 1802 | if (np->value.is<TableBlock_t>()) { | 1851 | if (np->value.is<TableBlock_t>()) { |
| 1803 | auto subPairs = destructFromExp(np->value); | 1852 | auto subPairs = destructFromExp(np->value, optional); |
| 1804 | for (auto& p : subPairs) { | 1853 | for (auto& p : subPairs) { |
| 1805 | pairs.push_back({ | 1854 | pairs.push_back({ |
| 1806 | p.isVariable, | 1855 | p.target, |
| 1807 | p.name, | 1856 | p.targetVar, |
| 1808 | keyName + p.structure, | 1857 | keyName + sep + p.structure, |
| 1809 | p.defVal, | 1858 | p.defVal |
| 1810 | p.isMetatable | ||
| 1811 | }); | 1859 | }); |
| 1812 | } | 1860 | } |
| 1813 | } | 1861 | } |
| @@ -1816,14 +1864,13 @@ private: | |||
| 1816 | case id<TableBlockIndent_t>(): { | 1864 | case id<TableBlockIndent_t>(): { |
| 1817 | auto tb = static_cast<TableBlockIndent_t*>(pair); | 1865 | auto tb = static_cast<TableBlockIndent_t*>(pair); |
| 1818 | ++index; | 1866 | ++index; |
| 1819 | auto subPairs = destructFromExp(tb); | 1867 | auto subPairs = destructFromExp(tb, optional); |
| 1820 | for (auto& p : subPairs) { | 1868 | for (auto& p : subPairs) { |
| 1821 | pairs.push_back({ | 1869 | pairs.push_back({ |
| 1822 | p.isVariable, | 1870 | p.target, |
| 1823 | p.name, | 1871 | p.targetVar, |
| 1824 | '[' + std::to_string(index) + ']' + p.structure, | 1872 | '[' + std::to_string(index) + ']' + sep + p.structure, |
| 1825 | p.defVal, | 1873 | p.defVal |
| 1826 | p.isMetatable | ||
| 1827 | }); | 1874 | }); |
| 1828 | } | 1875 | } |
| 1829 | break; | 1876 | break; |
| @@ -1841,18 +1888,9 @@ private: | |||
| 1841 | item->getByPath<TableLit_t>()) { | 1888 | item->getByPath<TableLit_t>()) { |
| 1842 | throw std::logic_error(_info.errorMessage("invalid use of default value"sv, dp->defVal)); | 1889 | throw std::logic_error(_info.errorMessage("invalid use of default value"sv, dp->defVal)); |
| 1843 | } else { | 1890 | } else { |
| 1844 | bool lintGlobal = _config.lintGlobalVariable; | 1891 | auto varName = singleVariableFrom(exp, false); |
| 1845 | _config.lintGlobalVariable = false; | ||
| 1846 | auto varName = singleVariableFrom(exp); | ||
| 1847 | bool isVariable = !varName.empty(); | ||
| 1848 | if (!isVariable) { | ||
| 1849 | str_list temp; | ||
| 1850 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1851 | varName = std::move(temp.back()); | ||
| 1852 | } | ||
| 1853 | _config.lintGlobalVariable = lintGlobal; | ||
| 1854 | pairs.push_back({ | 1892 | pairs.push_back({ |
| 1855 | isVariable, | 1893 | exp, |
| 1856 | varName, | 1894 | varName, |
| 1857 | '[' + std::to_string(index) + ']', | 1895 | '[' + std::to_string(index) + ']', |
| 1858 | dp->defVal | 1896 | dp->defVal |
| @@ -1872,27 +1910,18 @@ private: | |||
| 1872 | keyName = "."s + keyName; | 1910 | keyName = "."s + keyName; |
| 1873 | } | 1911 | } |
| 1874 | } | 1912 | } |
| 1875 | if (auto exp = dp->value.as<Exp_t>()) { | 1913 | if (auto exp = dp->value.get()) { |
| 1876 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); | 1914 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); |
| 1877 | bool lintGlobal = _config.lintGlobalVariable; | 1915 | auto varName = singleVariableFrom(exp, false); |
| 1878 | _config.lintGlobalVariable = false; | ||
| 1879 | auto varName = singleVariableFrom(exp); | ||
| 1880 | bool isVariable = !varName.empty(); | ||
| 1881 | if (!isVariable) { | ||
| 1882 | str_list temp; | ||
| 1883 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1884 | varName = std::move(temp.back()); | ||
| 1885 | } | ||
| 1886 | _config.lintGlobalVariable = lintGlobal; | ||
| 1887 | pairs.push_back({ | 1916 | pairs.push_back({ |
| 1888 | isVariable, | 1917 | exp, |
| 1889 | varName, | 1918 | varName, |
| 1890 | keyName, | 1919 | keyName, |
| 1891 | dp->defVal | 1920 | dp->defVal |
| 1892 | }); | 1921 | }); |
| 1893 | } else { | 1922 | } else { |
| 1894 | pairs.push_back({ | 1923 | pairs.push_back({ |
| 1895 | true, | 1924 | toAst<Exp_t>(valueStr, dp).get(), |
| 1896 | valueStr, | 1925 | valueStr, |
| 1897 | keyName, | 1926 | keyName, |
| 1898 | dp->defVal | 1927 | dp->defVal |
| @@ -1910,8 +1939,7 @@ private: | |||
| 1910 | newPair->key.set(newKey); | 1939 | newPair->key.set(newKey); |
| 1911 | if (newPair->value) { | 1940 | if (newPair->value) { |
| 1912 | newPair->value.set(mp->value); | 1941 | newPair->value.set(mp->value); |
| 1913 | } | 1942 | } else { |
| 1914 | else { | ||
| 1915 | newPair->value.set(toAst<Exp_t>(key, mp->key)); | 1943 | newPair->value.set(toAst<Exp_t>(key, mp->key)); |
| 1916 | } | 1944 | } |
| 1917 | } else { | 1945 | } else { |
| @@ -1959,14 +1987,13 @@ private: | |||
| 1959 | simpleValue->value.set(subMetaDestruct); | 1987 | simpleValue->value.set(subMetaDestruct); |
| 1960 | auto value = subMetaDestruct->new_ptr<Value_t>(); | 1988 | auto value = subMetaDestruct->new_ptr<Value_t>(); |
| 1961 | value->item.set(simpleValue); | 1989 | value->item.set(simpleValue); |
| 1962 | auto subPairs = destructFromExp(newExp(value, subMetaDestruct)); | 1990 | auto subPairs = destructFromExp(newExp(value, subMetaDestruct), optional); |
| 1963 | for (const auto& p : subPairs) { | 1991 | for (const auto& p : subPairs) { |
| 1964 | pairs.push_back({ | 1992 | pairs.push_back({ |
| 1965 | p.isVariable, | 1993 | p.target, |
| 1966 | p.name, | 1994 | p.targetVar, |
| 1967 | ".#"s + p.structure, | 1995 | ".#"s + sep + p.structure, |
| 1968 | p.defVal, | 1996 | p.defVal |
| 1969 | true | ||
| 1970 | }); | 1997 | }); |
| 1971 | } | 1998 | } |
| 1972 | } | 1999 | } |
| @@ -1974,7 +2001,7 @@ private: | |||
| 1974 | } | 2001 | } |
| 1975 | 2002 | ||
| 1976 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> | 2003 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> |
| 1977 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly) { | 2004 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { |
| 1978 | auto x = assignment; | 2005 | auto x = assignment; |
| 1979 | std::list<Destructure> destructs; | 2006 | std::list<Destructure> destructs; |
| 1980 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; | 2007 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; |
| @@ -1993,10 +2020,10 @@ private: | |||
| 1993 | while (values.size() < size) values.emplace_back(nullNode); | 2020 | while (values.size() < size) values.emplace_back(nullNode); |
| 1994 | } | 2021 | } |
| 1995 | using iter = node_container::iterator; | 2022 | using iter = node_container::iterator; |
| 1996 | std::vector<std::pair<iter,iter>> destructPairs; | 2023 | std::vector<std::pair<iter, iter>> destructPairs; |
| 1997 | ast_list<false, ast_node> valueItems; | 2024 | ast_list<false, ast_node> valueItems; |
| 1998 | if (!varDefOnly) pushScope(); | ||
| 1999 | str_list temp; | 2025 | str_list temp; |
| 2026 | pushScope(); | ||
| 2000 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { | 2027 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { |
| 2001 | auto expr = *i; | 2028 | auto expr = *i; |
| 2002 | auto value = singleValueFrom(expr); | 2029 | auto value = singleValueFrom(expr); |
| @@ -2019,7 +2046,7 @@ private: | |||
| 2019 | } else { | 2046 | } else { |
| 2020 | throw std::logic_error(_info.errorMessage("can not destructure a nil value"sv, destructNode)); | 2047 | throw std::logic_error(_info.errorMessage("can not destructure a nil value"sv, destructNode)); |
| 2021 | } | 2048 | } |
| 2022 | destructPairs.push_back({i,j}); | 2049 | destructPairs.push_back({i, j}); |
| 2023 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); | 2050 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); |
| 2024 | auto subMetaDestruct = destructNode->new_ptr<TableLit_t>(); | 2051 | auto subMetaDestruct = destructNode->new_ptr<TableLit_t>(); |
| 2025 | const node_container* dlist = nullptr; | 2052 | const node_container* dlist = nullptr; |
| @@ -2103,15 +2130,14 @@ private: | |||
| 2103 | if (!tab->values.empty()) { | 2130 | if (!tab->values.empty()) { |
| 2104 | auto& destruct = destructs.emplace_back(); | 2131 | auto& destruct = destructs.emplace_back(); |
| 2105 | if (!varDefOnly) { | 2132 | if (!varDefOnly) { |
| 2106 | transformAssignItem(valueItems.back(), temp); | 2133 | destruct.value = valueItems.back(); |
| 2107 | destruct.value = std::move(temp.back()); | 2134 | destruct.valueVar = singleVariableFrom(destruct.value, false); |
| 2108 | temp.pop_back(); | ||
| 2109 | } | 2135 | } |
| 2110 | auto simpleValue = tab->new_ptr<SimpleValue_t>(); | 2136 | auto simpleValue = tab->new_ptr<SimpleValue_t>(); |
| 2111 | simpleValue->value.set(tab); | 2137 | simpleValue->value.set(tab); |
| 2112 | auto value = tab->new_ptr<Value_t>(); | 2138 | auto value = tab->new_ptr<Value_t>(); |
| 2113 | value->item.set(simpleValue); | 2139 | value->item.set(simpleValue); |
| 2114 | auto pairs = destructFromExp(newExp(value, expr)); | 2140 | auto pairs = destructFromExp(newExp(value, expr), optional); |
| 2115 | if (pairs.empty()) { | 2141 | if (pairs.empty()) { |
| 2116 | throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab)); | 2142 | throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab)); |
| 2117 | } | 2143 | } |
| @@ -2122,18 +2148,34 @@ private: | |||
| 2122 | item.structure.clear(); | 2148 | item.structure.clear(); |
| 2123 | } | 2149 | } |
| 2124 | } else if (tab == subMetaDestruct.get()) { | 2150 | } else if (tab == subMetaDestruct.get()) { |
| 2125 | destruct.value.insert(0, globalVar("getmetatable"sv, tab) + '('); | 2151 | auto p = destruct.value.get(); |
| 2126 | destruct.value.append(")"sv); | 2152 | auto chainValue = toAst<ChainValue_t>("getmetatable()", p); |
| 2153 | static_cast<Invoke_t*>(chainValue->items.back())->args.push_back(destruct.value); | ||
| 2154 | auto value = p->new_ptr<Value_t>(); | ||
| 2155 | value->item.set(chainValue); | ||
| 2156 | auto exp = newExp(value, p); | ||
| 2157 | destruct.value.set(exp); | ||
| 2158 | destruct.valueVar.clear(); | ||
| 2127 | } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) { | 2159 | } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) { |
| 2128 | destruct.value.insert(0, "("sv); | 2160 | auto p = destruct.value.get(); |
| 2129 | destruct.value.append(")"sv); | 2161 | auto parens = p->new_ptr<Parens_t>(); |
| 2162 | parens->expr.set(p); | ||
| 2163 | auto callable = p->new_ptr<Callable_t>(); | ||
| 2164 | callable->item.set(parens); | ||
| 2165 | auto chainValue = p->new_ptr<ChainValue_t>(); | ||
| 2166 | chainValue->items.push_back(callable); | ||
| 2167 | auto value = p->new_ptr<Value_t>(); | ||
| 2168 | value->item.set(chainValue); | ||
| 2169 | auto exp = newExp(value, p); | ||
| 2170 | destruct.value.set(exp); | ||
| 2171 | destruct.valueVar.clear(); | ||
| 2130 | } | 2172 | } |
| 2131 | } | 2173 | } |
| 2132 | } | 2174 | } |
| 2133 | } | 2175 | } |
| 2134 | } | 2176 | } |
| 2135 | } | 2177 | } |
| 2136 | if (!varDefOnly) popScope(); | 2178 | popScope(); |
| 2137 | for (const auto& p : destructPairs) { | 2179 | for (const auto& p : destructPairs) { |
| 2138 | exprs.erase(p.first); | 2180 | exprs.erase(p.first); |
| 2139 | values.erase(p.second); | 2181 | values.erase(p.second); |
| @@ -2211,7 +2253,7 @@ private: | |||
| 2211 | BLOCK_START | 2253 | BLOCK_START |
| 2212 | auto exp = ast_cast<Exp_t>(item); | 2254 | auto exp = ast_cast<Exp_t>(item); |
| 2213 | BREAK_IF(!exp); | 2255 | BREAK_IF(!exp); |
| 2214 | auto var = singleVariableFrom(exp); | 2256 | auto var = singleVariableFrom(exp, true); |
| 2215 | BREAK_IF(!var.empty()); | 2257 | BREAK_IF(!var.empty()); |
| 2216 | auto upVar = getUnusedName("_update_"sv); | 2258 | auto upVar = getUnusedName("_update_"sv); |
| 2217 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 2259 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -2373,15 +2415,12 @@ private: | |||
| 2373 | if (asmt) { | 2415 | if (asmt) { |
| 2374 | ast_ptr<false, ast_node> exp = asmt->expList->exprs.front(); | 2416 | ast_ptr<false, ast_node> exp = asmt->expList->exprs.front(); |
| 2375 | auto x = exp; | 2417 | auto x = exp; |
| 2376 | bool lintGlobal = _config.lintGlobalVariable; | 2418 | auto var = singleVariableFrom(exp, false); |
| 2377 | _config.lintGlobalVariable = false; | ||
| 2378 | auto var = singleVariableFrom(exp); | ||
| 2379 | _config.lintGlobalVariable = lintGlobal; | ||
| 2380 | if (var.empty() || isGlobal(var)) { | 2419 | if (var.empty() || isGlobal(var)) { |
| 2381 | storingValue = true; | 2420 | storingValue = true; |
| 2382 | auto desVar = getUnusedName("_des_"sv); | 2421 | auto desVar = getUnusedName("_des_"sv); |
| 2383 | if (asmt->assign->values.objects().size() == 1) { | 2422 | if (asmt->assign->values.objects().size() == 1) { |
| 2384 | auto var = singleVariableFrom(asmt->assign->values.objects().front()); | 2423 | auto var = singleVariableFrom(asmt->assign->values.objects().front(), true); |
| 2385 | if (!var.empty() && isLocal(var)) { | 2424 | if (!var.empty() && isLocal(var)) { |
| 2386 | desVar = var; | 2425 | desVar = var; |
| 2387 | storingValue = false; | 2426 | storingValue = false; |
| @@ -2524,10 +2563,7 @@ private: | |||
| 2524 | } | 2563 | } |
| 2525 | bool findPlaceHolder = false; | 2564 | bool findPlaceHolder = false; |
| 2526 | for (auto a : args->objects()) { | 2565 | for (auto a : args->objects()) { |
| 2527 | bool lintGlobal = _config.lintGlobalVariable; | 2566 | auto name = singleVariableFrom(a, false); |
| 2528 | _config.lintGlobalVariable = false; | ||
| 2529 | auto name = singleVariableFrom(a); | ||
| 2530 | _config.lintGlobalVariable = lintGlobal; | ||
| 2531 | if (name == "_"sv) { | 2567 | if (name == "_"sv) { |
| 2532 | if (!findPlaceHolder) { | 2568 | if (!findPlaceHolder) { |
| 2533 | args->swap(a, arg); | 2569 | args->swap(a, arg); |
| @@ -2643,7 +2679,7 @@ private: | |||
| 2643 | funcStart = &temp.emplace_back(); | 2679 | funcStart = &temp.emplace_back(); |
| 2644 | pushScope(); | 2680 | pushScope(); |
| 2645 | } | 2681 | } |
| 2646 | auto objVar = singleVariableFrom(left); | 2682 | auto objVar = singleVariableFrom(left, true); |
| 2647 | auto prepareValue = [&](bool forAssignment = false) { | 2683 | auto prepareValue = [&](bool forAssignment = false) { |
| 2648 | if (objVar.empty() || !isLocal(objVar)) { | 2684 | if (objVar.empty() || !isLocal(objVar)) { |
| 2649 | if (forAssignment) { | 2685 | if (forAssignment) { |
| @@ -2953,10 +2989,7 @@ private: | |||
| 2953 | } | 2989 | } |
| 2954 | bool findPlaceHolder = false; | 2990 | bool findPlaceHolder = false; |
| 2955 | for (auto a : args->objects()) { | 2991 | for (auto a : args->objects()) { |
| 2956 | bool lintGlobal = _config.lintGlobalVariable; | 2992 | auto name = singleVariableFrom(a, false); |
| 2957 | _config.lintGlobalVariable = false; | ||
| 2958 | auto name = singleVariableFrom(a); | ||
| 2959 | _config.lintGlobalVariable = lintGlobal; | ||
| 2960 | if (name == "_"sv) { | 2993 | if (name == "_"sv) { |
| 2961 | if (!findPlaceHolder) { | 2994 | if (!findPlaceHolder) { |
| 2962 | args->swap(a, arg); | 2995 | args->swap(a, arg); |
| @@ -3040,14 +3073,14 @@ private: | |||
| 3040 | any->decls.push_back(var); | 3073 | any->decls.push_back(var); |
| 3041 | } | 3074 | } |
| 3042 | } | 3075 | } |
| 3043 | auto info = extractDestructureInfo(assignment, true); | 3076 | auto info = extractDestructureInfo(assignment, true, false); |
| 3044 | if (!info.first.empty()) { | 3077 | if (!info.first.empty()) { |
| 3045 | for (const auto& destruct : info.first) | 3078 | for (const auto& destruct : info.first) |
| 3046 | for (const auto& item : destruct.items) | 3079 | for (const auto& item : destruct.items) |
| 3047 | if (item.isVariable) { | 3080 | if (!item.targetVar.empty()) { |
| 3048 | if (std::isupper(item.name[0]) && capital) { capital->decls.push_back(item.name); | 3081 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); |
| 3049 | } else if (any) { | 3082 | } else if (any) { |
| 3050 | any->decls.push_back(item.name); | 3083 | any->decls.push_back(item.targetVar); |
| 3051 | } | 3084 | } |
| 3052 | } | 3085 | } |
| 3053 | } | 3086 | } |
| @@ -4043,7 +4076,7 @@ private: | |||
| 4043 | auto value = x->new_ptr<Value_t>(); | 4076 | auto value = x->new_ptr<Value_t>(); |
| 4044 | value->item.set(chainValue); | 4077 | value->item.set(chainValue); |
| 4045 | auto exp = newExp(value, x); | 4078 | auto exp = newExp(value, x); |
| 4046 | callVar = singleVariableFrom(exp); | 4079 | callVar = singleVariableFrom(exp, true); |
| 4047 | if (callVar.empty()) { | 4080 | if (callVar.empty()) { |
| 4048 | callVar = getUnusedName("_call_"s); | 4081 | callVar = getUnusedName("_call_"s); |
| 4049 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4082 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -4672,7 +4705,7 @@ private: | |||
| 4672 | std::string indexVar = getUnusedName("_idx_"sv); | 4705 | std::string indexVar = getUnusedName("_idx_"sv); |
| 4673 | std::string keyVar = getUnusedName("_key_"sv); | 4706 | std::string keyVar = getUnusedName("_key_"sv); |
| 4674 | std::string valueVar = getUnusedName("_value_"sv); | 4707 | std::string valueVar = getUnusedName("_value_"sv); |
| 4675 | auto objVar = singleVariableFrom(spread->exp); | 4708 | auto objVar = singleVariableFrom(spread->exp, true); |
| 4676 | if (objVar.empty()) { | 4709 | if (objVar.empty()) { |
| 4677 | objVar = getUnusedName("_obj_"); | 4710 | objVar = getUnusedName("_obj_"); |
| 4678 | auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); | 4711 | auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); |
| @@ -5146,7 +5179,7 @@ private: | |||
| 5146 | switch (loopTarget->getId()) { | 5179 | switch (loopTarget->getId()) { |
| 5147 | case id<star_exp_t>(): { | 5180 | case id<star_exp_t>(): { |
| 5148 | auto star_exp = static_cast<star_exp_t*>(loopTarget); | 5181 | auto star_exp = static_cast<star_exp_t*>(loopTarget); |
| 5149 | auto listVar = singleVariableFrom(star_exp->value); | 5182 | auto listVar = singleVariableFrom(star_exp->value, true); |
| 5150 | if (!isLocal(listVar)) listVar.clear(); | 5183 | if (!isLocal(listVar)) listVar.clear(); |
| 5151 | auto indexVar = getUnusedName("_index_"sv); | 5184 | auto indexVar = getUnusedName("_index_"sv); |
| 5152 | varAfter.push_back(indexVar); | 5185 | varAfter.push_back(indexVar); |
| @@ -5816,7 +5849,7 @@ private: | |||
| 5816 | assignItem = std::move(temp.back()); | 5849 | assignItem = std::move(temp.back()); |
| 5817 | temp.pop_back(); | 5850 | temp.pop_back(); |
| 5818 | } else if (expList) { | 5851 | } else if (expList) { |
| 5819 | auto name = singleVariableFrom(expList); | 5852 | auto name = singleVariableFrom(expList, true); |
| 5820 | if (!name.empty()) { | 5853 | if (!name.empty()) { |
| 5821 | className = '\"' + name + '\"'; | 5854 | className = '\"' + name + '\"'; |
| 5822 | } | 5855 | } |
| @@ -5834,12 +5867,12 @@ private: | |||
| 5834 | if (auto assignment = assignmentFrom(statement)) { | 5867 | if (auto assignment = assignmentFrom(statement)) { |
| 5835 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); | 5868 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); |
| 5836 | varDefs.insert(varDefs.end(), names.begin(), names.end()); | 5869 | varDefs.insert(varDefs.end(), names.begin(), names.end()); |
| 5837 | auto info = extractDestructureInfo(assignment, true); | 5870 | auto info = extractDestructureInfo(assignment, true, false); |
| 5838 | if (!info.first.empty()) { | 5871 | if (!info.first.empty()) { |
| 5839 | for (const auto& destruct : info.first) | 5872 | for (const auto& destruct : info.first) |
| 5840 | for (const auto& item : destruct.items) | 5873 | for (const auto& item : destruct.items) |
| 5841 | if (item.isVariable && addToScope(item.name)) | 5874 | if (!item.targetVar.empty() && addToScope(item.targetVar)) |
| 5842 | varDefs.push_back(item.name); | 5875 | varDefs.push_back(item.targetVar); |
| 5843 | } | 5876 | } |
| 5844 | BLOCK_START | 5877 | BLOCK_START |
| 5845 | auto assign = assignment->action.as<Assign_t>(); | 5878 | auto assign = assignment->action.as<Assign_t>(); |
| @@ -6193,7 +6226,7 @@ private: | |||
| 6193 | auto vars = getAssignVars(with); | 6226 | auto vars = getAssignVars(with); |
| 6194 | if (vars.front().empty() || isGlobal(vars.front())) { | 6227 | if (vars.front().empty() || isGlobal(vars.front())) { |
| 6195 | if (with->assigns->values.objects().size() == 1) { | 6228 | if (with->assigns->values.objects().size() == 1) { |
| 6196 | auto var = singleVariableFrom(with->assigns->values.objects().front()); | 6229 | auto var = singleVariableFrom(with->assigns->values.objects().front(), true); |
| 6197 | if (!var.empty() && isLocal(var)) { | 6230 | if (!var.empty() && isLocal(var)) { |
| 6198 | withVar = var; | 6231 | withVar = var; |
| 6199 | } | 6232 | } |
| @@ -6239,7 +6272,7 @@ private: | |||
| 6239 | transformAssignment(assignment, temp); | 6272 | transformAssignment(assignment, temp); |
| 6240 | } | 6273 | } |
| 6241 | } else { | 6274 | } else { |
| 6242 | withVar = singleVariableFrom(with->valueList); | 6275 | withVar = singleVariableFrom(with->valueList, true); |
| 6243 | if (withVar.empty() || !isLocal(withVar)) { | 6276 | if (withVar.empty() || !isLocal(withVar)) { |
| 6244 | withVar = getUnusedName("_with_"sv); | 6277 | withVar = getUnusedName("_with_"sv); |
| 6245 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 6278 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -6265,11 +6298,11 @@ private: | |||
| 6265 | if (!names.empty()) { | 6298 | if (!names.empty()) { |
| 6266 | return traversal::Stop; | 6299 | return traversal::Stop; |
| 6267 | } | 6300 | } |
| 6268 | auto info = extractDestructureInfo(assignment, true); | 6301 | auto info = extractDestructureInfo(assignment, true, false); |
| 6269 | if (!info.first.empty()) { | 6302 | if (!info.first.empty()) { |
| 6270 | for (const auto& destruct : info.first) | 6303 | for (const auto& destruct : info.first) |
| 6271 | for (const auto& item : destruct.items) | 6304 | for (const auto& item : destruct.items) |
| 6272 | if (item.isVariable && !isDefined(item.name)) | 6305 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) |
| 6273 | return traversal::Stop; | 6306 | return traversal::Stop; |
| 6274 | } | 6307 | } |
| 6275 | BLOCK_START | 6308 | BLOCK_START |
| @@ -6417,12 +6450,12 @@ private: | |||
| 6417 | assignment->action.set(exportNode->assign); | 6450 | assignment->action.set(exportNode->assign); |
| 6418 | transformAssignment(assignment, out); | 6451 | transformAssignment(assignment, out); |
| 6419 | str_list names = transformAssignDefs(expList, DefOp::Get); | 6452 | str_list names = transformAssignDefs(expList, DefOp::Get); |
| 6420 | auto info = extractDestructureInfo(assignment, true); | 6453 | auto info = extractDestructureInfo(assignment, true, false); |
| 6421 | if (!info.first.empty()) { | 6454 | if (!info.first.empty()) { |
| 6422 | for (const auto& destruct : info.first) | 6455 | for (const auto& destruct : info.first) |
| 6423 | for (const auto& item : destruct.items) | 6456 | for (const auto& item : destruct.items) |
| 6424 | if (item.isVariable) | 6457 | if (!item.targetVar.empty()) |
| 6425 | names.push_back(item.name); | 6458 | names.push_back(item.targetVar); |
| 6426 | } | 6459 | } |
| 6427 | if (_info.exportDefault) { | 6460 | if (_info.exportDefault) { |
| 6428 | out.back().append(indent() + _info.moduleName + " = "s + names.back() + nlr(exportNode)); | 6461 | out.back().append(indent() + _info.moduleName + " = "s + names.back() + nlr(exportNode)); |
| @@ -6699,7 +6732,7 @@ private: | |||
| 6699 | void transformImportFrom(ImportFrom_t* import, str_list& out) { | 6732 | void transformImportFrom(ImportFrom_t* import, str_list& out) { |
| 6700 | str_list temp; | 6733 | str_list temp; |
| 6701 | auto x = import; | 6734 | auto x = import; |
| 6702 | auto objVar = singleVariableFrom(import->exp); | 6735 | auto objVar = singleVariableFrom(import->exp, true); |
| 6703 | ast_ptr<false, ExpListAssign_t> objAssign; | 6736 | ast_ptr<false, ExpListAssign_t> objAssign; |
| 6704 | if (objVar.empty()) { | 6737 | if (objVar.empty()) { |
| 6705 | objVar = getUnusedName("_obj_"sv); | 6738 | objVar = getUnusedName("_obj_"sv); |
| @@ -7065,7 +7098,7 @@ private: | |||
| 7065 | pushScope(); | 7098 | pushScope(); |
| 7066 | } | 7099 | } |
| 7067 | bool extraScope = false; | 7100 | bool extraScope = false; |
| 7068 | auto objVar = singleVariableFrom(switchNode->target); | 7101 | auto objVar = singleVariableFrom(switchNode->target, true); |
| 7069 | if (objVar.empty() || !isLocal(objVar)) { | 7102 | if (objVar.empty() || !isLocal(objVar)) { |
| 7070 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { | 7103 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { |
| 7071 | extraScope = true; | 7104 | extraScope = true; |
| @@ -7082,24 +7115,89 @@ private: | |||
| 7082 | transformAssignment(assignment, temp); | 7115 | transformAssignment(assignment, temp); |
| 7083 | } | 7116 | } |
| 7084 | const auto& branches = switchNode->branches.objects(); | 7117 | const auto& branches = switchNode->branches.objects(); |
| 7118 | int addScope = 0; | ||
| 7119 | bool firstBranch = true; | ||
| 7120 | std::string tabCheckVar; | ||
| 7085 | for (auto branch_ : branches) { | 7121 | for (auto branch_ : branches) { |
| 7086 | auto branch = static_cast<SwitchCase_t*>(branch_); | 7122 | auto branch = static_cast<SwitchCase_t*>(branch_); |
| 7087 | temp.push_back(indent() + (branches.front() == branch ? "if"s : "elseif"s)); | 7123 | if (auto value = singleValueFrom(branch->valueList); |
| 7088 | str_list tmp; | 7124 | value->item.is<simple_table_t>() || |
| 7089 | const auto& exprs = branch->valueList->exprs.objects(); | 7125 | value->getByPath<SimpleValue_t, TableLit_t>()) { |
| 7090 | for (auto exp_ : exprs) { | 7126 | if (!firstBranch) { |
| 7091 | auto exp = static_cast<Exp_t*>(exp_); | 7127 | temp.push_back(indent() + "else"s + nll(branch)); |
| 7092 | transformExp(exp, tmp, ExpUsage::Closure); | 7128 | pushScope(); |
| 7093 | if (!singleValueFrom(exp)) { | 7129 | addScope++; |
| 7094 | tmp.back() = '(' + tmp.back() + ')'; | 7130 | } |
| 7131 | if (tabCheckVar.empty()) { | ||
| 7132 | if (!extraScope) { | ||
| 7133 | temp.push_back(indent() + "do"s + nll(branch)); | ||
| 7134 | pushScope(); | ||
| 7135 | extraScope = true; | ||
| 7136 | } | ||
| 7137 | tabCheckVar = getUnusedName("_tab_"); | ||
| 7138 | forceAddToScope(tabCheckVar); | ||
| 7139 | temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + globalVar("type", branch) + '(' + objVar + ')' + nll(branch)); | ||
| 7140 | } | ||
| 7141 | std::string matchVar; | ||
| 7142 | bool lastBranch = branches.back() == branch_; | ||
| 7143 | if (!lastBranch) { | ||
| 7144 | matchVar = getUnusedName("_match_"); | ||
| 7145 | forceAddToScope(matchVar); | ||
| 7146 | temp.push_back(indent() + "local "s + matchVar + " = false"s + nll(branch)); | ||
| 7147 | } | ||
| 7148 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); | ||
| 7149 | pushScope(); | ||
| 7150 | auto assignment = assignmentFrom(static_cast<Exp_t*>(branch->valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); | ||
| 7151 | auto info = extractDestructureInfo(assignment, true, false); | ||
| 7152 | transformAssignment(assignment, temp, true); | ||
| 7153 | temp.push_back(indent() + "if"s); | ||
| 7154 | bool firstItem = true; | ||
| 7155 | for (const auto& destruct : info.first) { | ||
| 7156 | for (const auto& item : destruct.items) { | ||
| 7157 | str_list tmp; | ||
| 7158 | transformExp(item.target, tmp, ExpUsage::Closure); | ||
| 7159 | temp.back().append((firstItem ? " " : " and "s) + tmp.back() + " ~= nil"s); | ||
| 7160 | if (firstItem) firstItem = false; | ||
| 7161 | } | ||
| 7162 | } | ||
| 7163 | temp.back().append(" then"s + nll(branch)); | ||
| 7164 | pushScope(); | ||
| 7165 | transform_plain_body(branch->body, temp, usage, assignList); | ||
| 7166 | if (!lastBranch) { | ||
| 7167 | temp.push_back(indent() + matchVar + " = true"s + nll(branch)); | ||
| 7168 | } | ||
| 7169 | popScope(); | ||
| 7170 | if (!lastBranch) { | ||
| 7171 | temp.push_back(indent() + "end"s + nll(branch)); | ||
| 7172 | popScope(); | ||
| 7173 | temp.push_back(indent() + "end"s + nll(branch)); | ||
| 7174 | temp.push_back(indent() + "if not "s + matchVar + " then"s + nll(branch)); | ||
| 7175 | pushScope(); | ||
| 7176 | addScope++; | ||
| 7177 | } else { | ||
| 7178 | temp.push_back(indent() + "end"s + nll(branch)); | ||
| 7179 | popScope(); | ||
| 7180 | } | ||
| 7181 | firstBranch = true; | ||
| 7182 | } else { | ||
| 7183 | temp.push_back(indent() + (firstBranch ? "if"s : "elseif"s)); | ||
| 7184 | firstBranch = false; | ||
| 7185 | str_list tmp; | ||
| 7186 | const auto& exprs = branch->valueList->exprs.objects(); | ||
| 7187 | for (auto exp_ : exprs) { | ||
| 7188 | auto exp = static_cast<Exp_t*>(exp_); | ||
| 7189 | transformExp(exp, tmp, ExpUsage::Closure); | ||
| 7190 | if (!singleValueFrom(exp)) { | ||
| 7191 | tmp.back() = '(' + tmp.back() + ')'; | ||
| 7192 | } | ||
| 7193 | temp.back().append(' ' + tmp.back() + " == "s + | ||
| 7194 | (exp == exprs.back() ? objVar : objVar + " or"s)); | ||
| 7095 | } | 7195 | } |
| 7096 | temp.back().append(' ' + tmp.back() + " == "s + | 7196 | temp.back().append(" then"s + nll(branch)); |
| 7097 | (exp == exprs.back() ? objVar : objVar + " or"s)); | 7197 | pushScope(); |
| 7198 | transform_plain_body(branch->body, temp, usage, assignList); | ||
| 7199 | popScope(); | ||
| 7098 | } | 7200 | } |
| 7099 | temp.back().append(" then"s + nll(branch)); | ||
| 7100 | pushScope(); | ||
| 7101 | transform_plain_body(branch->body, temp, usage, assignList); | ||
| 7102 | popScope(); | ||
| 7103 | } | 7201 | } |
| 7104 | if (switchNode->lastBranch) { | 7202 | if (switchNode->lastBranch) { |
| 7105 | temp.push_back(indent() + "else"s + nll(switchNode->lastBranch)); | 7203 | temp.push_back(indent() + "else"s + nll(switchNode->lastBranch)); |
| @@ -7107,6 +7205,11 @@ private: | |||
| 7107 | transform_plain_body(switchNode->lastBranch, temp, usage, assignList); | 7205 | transform_plain_body(switchNode->lastBranch, temp, usage, assignList); |
| 7108 | popScope(); | 7206 | popScope(); |
| 7109 | } | 7207 | } |
| 7208 | while (addScope > 0) { | ||
| 7209 | addScope--; | ||
| 7210 | temp.push_back(indent() + "end"s + nlr(switchNode)); | ||
| 7211 | popScope(); | ||
| 7212 | } | ||
| 7110 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 7213 | temp.push_back(indent() + "end"s + nlr(switchNode)); |
| 7111 | if (usage == ExpUsage::Closure) { | 7214 | if (usage == ExpUsage::Closure) { |
| 7112 | _enableReturn.pop(); | 7215 | _enableReturn.pop(); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 78b4713..199c0bd 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -225,7 +225,7 @@ YueParser::YueParser() { | |||
| 225 | WithExp = ExpList >> -Assign; | 225 | WithExp = ExpList >> -Assign; |
| 226 | 226 | ||
| 227 | With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do"); | 227 | With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do"); |
| 228 | SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(ExpList)) >> plain_body_with("then"); | 228 | SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(SwitchList)) >> plain_body_with("then"); |
| 229 | SwitchElse = Space >> key("else") >> plain_body; | 229 | SwitchElse = Space >> key("else") >> plain_body; |
| 230 | 230 | ||
| 231 | SwitchBlock = *EmptyLine >> | 231 | SwitchBlock = *EmptyLine >> |
| @@ -235,6 +235,9 @@ YueParser::YueParser() { | |||
| 235 | -(Break >> *EmptyLine >> CheckIndent >> SwitchElse) >> | 235 | -(Break >> *EmptyLine >> CheckIndent >> SwitchElse) >> |
| 236 | PopIndent; | 236 | PopIndent; |
| 237 | 237 | ||
| 238 | exp_not_tab = not_(simple_table | TableLit) >> Exp; | ||
| 239 | |||
| 240 | SwitchList = Seperator >> Exp >> *(sym(',') >> exp_not_tab); | ||
| 238 | Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) | 241 | Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) |
| 239 | >> -Space >> Break >> SwitchBlock; | 242 | >> -Space >> Break >> SwitchBlock; |
| 240 | 243 | ||
| @@ -550,14 +553,14 @@ YueParser::YueParser() { | |||
| 550 | symx(':') >> not_(':') >> | 553 | symx(':') >> not_(':') >> |
| 551 | (Exp | TableBlock | +SpaceBreak >> Exp); | 554 | (Exp | TableBlock | +SpaceBreak >> Exp); |
| 552 | 555 | ||
| 553 | default_pair = (sym(':') >> Variable >> not_('#') >> Seperator | KeyName >> symx(':') >> Seperator >> Exp | Exp >> Seperator) >> sym('=') >> Exp; | 556 | default_pair = (sym(':') >> Variable >> not_('#') >> Seperator | KeyName >> symx(':') >> Seperator >> exp_not_tab | exp_not_tab >> Seperator) >> sym('=') >> Exp; |
| 554 | 557 | ||
| 555 | meta_variable_pair = sym(':') >> Variable >> expr('#'); | 558 | meta_variable_pair = sym(':') >> Variable >> expr('#'); |
| 556 | 559 | ||
| 557 | meta_normal_pair = Space >> -(Name | symx('[') >> not_('[') >> Exp >> sym(']')) >> expr("#:") >> | 560 | meta_normal_pair = Space >> -(Name | symx('[') >> not_('[') >> Exp >> sym(']')) >> expr("#:") >> |
| 558 | (Exp | TableBlock | +(SpaceBreak) >> Exp); | 561 | (Exp | TableBlock | +(SpaceBreak) >> Exp); |
| 559 | 562 | ||
| 560 | meta_default_pair = (sym(':') >> Variable >> expr('#') >> Seperator | Space >> -Name >> expr("#:") >> Seperator >> Exp) >> sym('=') >> Exp; | 563 | meta_default_pair = (sym(':') >> Variable >> expr('#') >> Seperator | Space >> -Name >> expr("#:") >> Seperator >> exp_not_tab) >> sym('=') >> Exp; |
| 561 | 564 | ||
| 562 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; | 565 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; |
| 563 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | 566 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index eea3027..b71a67c 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -188,6 +188,7 @@ private: | |||
| 188 | rule pipe_exp; | 188 | rule pipe_exp; |
| 189 | rule expo_value; | 189 | rule expo_value; |
| 190 | rule expo_exp; | 190 | rule expo_exp; |
| 191 | rule exp_not_tab; | ||
| 191 | rule empty_line_stop; | 192 | rule empty_line_stop; |
| 192 | rule Line; | 193 | rule Line; |
| 193 | rule Shebang; | 194 | rule Shebang; |
| @@ -230,6 +231,7 @@ private: | |||
| 230 | AST_RULE(ExpList) | 231 | AST_RULE(ExpList) |
| 231 | AST_RULE(Return) | 232 | AST_RULE(Return) |
| 232 | AST_RULE(With) | 233 | AST_RULE(With) |
| 234 | AST_RULE(SwitchList) | ||
| 233 | AST_RULE(SwitchCase) | 235 | AST_RULE(SwitchCase) |
| 234 | AST_RULE(Switch) | 236 | AST_RULE(Switch) |
| 235 | AST_RULE(assignment) | 237 | AST_RULE(assignment) |
