diff options
author | Li Jin <dragon-fly@qq.com> | 2021-08-17 16:21:39 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2021-08-17 16:21:39 +0800 |
commit | 792e942f5269655ee03c48400999f3604b84396c (patch) | |
tree | cc3d6fe477f08ffed985e297ee789d2213387a44 | |
parent | 7295e9efe092fca4ab6eebf6408af93d5f56dd80 (diff) | |
download | yuescript-792e942f5269655ee03c48400999f3604b84396c.tar.gz yuescript-792e942f5269655ee03c48400999f3604b84396c.tar.bz2 yuescript-792e942f5269655ee03c48400999f3604b84396c.zip |
fix issue #64.
-rw-r--r-- | spec/inputs/destructure.yue | 29 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 30 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 278 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 9 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 3 |
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 | ||
145 | do | ||
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 | |||
169 | do | ||
170 | {#: mt = {}, sub#: subFunc} = tb.x | ||
171 | |||
172 | do | ||
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) |
427 | AST_END(normal_pair) | 427 | AST_END(normal_pair) |
428 | 428 | ||
429 | AST_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) | ||
435 | AST_END(default_pair) | ||
436 | |||
429 | AST_NODE(meta_variable_pair) | 437 | AST_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) |
438 | AST_END(meta_normal_pair) | 446 | AST_END(meta_normal_pair) |
439 | 447 | ||
448 | AST_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) | ||
454 | AST_END(meta_default_pair) | ||
455 | |||
440 | AST_NODE(simple_table) | 456 | AST_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) | |||
562 | AST_LEAF(default_value) | 578 | AST_LEAF(default_value) |
563 | AST_END(default_value) | 579 | AST_END(default_value) |
564 | 580 | ||
581 | class default_pair_t; | ||
582 | class meta_default_pair_t; | ||
583 | |||
565 | AST_NODE(TableLit) | 584 | AST_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) |
569 | AST_END(TableLit) | 590 | AST_END(TableLit) |
570 | 591 | ||
571 | AST_NODE(TableBlockIndent) | 592 | AST_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) |
575 | AST_END(TableBlockIndent) | 598 | AST_END(TableBlockIndent) |
576 | 599 | ||
577 | AST_NODE(TableBlock) | 600 | AST_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) |
581 | AST_END(TableBlock) | 605 | AST_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 | ||
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.7.17"sv; | 59 | const std::string_view version = "0.7.18"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 { |
@@ -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) |