aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-08-17 16:21:39 +0800
committerLi Jin <dragon-fly@qq.com>2021-08-17 16:21:39 +0800
commit792e942f5269655ee03c48400999f3604b84396c (patch)
treecc3d6fe477f08ffed985e297ee789d2213387a44
parent7295e9efe092fca4ab6eebf6408af93d5f56dd80 (diff)
downloadyuescript-792e942f5269655ee03c48400999f3604b84396c.tar.gz
yuescript-792e942f5269655ee03c48400999f3604b84396c.tar.bz2
yuescript-792e942f5269655ee03c48400999f3604b84396c.zip
fix issue #64.
-rw-r--r--spec/inputs/destructure.yue29
-rw-r--r--src/yuescript/yue_ast.h30
-rw-r--r--src/yuescript/yue_compiler.cpp278
-rw-r--r--src/yuescript/yue_parser.cpp9
-rw-r--r--src/yuescript/yue_parser.h3
5 files changed, 319 insertions, 30 deletions
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue
index 7bf5a88..c46cef5 100644
--- a/spec/inputs/destructure.yue
+++ b/spec/inputs/destructure.yue
@@ -142,3 +142,32 @@ do
142 142
143 {:a},b = a\if(123) + t, 123 143 {:a},b = a\if(123) + t, 123
144 144
145do
146 {:name = "nameless", :job = "jobless"} = person
147
148 request = (url, options = {}) ->
149 {
150 :method = "GET"
151 :headers = {}
152 :parameters = {}
153 :payload = ""
154 :ok
155 :err
156 :final
157 } = options
158 res = makeRequest(url, method, parameters, payload, ok, err, final)
159 return res
160
161 {key1: {key2: value1 = 123}, :key3 = "abc"} = tb
162
163 {#: mt = {__index: {abc: 123}}, #: {:call# = (-> {}), :add#}} = tb
164
165 {x: {#: mtx = {}}, :y, z: zItem, :index# = -> nil} = tb
166
167 {#: {func: a.b(-> 123).c = item?.defVal}} = tb
168
169do
170 {#: mt = {}, sub#: subFunc} = tb.x
171
172do
173 {x: {#: mt = {}, sub#: subFunc}} = tb
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 7d79341..69c9607 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -426,6 +426,14 @@ AST_NODE(normal_pair)
426 AST_MEMBER(normal_pair, &key, &value) 426 AST_MEMBER(normal_pair, &key, &value)
427AST_END(normal_pair) 427AST_END(normal_pair)
428 428
429AST_NODE(default_pair)
430 ast_sel<true, Variable_t, KeyName_t> key;
431 ast_ptr<true, Seperator_t> sep;
432 ast_ptr<false, Exp_t> value;
433 ast_ptr<true, Exp_t> defVal;
434 AST_MEMBER(default_pair, &key, &sep, &value, &defVal)
435AST_END(default_pair)
436
429AST_NODE(meta_variable_pair) 437AST_NODE(meta_variable_pair)
430 ast_ptr<true, Variable_t> name; 438 ast_ptr<true, Variable_t> name;
431 AST_MEMBER(meta_variable_pair, &name) 439 AST_MEMBER(meta_variable_pair, &name)
@@ -437,6 +445,14 @@ AST_NODE(meta_normal_pair)
437 AST_MEMBER(meta_normal_pair, &key, &value) 445 AST_MEMBER(meta_normal_pair, &key, &value)
438AST_END(meta_normal_pair) 446AST_END(meta_normal_pair)
439 447
448AST_NODE(meta_default_pair)
449 ast_sel<false, Variable_t, Name_t> key;
450 ast_ptr<true, Seperator_t> sep;
451 ast_ptr<false, Exp_t> value;
452 ast_ptr<true, Exp_t> defVal;
453 AST_MEMBER(meta_default_pair, &key, &sep, &value, &defVal)
454AST_END(meta_default_pair)
455
440AST_NODE(simple_table) 456AST_NODE(simple_table)
441 ast_ptr<true, Seperator_t> sep; 457 ast_ptr<true, Seperator_t> sep;
442 ast_sel_list<true, variable_pair_t, normal_pair_t, meta_variable_pair_t, meta_normal_pair_t> pairs; 458 ast_sel_list<true, variable_pair_t, normal_pair_t, meta_variable_pair_t, meta_normal_pair_t> pairs;
@@ -562,21 +578,29 @@ AST_END(Value)
562AST_LEAF(default_value) 578AST_LEAF(default_value)
563AST_END(default_value) 579AST_END(default_value)
564 580
581class default_pair_t;
582class meta_default_pair_t;
583
565AST_NODE(TableLit) 584AST_NODE(TableLit)
566 ast_ptr<true, Seperator_t> sep; 585 ast_ptr<true, Seperator_t> sep;
567 ast_sel_list<false, variable_pair_t, normal_pair_t, Exp_t, meta_variable_pair_t, meta_normal_pair_t> values; 586 ast_sel_list<false,
587 variable_pair_t, normal_pair_t, Exp_t, default_pair_t,
588 meta_variable_pair_t, meta_normal_pair_t, meta_default_pair_t> values;
568 AST_MEMBER(TableLit, &sep, &values) 589 AST_MEMBER(TableLit, &sep, &values)
569AST_END(TableLit) 590AST_END(TableLit)
570 591
571AST_NODE(TableBlockIndent) 592AST_NODE(TableBlockIndent)
572 ast_ptr<true, Seperator_t> sep; 593 ast_ptr<true, Seperator_t> sep;
573 ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, meta_variable_pair_t, meta_normal_pair_t> values; 594 ast_sel_list<false,
595 variable_pair_t, normal_pair_t, TableBlockIndent_t, default_pair_t,
596 meta_variable_pair_t, meta_normal_pair_t, meta_default_pair_t> values;
574 AST_MEMBER(TableBlockIndent, &sep, &values) 597 AST_MEMBER(TableBlockIndent, &sep, &values)
575AST_END(TableBlockIndent) 598AST_END(TableBlockIndent)
576 599
577AST_NODE(TableBlock) 600AST_NODE(TableBlock)
578 ast_ptr<true, Seperator_t> sep; 601 ast_ptr<true, Seperator_t> sep;
579 ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, Exp_t, TableBlock_t, meta_variable_pair_t, meta_normal_pair_t> values; 602 ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, Exp_t, TableBlock_t, default_pair_t,
603 meta_variable_pair_t, meta_normal_pair_t, meta_default_pair_t> values;
580 AST_MEMBER(TableBlock, &sep, &values) 604 AST_MEMBER(TableBlock, &sep, &values)
581AST_END(TableBlock) 605AST_END(TableBlock)
582 606
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index ca846a5..8e4072f 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -56,7 +56,7 @@ using namespace parserlib;
56 56
57typedef std::list<std::string> str_list; 57typedef std::list<std::string> str_list;
58 58
59const std::string_view version = "0.7.17"sv; 59const std::string_view version = "0.7.18"sv;
60const std::string_view extension = "yue"sv; 60const std::string_view extension = "yue"sv;
61 61
62class YueCompilerImpl { 62class YueCompilerImpl {
@@ -248,6 +248,8 @@ private:
248 bool isVariable = false; 248 bool isVariable = false;
249 std::string name; 249 std::string name;
250 std::string structure; 250 std::string structure;
251 ast_ptr<true, Exp_t> defVal;
252 bool isMetatable = false;
251 }; 253 };
252 254
253 struct Destructure { 255 struct Destructure {
@@ -1364,45 +1366,102 @@ private:
1364 if (info.second) { 1366 if (info.second) {
1365 transformAssignmentCommon(info.second, temp); 1367 transformAssignmentCommon(info.second, temp);
1366 } 1368 }
1367 for (const auto& destruct : info.first) { 1369 for (auto& destruct : info.first) {
1370 std::list<std::pair<std::string, std::string>> leftPairs;
1368 if (destruct.items.size() == 1) { 1371 if (destruct.items.size() == 1) {
1369 auto& pair = destruct.items.front(); 1372 auto& pair = destruct.items.front();
1370 _buf << indent(); 1373 if (!pair.isVariable && pair.defVal) {
1371 if (pair.isVariable) { 1374 auto objVar = getUnusedName("_obj_"sv);
1372 checkConst(pair.name, assignment); 1375 leftPairs.push_back({pair.name, objVar});
1373 if (!isDefined(pair.name)) _buf << "local "s; 1376 pair.name = objVar;
1377 pair.isVariable = true;
1378 }
1379 if (pair.isMetatable) {
1380 if (pair.isVariable) {
1381 checkConst(pair.name, assignment);
1382 if (addToScope(pair.name)) {
1383 _buf << indent() << "local "sv << pair.name << nll(assignment);
1384 }
1385 }
1386 bool valueDefined = isDefined(destruct.value);
1387 std::string objVar;
1388 if (valueDefined) {
1389 objVar = destruct.value;
1390 } else {
1391 _buf << indent() << "do"sv << nll(assignment);
1392 pushScope();
1393 objVar = getUnusedName("_obj_"sv);
1394 addToScope(objVar);
1395 _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment);
1396 temp.push_back(clearBuf());
1397 }
1398 auto valueExp = toAst<Exp_t>(objVar + pair.structure, assignment);
1399 transformExp(valueExp, temp, ExpUsage::Closure);
1400 _buf << indent() << pair.name << " = "sv << temp.back() << nll(assignment);
1401 if (!valueDefined) {
1402 popScope();
1403 _buf << indent() << "end"sv << nlr(assignment);
1404 }
1405 temp.back() = clearBuf();
1406 } else {
1407 _buf << indent();
1408 if (pair.isVariable) {
1409 checkConst(pair.name, assignment);
1410 if (addToScope(pair.name)) _buf << "local "sv;
1411 }
1412 _buf << pair.name << " = "sv << destruct.value << pair.structure << nll(assignment);
1413 temp.push_back(clearBuf());
1374 } 1414 }
1375 _buf << pair.name << " = "sv << destruct.value << pair.structure << nll(assignment);
1376 addToScope(pair.name);
1377 temp.push_back(clearBuf());
1378 } else if (_parser.match<Name_t>(destruct.value) && isDefined(destruct.value)) { 1415 } else if (_parser.match<Name_t>(destruct.value) && isDefined(destruct.value)) {
1379 str_list defs, names, values; 1416 str_list defs, names, values;
1380 for (const auto& item : destruct.items) { 1417 bool isMetatable = false;
1418 for (auto& item : destruct.items) {
1381 if (item.isVariable) { 1419 if (item.isVariable) {
1382 checkConst(item.name, assignment); 1420 checkConst(item.name, assignment);
1383 if (addToScope(item.name)) defs.push_back(item.name); 1421 if (addToScope(item.name)) defs.push_back(item.name);
1422 } else if (item.defVal) {
1423 auto objVar = getUnusedName("_obj_"sv);
1424 addToScope(objVar);
1425 defs.push_back(objVar);
1426 leftPairs.push_back({item.name, objVar});
1427 item.name = objVar;
1384 } 1428 }
1429 if (item.isMetatable) isMetatable = true;
1385 names.push_back(item.name); 1430 names.push_back(item.name);
1386 values.push_back(item.structure); 1431 values.push_back(item.structure);
1387 } 1432 }
1388 for (auto& v : values) v.insert(0, destruct.value); 1433 for (auto& v : values) v.insert(0, destruct.value);
1434 if (isMetatable) {
1435 auto newExpList = toAst<ExpList_t>(join(values, ","sv), assignment);
1436 transformExpList(newExpList, temp);
1437 } else {
1438 temp.push_back(join(values, ", "sv));
1439 }
1389 if (defs.empty()) { 1440 if (defs.empty()) {
1390 _buf << indent() << join(names, ", "sv) << " = "sv << join(values, ", "sv) << nll(assignment); 1441 _buf << indent() << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment);
1391 } else { 1442 } else {
1392 _buf << indent() << "local "sv; 1443 _buf << indent() << "local "sv;
1393 if (defs.size() != names.size()) { 1444 if (defs.size() != names.size()) {
1394 _buf << join(defs,", "sv) << nll(assignment) << indent(); 1445 _buf << join(defs, ", "sv) << nll(assignment) << indent();
1395 } 1446 }
1396 _buf << join(names, ", "sv) << " = "sv << join(values, ", "sv) << nll(assignment); 1447 _buf << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment);
1397 } 1448 }
1398 temp.push_back(clearBuf()); 1449 temp.back() = clearBuf();
1399 } else { 1450 } else {
1400 str_list defs, names, values; 1451 str_list defs, names, values;
1401 for (const auto& item : destruct.items) { 1452 bool isMetatable = false;
1453 for (auto& item : destruct.items) {
1402 if (item.isVariable) { 1454 if (item.isVariable) {
1403 checkConst(item.name, assignment); 1455 checkConst(item.name, assignment);
1404 if (addToScope(item.name)) defs.push_back(item.name); 1456 if (addToScope(item.name)) defs.push_back(item.name);
1457 } else if (item.defVal) {
1458 auto objVar = getUnusedName("_obj_"sv);
1459 addToScope(objVar);
1460 defs.push_back(objVar);
1461 leftPairs.push_back({item.name, objVar});
1462 item.name = objVar;
1405 } 1463 }
1464 if (item.isMetatable) isMetatable = true;
1406 names.push_back(item.name); 1465 names.push_back(item.name);
1407 values.push_back(item.structure); 1466 values.push_back(item.structure);
1408 } 1467 }
@@ -1410,13 +1469,34 @@ private:
1410 _buf << indent() << "do"sv << nll(assignment); 1469 _buf << indent() << "do"sv << nll(assignment);
1411 pushScope(); 1470 pushScope();
1412 auto objVar = getUnusedName("_obj_"sv); 1471 auto objVar = getUnusedName("_obj_"sv);
1472 addToScope(objVar);
1413 for (auto& v : values) v.insert(0, objVar); 1473 for (auto& v : values) v.insert(0, objVar);
1474 if (isMetatable) {
1475 auto newExpList = toAst<ExpList_t>(join(values, ","sv), assignment);
1476 transformExpList(newExpList, temp);
1477 } else {
1478 temp.push_back(join(values, ", "sv));
1479 }
1414 _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment); 1480 _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment);
1415 _buf << indent() << join(names, ", "sv) << " = "sv << join(values, ", "sv) << nll(assignment); 1481 _buf << indent() << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment);
1416 popScope(); 1482 popScope();
1417 _buf << indent() << "end"sv << nll(assignment); 1483 _buf << indent() << "end"sv << nll(assignment);
1418 temp.push_back(clearBuf()); 1484 temp.back() = clearBuf();
1485 }
1486 for (const auto& item : destruct.items) {
1487 if (item.defVal) {
1488 auto stmt = toAst<Statement_t>(item.name + "=nil if "s + item.name + "==nil", item.defVal);
1489 auto defAssign = stmt->content.as<ExpListAssign_t>();
1490 auto assign = defAssign->action.as<Assign_t>();
1491 assign->values.clear();
1492 assign->values.push_back(item.defVal);
1493 transformStatement(stmt, temp);
1494 }
1419 } 1495 }
1496 for (const auto& item : leftPairs) {
1497 _buf << indent() << item.first << " = "sv << item.second << nll(assignment);
1498 }
1499 temp.push_back(clearBuf());
1420 } 1500 }
1421 out.push_back(join(temp)); 1501 out.push_back(join(temp));
1422 } 1502 }
@@ -1463,6 +1543,7 @@ private:
1463 if (!tableItems) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); 1543 if (!tableItems) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node));
1464 std::list<DestructItem> pairs; 1544 std::list<DestructItem> pairs;
1465 int index = 0; 1545 int index = 0;
1546 auto subMetaDestruct = node->new_ptr<TableLit_t>();
1466 for (auto pair : *tableItems) { 1547 for (auto pair : *tableItems) {
1467 switch (pair->getId()) { 1548 switch (pair->getId()) {
1468 case id<Exp_t>(): { 1549 case id<Exp_t>(): {
@@ -1477,7 +1558,8 @@ private:
1477 auto subPairs = destructFromExp(pair); 1558 auto subPairs = destructFromExp(pair);
1478 for (auto& p : subPairs) { 1559 for (auto& p : subPairs) {
1479 pairs.push_back({p.isVariable, p.name, 1560 pairs.push_back({p.isVariable, p.name,
1480 '[' + std::to_string(index) + ']' + p.structure}); 1561 '[' + std::to_string(index) + ']' + p.structure,
1562 p.defVal, p.isMetatable});
1481 } 1563 }
1482 } else { 1564 } else {
1483 bool lintGlobal = _config.lintGlobalVariable; 1565 bool lintGlobal = _config.lintGlobalVariable;
@@ -1494,7 +1576,8 @@ private:
1494 pairs.push_back({ 1576 pairs.push_back({
1495 isVariable, 1577 isVariable,
1496 varName, 1578 varName,
1497 '[' + std::to_string(index) + ']' 1579 '[' + std::to_string(index) + ']',
1580 nullptr
1498 }); 1581 });
1499 } 1582 }
1500 break; 1583 break;
@@ -1503,9 +1586,9 @@ private:
1503 auto vp = static_cast<variable_pair_t*>(pair); 1586 auto vp = static_cast<variable_pair_t*>(pair);
1504 auto name = _parser.toString(vp->name); 1587 auto name = _parser.toString(vp->name);
1505 if (Keywords.find(name) != Keywords.end()) { 1588 if (Keywords.find(name) != Keywords.end()) {
1506 pairs.push_back({true, name, "[\""s + name + "\"]"s}); 1589 pairs.push_back({true, name, "[\""s + name + "\"]"s, nullptr});
1507 } else { 1590 } else {
1508 pairs.push_back({true, name, '.' + name}); 1591 pairs.push_back({true, name, '.' + name, nullptr});
1509 } 1592 }
1510 break; 1593 break;
1511 } 1594 }
@@ -1532,7 +1615,9 @@ private:
1532 pairs.push_back({ 1615 pairs.push_back({
1533 p.isVariable, 1616 p.isVariable,
1534 p.name, 1617 p.name,
1535 keyName + p.structure 1618 keyName + p.structure,
1619 p.defVal,
1620 p.isMetatable
1536 }); 1621 });
1537 } 1622 }
1538 } else { 1623 } else {
@@ -1549,7 +1634,8 @@ private:
1549 pairs.push_back({ 1634 pairs.push_back({
1550 isVariable, 1635 isVariable,
1551 varName, 1636 varName,
1552 keyName 1637 keyName,
1638 nullptr
1553 }); 1639 });
1554 } 1640 }
1555 break; 1641 break;
@@ -1560,7 +1646,9 @@ private:
1560 pairs.push_back({ 1646 pairs.push_back({
1561 p.isVariable, 1647 p.isVariable,
1562 p.name, 1648 p.name,
1563 keyName + p.structure 1649 keyName + p.structure,
1650 p.defVal,
1651 p.isMetatable
1564 }); 1652 });
1565 } 1653 }
1566 } 1654 }
@@ -1574,14 +1662,126 @@ private:
1574 pairs.push_back({ 1662 pairs.push_back({
1575 p.isVariable, 1663 p.isVariable,
1576 p.name, 1664 p.name,
1577 '[' + std::to_string(index) + ']' + p.structure 1665 '[' + std::to_string(index) + ']' + p.structure,
1666 p.defVal,
1667 p.isMetatable
1668 });
1669 }
1670 break;
1671 }
1672 case id<default_pair_t>() : {
1673 auto dp = static_cast<default_pair_t*>(pair);
1674 std::string keyName, valueStr;
1675 if (dp->key) {
1676 auto key = dp->key->getByPath<Name_t>();
1677 if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, dp));
1678 keyName = _parser.toString(key);
1679 if (!dp->value) valueStr = keyName;
1680 if (Keywords.find(keyName) != Keywords.end()) {
1681 keyName = "[\""s + keyName + "\"]"s;
1682 }
1683 else {
1684 keyName = "."s + keyName;
1685 }
1686 }
1687 if (auto exp = dp->value.as<Exp_t>()) {
1688 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp));
1689 bool lintGlobal = _config.lintGlobalVariable;
1690 _config.lintGlobalVariable = false;
1691 auto varName = singleVariableFrom(exp);
1692 bool isVariable = !varName.empty();
1693 if (!isVariable) {
1694 str_list temp;
1695 transformExp(exp, temp, ExpUsage::Closure);
1696 varName = std::move(temp.back());
1697 }
1698 _config.lintGlobalVariable = lintGlobal;
1699 pairs.push_back({
1700 isVariable,
1701 varName,
1702 keyName,
1703 dp->defVal
1704 });
1705 } else {
1706 pairs.push_back({
1707 true,
1708 valueStr,
1709 keyName,
1710 dp->defVal
1578 }); 1711 });
1579 } 1712 }
1580 break; 1713 break;
1581 } 1714 }
1715 case id<meta_default_pair_t>(): {
1716 auto mp = static_cast<meta_default_pair_t*>(pair);
1717 auto newPair = pair->new_ptr<default_pair_t>();
1718 if (mp->key) {
1719 auto key = _parser.toString(mp->key);
1720 _buf << "__"sv << key;
1721 auto newKey = toAst<KeyName_t>(clearBuf(), mp->key);
1722 newPair->key.set(newKey);
1723 if (newPair->value) {
1724 newPair->value.set(mp->value);
1725 }
1726 else {
1727 newPair->value.set(toAst<Exp_t>(key, mp->key));
1728 }
1729 } else {
1730 newPair->value.set(mp->value);
1731 }
1732 newPair->defVal.set(mp->defVal);
1733 subMetaDestruct->values.push_back(newPair);
1734 break;
1735 }
1736 case id<meta_variable_pair_t>(): {
1737 auto mp = static_cast<meta_variable_pair_t*>(pair);
1738 auto name = _parser.toString(mp->name);
1739 _buf << "__"sv << name << ':' << name;
1740 auto newPair = toAst<normal_pair_t>(clearBuf(), pair);
1741 subMetaDestruct->values.push_back(newPair);
1742 break;
1743 }
1744 case id<meta_normal_pair_t>(): {
1745 auto mp = static_cast<meta_normal_pair_t*>(pair);
1746 auto newPair = pair->new_ptr<normal_pair_t>();
1747 if (mp->key) {
1748 switch (mp->key->getId()) {
1749 case id<Name_t>(): {
1750 auto key = _parser.toString(mp->key);
1751 _buf << "__"sv << key;
1752 auto newKey = toAst<KeyName_t>(clearBuf(), mp->key);
1753 newPair->key.set(newKey);
1754 break;
1755 }
1756 case id<Exp_t>():
1757 newPair->key.set(mp->key);
1758 break;
1759 default: YUEE("AST node mismatch", mp->key); break;
1760 }
1761 }
1762 newPair->value.set(mp->value);
1763 subMetaDestruct->values.push_back(newPair);
1764 break;
1765 }
1582 default: YUEE("AST node mismatch", pair); break; 1766 default: YUEE("AST node mismatch", pair); break;
1583 } 1767 }
1584 } 1768 }
1769 if (!subMetaDestruct->values.empty()) {
1770 auto simpleValue = subMetaDestruct->new_ptr<SimpleValue_t>();
1771 simpleValue->value.set(subMetaDestruct);
1772 auto value = subMetaDestruct->new_ptr<Value_t>();
1773 value->item.set(simpleValue);
1774 auto subPairs = destructFromExp(newExp(value, subMetaDestruct));
1775 for (const auto& p : subPairs) {
1776 pairs.push_back({
1777 p.isVariable,
1778 p.name,
1779 ".#"s + p.structure,
1780 p.defVal,
1781 true
1782 });
1783 }
1784 }
1585 return pairs; 1785 return pairs;
1586 } 1786 }
1587 1787
@@ -1638,6 +1838,26 @@ private:
1638 } 1838 }
1639 for (auto item : *dlist) { 1839 for (auto item : *dlist) {
1640 switch (item->getId()) { 1840 switch (item->getId()) {
1841 case id<meta_default_pair_t>(): {
1842 auto mp = static_cast<meta_default_pair_t*>(item);
1843 auto newPair = item->new_ptr<default_pair_t>();
1844 if (mp->key) {
1845 auto key = _parser.toString(mp->key);
1846 _buf << "__"sv << key;
1847 auto newKey = toAst<KeyName_t>(clearBuf(), mp->key);
1848 newPair->key.set(newKey);
1849 if (newPair->value) {
1850 newPair->value.set(mp->value);
1851 } else {
1852 newPair->value.set(toAst<Exp_t>(key, mp->key));
1853 }
1854 } else {
1855 newPair->value.set(mp->value);
1856 }
1857 newPair->defVal.set(mp->defVal);
1858 subMetaDestruct->values.push_back(newPair);
1859 break;
1860 }
1641 case id<meta_variable_pair_t>(): { 1861 case id<meta_variable_pair_t>(): {
1642 auto mp = static_cast<meta_variable_pair_t*>(item); 1862 auto mp = static_cast<meta_variable_pair_t*>(item);
1643 auto name = _parser.toString(mp->name); 1863 auto name = _parser.toString(mp->name);
@@ -5344,6 +5564,14 @@ private:
5344 } 5564 }
5345 break; 5565 break;
5346 } 5566 }
5567 case id<default_pair_t>(): {
5568 throw std::logic_error(_info.errorMessage("invalid use of default value"sv, static_cast<default_pair_t*>(pair)->defVal));
5569 break;
5570 }
5571 case id<meta_default_pair_t>(): {
5572 throw std::logic_error(_info.errorMessage("invalid use of default value"sv, static_cast<meta_default_pair_t*>(pair)->defVal));
5573 break;
5574 }
5347 default: YUEE("AST node mismatch", pair); break; 5575 default: YUEE("AST node mismatch", pair); break;
5348 } 5576 }
5349 if (!isMetamethod) { 5577 if (!isMetamethod) {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index f530776..a3e70c6 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -465,7 +465,7 @@ YueParser::YueParser() {
465 and_(expr('[')) >> LuaString | 465 and_(expr('[')) >> LuaString |
466 and_(expr('{')) >> TableLit); 466 and_(expr('{')) >> TableLit);
467 467
468 TableValue = KeyValue | Exp; 468 TableValue = KeyValueDef | Exp;
469 469
470 table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); 470 table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(',');
471 471
@@ -536,14 +536,19 @@ YueParser::YueParser() {
536 Space >> LuaString 536 Space >> LuaString
537 ) >> 537 ) >>
538 symx(':') >> not_(':') >> 538 symx(':') >> not_(':') >>
539 (Exp | TableBlock | +(SpaceBreak) >> Exp); 539 (Exp | TableBlock | +SpaceBreak >> Exp);
540
541 default_pair = (sym(':') >> Variable >> not_('#') >> Seperator | KeyName >> symx(':') >> Seperator >> Exp) >> sym('=') >> Exp;
540 542
541 meta_variable_pair = sym(':') >> Variable >> expr('#'); 543 meta_variable_pair = sym(':') >> Variable >> expr('#');
542 544
543 meta_normal_pair = Space >> -(Name | symx('[') >> Exp >> sym(']')) >> expr("#:") >> 545 meta_normal_pair = Space >> -(Name | symx('[') >> Exp >> sym(']')) >> expr("#:") >>
544 (Exp | TableBlock | +(SpaceBreak) >> Exp); 546 (Exp | TableBlock | +(SpaceBreak) >> Exp);
545 547
548 meta_default_pair = (sym(':') >> Variable >> expr('#') >> Seperator | -Name >> expr("#:") >> Seperator >> Exp) >> sym('=') >> Exp;
549
546 KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; 550 KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair;
551 KeyValueDef = (variable_pair | normal_pair | meta_variable_pair | meta_normal_pair) >> not_(sym('=')) | default_pair | meta_default_pair;
547 552
548 KeyValueList = KeyValue >> *(sym(',') >> KeyValue); 553 KeyValueList = KeyValue >> *(sym(',') >> KeyValue);
549 KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (Exp | TableBlock)); 554 KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (Exp | TableBlock));
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 2a3c1e4..71519f3 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -148,6 +148,7 @@ private:
148 rule CompClause; 148 rule CompClause;
149 rule Chain; 149 rule Chain;
150 rule KeyValue; 150 rule KeyValue;
151 rule KeyValueDef;
151 rule single_string_inner; 152 rule single_string_inner;
152 rule interp; 153 rule interp;
153 rule double_string_plain; 154 rule double_string_plain;
@@ -289,8 +290,10 @@ private:
289 AST_RULE(Export) 290 AST_RULE(Export)
290 AST_RULE(variable_pair) 291 AST_RULE(variable_pair)
291 AST_RULE(normal_pair) 292 AST_RULE(normal_pair)
293 AST_RULE(default_pair)
292 AST_RULE(meta_variable_pair) 294 AST_RULE(meta_variable_pair)
293 AST_RULE(meta_normal_pair) 295 AST_RULE(meta_normal_pair)
296 AST_RULE(meta_default_pair)
294 AST_RULE(FnArgDef) 297 AST_RULE(FnArgDef)
295 AST_RULE(FnArgDefList) 298 AST_RULE(FnArgDefList)
296 AST_RULE(outer_var_shadow) 299 AST_RULE(outer_var_shadow)