aboutsummaryrefslogtreecommitdiff
path: root/src/yuescript/yue_compiler.cpp
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 /src/yuescript/yue_compiler.cpp
parent7295e9efe092fca4ab6eebf6408af93d5f56dd80 (diff)
downloadyuescript-792e942f5269655ee03c48400999f3604b84396c.tar.gz
yuescript-792e942f5269655ee03c48400999f3604b84396c.tar.bz2
yuescript-792e942f5269655ee03c48400999f3604b84396c.zip
fix issue #64.
Diffstat (limited to '')
-rw-r--r--src/yuescript/yue_compiler.cpp278
1 files changed, 253 insertions, 25 deletions
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) {