diff options
author | Li Jin <dragon-fly@qq.com> | 2022-07-26 11:34:34 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-07-26 11:34:34 +0800 |
commit | f7150a004e26f446fbf7a47bae368f209248fa67 (patch) | |
tree | 28cbfc756cfef955a6a40f62d3395920938256db | |
parent | 13c7eb4252e8c4228fabf1ade13b7b9bcbd80656 (diff) | |
download | yuescript-f7150a004e26f446fbf7a47bae368f209248fa67.tar.gz yuescript-f7150a004e26f446fbf7a47bae368f209248fa67.tar.bz2 yuescript-f7150a004e26f446fbf7a47bae368f209248fa67.zip |
make destructuring work on function multiple returned values, fix `a, b[] = 1` crashing issue, no longer support implicit declaring variable to be nil.
-rw-r--r-- | spec/inputs/destructure.yue | 8 | ||||
-rw-r--r-- | spec/inputs/local.yue | 2 | ||||
-rw-r--r-- | spec/inputs/syntax.yue | 2 | ||||
-rw-r--r-- | spec/outputs/destructure.lua | 21 | ||||
-rw-r--r-- | spec/outputs/local.lua | 2 | ||||
-rw-r--r-- | spec/outputs/syntax.lua | 2 | ||||
-rw-r--r-- | src/yue.cpp | 8 | ||||
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 191 |
8 files changed, 172 insertions, 64 deletions
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 24282c0..53f9ea3 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
@@ -12,7 +12,7 @@ do | |||
12 | {:a,:b,:c,:d} = yeah | 12 | {:a,:b,:c,:d} = yeah |
13 | 13 | ||
14 | {a}, b = one, two | 14 | {a}, b = one, two |
15 | {b}, c = one | 15 | {b}, c = one, nil |
16 | {d}, e = one, two | 16 | {d}, e = one, two |
17 | 17 | ||
18 | x, {y} = one, two | 18 | x, {y} = one, two |
@@ -22,7 +22,7 @@ do | |||
22 | 22 | ||
23 | {a, :b, c, :d, e, :f, g} = tbl | 23 | {a, :b, c, :d, e, :f, g} = tbl |
24 | 24 | ||
25 | do :a, :b, c = tbl | 25 | do :a, :b, c = tbl, nil |
26 | 26 | ||
27 | do a, :b, :c = tbl, _ | 27 | do a, :b, :c = tbl, _ |
28 | 28 | ||
@@ -187,3 +187,7 @@ do | |||
187 | do | 187 | do |
188 | const :width, :height = View.size | 188 | const :width, :height = View.size |
189 | const {:x = 0.0, :y = 0.0} = point | 189 | const {:x = 0.0, :y = 0.0} = point |
190 | |||
191 | do | ||
192 | x1, x2, x3, a[], d, {b}, e, c.# = 1, 2, 3, f! | ||
193 | y1, :y2, :y3, y4 = f1!, f2! | ||
diff --git a/spec/inputs/local.yue b/spec/inputs/local.yue index 8e04742..a801fb7 100644 --- a/spec/inputs/local.yue +++ b/spec/inputs/local.yue | |||
@@ -3,7 +3,7 @@ do | |||
3 | local a | 3 | local a |
4 | local a,b,c | 4 | local a,b,c |
5 | 5 | ||
6 | b,g = 23232 | 6 | b,g = 23232,nil |
7 | 7 | ||
8 | 8 | ||
9 | do | 9 | do |
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index d18bd0e..e274f1a 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | a = 1 + 2* 3 / 6 | 3 | a = 1 + 2* 3 / 6 |
4 | 4 | ||
5 | a, bunch, go, here = another, world | 5 | a, bunch, go, here = another, world, nil, nil |
6 | 6 | ||
7 | func arg1, arg2, another, arg3 | 7 | func arg1, arg2, another, arg3 |
8 | 8 | ||
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 59ee358..dfac42c 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua | |||
@@ -407,3 +407,24 @@ do | |||
407 | end | 407 | end |
408 | end | 408 | end |
409 | end | 409 | end |
410 | do | ||
411 | local x1, x2, x3, d, e | ||
412 | local b | ||
413 | do | ||
414 | local _obj_0, _obj_1, _obj_2, _obj_3, _obj_4 = f() | ||
415 | do | ||
416 | local _obj_5 = a | ||
417 | _obj_5[#_obj_5 + 1] = _obj_0 | ||
418 | end | ||
419 | setmetatable(c, _obj_4) | ||
420 | x1, x2, x3, d, e = 1, 2, 3, _obj_1, _obj_3 | ||
421 | b = _obj_2[1] | ||
422 | end | ||
423 | local y1, y4 | ||
424 | local y2, y3 | ||
425 | do | ||
426 | local _obj_0, _obj_1 = f2() | ||
427 | y1, y4 = f1(), _obj_1 | ||
428 | y2, y3 = _obj_0.y2, _obj_0.y3 | ||
429 | end | ||
430 | end | ||
diff --git a/spec/outputs/local.lua b/spec/outputs/local.lua index 524d9ef..5004e75 100644 --- a/spec/outputs/local.lua +++ b/spec/outputs/local.lua | |||
@@ -2,7 +2,7 @@ do | |||
2 | local a | 2 | local a |
3 | local a, b, c | 3 | local a, b, c |
4 | local g | 4 | local g |
5 | b, g = 23232 | 5 | b, g = 23232, nil |
6 | end | 6 | end |
7 | do | 7 | do |
8 | local x = 1212 | 8 | local x = 1212 |
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index a4cb8e2..22b6b80 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua | |||
@@ -1,6 +1,6 @@ | |||
1 | local a = 1 + 2 * 3 / 6 | 1 | local a = 1 + 2 * 3 / 6 |
2 | local bunch, go, here | 2 | local bunch, go, here |
3 | a, bunch, go, here = another, world | 3 | a, bunch, go, here = another, world, nil, nil |
4 | func(arg1, arg2, another, arg3) | 4 | func(arg1, arg2, another, arg3) |
5 | local we | 5 | local we |
6 | here, we = function() end, yeah | 6 | here, we = function() end, yeah |
diff --git a/src/yue.cpp b/src/yue.cpp index cb27db8..6011d94 100644 --- a/src/yue.cpp +++ b/src/yue.cpp | |||
@@ -446,7 +446,7 @@ int main(int narg, const char** args) { | |||
446 | return 0; | 446 | return 0; |
447 | } | 447 | } |
448 | if (!resultFile.empty() && files.size() > 1) { | 448 | if (!resultFile.empty() && files.size() > 1) { |
449 | std::cout << "Error: -o can not be used with multiple input files.\n"sv; | 449 | std::cout << "Error: -o can not be used with multiple input files\n"sv; |
450 | std::cout << help; | 450 | std::cout << help; |
451 | } | 451 | } |
452 | std::list<std::future<std::tuple<int,std::string,std::string>>> results; | 452 | std::list<std::future<std::tuple<int,std::string,std::string>>> results; |
@@ -485,7 +485,7 @@ int main(int narg, const char** args) { | |||
485 | return std::tuple{0, file.first, buf.str()}; | 485 | return std::tuple{0, file.first, buf.str()}; |
486 | } else { | 486 | } else { |
487 | std::ostringstream buf; | 487 | std::ostringstream buf; |
488 | buf << "Failed to compile: "sv << file.first << ".\n"sv; | 488 | buf << "Failed to compile: "sv << file.first << '\n'; |
489 | buf << result.error << '\n'; | 489 | buf << result.error << '\n'; |
490 | return std::tuple{1, file.first, buf.str()}; | 490 | return std::tuple{1, file.first, buf.str()}; |
491 | } | 491 | } |
@@ -543,12 +543,12 @@ int main(int narg, const char** args) { | |||
543 | } | 543 | } |
544 | } else { | 544 | } else { |
545 | std::ostringstream buf; | 545 | std::ostringstream buf; |
546 | buf << "Failed to compile: "sv << file.first << ".\n"; | 546 | buf << "Failed to compile: "sv << file.first << '\n'; |
547 | buf << result.error << '\n'; | 547 | buf << result.error << '\n'; |
548 | return std::tuple{1, std::string(), buf.str()}; | 548 | return std::tuple{1, std::string(), buf.str()}; |
549 | } | 549 | } |
550 | } else { | 550 | } else { |
551 | return std::tuple{1, std::string(), "Failed to read file: "s + file.first + ".\n"}; | 551 | return std::tuple{1, std::string(), "Failed to read file: "s + file.first + '\n'}; |
552 | } | 552 | } |
553 | }); | 553 | }); |
554 | results.push_back(std::move(task)); | 554 | results.push_back(std::move(task)); |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index c10c6fd..2a703d0 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -54,7 +54,7 @@ namespace yue { | |||
54 | 54 | ||
55 | typedef std::list<std::string> str_list; | 55 | typedef std::list<std::string> str_list; |
56 | 56 | ||
57 | const std::string_view version = "0.14.0"sv; | 57 | const std::string_view version = "0.14.1"sv; |
58 | const std::string_view extension = "yue"sv; | 58 | const std::string_view extension = "yue"sv; |
59 | 59 | ||
60 | class YueCompilerImpl { | 60 | class YueCompilerImpl { |
@@ -979,8 +979,8 @@ private: | |||
979 | auto x = statement; | 979 | auto x = statement; |
980 | if (statement->appendix) { | 980 | if (statement->appendix) { |
981 | if (auto assignment = assignmentFrom(statement)) { | 981 | if (auto assignment = assignmentFrom(statement)) { |
982 | auto preDefine = getPredefine(assignment); | 982 | auto preDefine = getPreDefineLine(assignment); |
983 | if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); | 983 | if (!preDefine.empty()) out.push_back(preDefine); |
984 | } else if (auto local = statement->content.as<Local_t>()) { | 984 | } else if (auto local = statement->content.as<Local_t>()) { |
985 | if (!local->defined) { | 985 | if (!local->defined) { |
986 | local->defined = true; | 986 | local->defined = true; |
@@ -1257,13 +1257,16 @@ private: | |||
1257 | return defs; | 1257 | return defs; |
1258 | } | 1258 | } |
1259 | 1259 | ||
1260 | std::string getPredefine(const str_list& defs) { | 1260 | std::string toLocalDecl(const str_list& defs) { |
1261 | if (defs.empty()) return Empty; | 1261 | if (defs.empty()) return Empty; |
1262 | return indent() + "local "s + join(defs, ", "sv); | 1262 | return indent() + "local "s + join(defs, ", "sv); |
1263 | } | 1263 | } |
1264 | 1264 | ||
1265 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 1265 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
1266 | auto info = extractDestructureInfo(assignment, true, false); | 1266 | auto info = extractDestructureInfo(assignment, true, false); |
1267 | if (info.assignment) { | ||
1268 | _buf << getPreDefineLine(info.assignment); | ||
1269 | } | ||
1267 | if (!info.destructures.empty()) { | 1270 | if (!info.destructures.empty()) { |
1268 | for (const auto& destruct : info.destructures) { | 1271 | for (const auto& destruct : info.destructures) { |
1269 | str_list defs; | 1272 | str_list defs; |
@@ -1280,14 +1283,20 @@ private: | |||
1280 | return clearBuf(); | 1283 | return clearBuf(); |
1281 | } | 1284 | } |
1282 | 1285 | ||
1283 | std::string getPredefine(ExpListAssign_t* assignment) { | 1286 | std::string getPreDefine(ExpListAssign_t* assignment) { |
1284 | auto preDefine = getDestrucureDefine(assignment); | 1287 | auto preDefine = getDestrucureDefine(assignment); |
1285 | if (preDefine.empty()) { | 1288 | if (preDefine.empty()) { |
1286 | preDefine = getPredefine(transformAssignDefs(assignment->expList, DefOp::Mark)); | 1289 | preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); |
1287 | } | 1290 | } |
1288 | return preDefine; | 1291 | return preDefine; |
1289 | } | 1292 | } |
1290 | 1293 | ||
1294 | std::string getPreDefineLine(ExpListAssign_t* assignment) { | ||
1295 | auto preDefine = getPreDefine(assignment); | ||
1296 | if (!preDefine.empty()) preDefine += nll(assignment); | ||
1297 | return preDefine; | ||
1298 | } | ||
1299 | |||
1291 | ExpList_t* expListFrom(Statement_t* statement) { | 1300 | ExpList_t* expListFrom(Statement_t* statement) { |
1292 | if (auto expListAssign = statement->content.as<ExpListAssign_t>()) { | 1301 | if (auto expListAssign = statement->content.as<ExpListAssign_t>()) { |
1293 | if (!expListAssign->action) { | 1302 | if (!expListAssign->action) { |
@@ -1334,18 +1343,93 @@ private: | |||
1334 | BLOCK_START | 1343 | BLOCK_START |
1335 | auto assign = ast_cast<Assign_t>(assignment->action); | 1344 | auto assign = ast_cast<Assign_t>(assignment->action); |
1336 | BREAK_IF(!assign); | 1345 | BREAK_IF(!assign); |
1337 | if (assignment->expList->exprs.size() < assign->values.size()) { | 1346 | auto x = assignment; |
1338 | auto num = assignment->expList->exprs.size(); | 1347 | const auto& exprs = x->expList->exprs.objects(); |
1348 | const auto& values = assign->values.objects(); | ||
1349 | if (exprs.size() < values.size()) { | ||
1350 | auto num = exprs.size(); | ||
1339 | if (num > 1) { | 1351 | if (num > 1) { |
1340 | _buf << "no more than "sv << num << " right values expected, got "sv << assign->values.size(); | 1352 | _buf << "no more than "sv << num << " right values expected, got "sv << values.size(); |
1341 | } else { | 1353 | } else { |
1342 | _buf << "only one right value expected, got "sv << assign->values.size(); | 1354 | _buf << "only one right value expected, got "sv << values.size(); |
1343 | } | 1355 | } |
1344 | throw std::logic_error(_info.errorMessage(clearBuf(), assign->values.front())); | 1356 | throw std::logic_error(_info.errorMessage(clearBuf(), values.front())); |
1357 | } | ||
1358 | if (exprs.size() > values.size()) { | ||
1359 | BLOCK_START | ||
1360 | auto value = singleValueFrom(values.back()); | ||
1361 | BREAK_IF(!value); | ||
1362 | auto chainValue = value->item.as<ChainValue_t>(); | ||
1363 | BREAK_IF(!chainValue); | ||
1364 | if (!ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) { | ||
1365 | _buf << exprs.size() << " right values expected, got "sv << values.size(); | ||
1366 | throw std::logic_error(_info.errorMessage(clearBuf(), values.front())); | ||
1367 | } | ||
1368 | auto newAssign = assign->new_ptr<Assign_t>(); | ||
1369 | newAssign->values.dup(assign->values); | ||
1370 | auto i = exprs.begin(); | ||
1371 | auto j = values.begin(); | ||
1372 | auto je = --values.end(); | ||
1373 | while (j != je) { | ||
1374 | ++i; ++j; | ||
1375 | } | ||
1376 | bool holdItem = false; | ||
1377 | for (auto it = i; it != exprs.end(); ++it) { | ||
1378 | BLOCK_START | ||
1379 | auto value = singleValueFrom(*it); | ||
1380 | BREAK_IF(!value); | ||
1381 | if (value->item.is<simple_table_t>() || | ||
1382 | value->getByPath<SimpleValue_t, TableLit_t>()) { | ||
1383 | holdItem = true; | ||
1384 | break; | ||
1385 | } | ||
1386 | auto chainValue = value->item.as<ChainValue_t>(); | ||
1387 | BREAK_IF(!chainValue); | ||
1388 | str_list temp; | ||
1389 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { | ||
1390 | BREAK_IF(!dot->name.is<Metatable_t>()); | ||
1391 | holdItem = true; | ||
1392 | } else if (ast_is<table_appending_op_t>(chainValue->items.back())) { | ||
1393 | holdItem = true; | ||
1394 | } | ||
1395 | BLOCK_END | ||
1396 | if (holdItem) { | ||
1397 | break; | ||
1398 | } | ||
1399 | } | ||
1400 | BREAK_IF(!holdItem); | ||
1401 | pushScope(); | ||
1402 | std::list<ast_ptr<false, Exp_t>> extraExprs; | ||
1403 | for (; i != exprs.end(); ++i) { | ||
1404 | auto var = getUnusedName("_obj_"sv); | ||
1405 | addToScope(var); | ||
1406 | extraExprs.push_back(toAst<Exp_t>(var, *i)); | ||
1407 | } | ||
1408 | popScope(); | ||
1409 | ast_ptr<true, ast_node> funcCall = values.back(); | ||
1410 | assign->values.pop_back(); | ||
1411 | auto preAssignment = funcCall->new_ptr<ExpListAssign_t>(); | ||
1412 | auto preAssign = funcCall->new_ptr<Assign_t>(); | ||
1413 | preAssign->values.push_back(funcCall); | ||
1414 | preAssignment->action.set(preAssign); | ||
1415 | auto preExplist = funcCall->new_ptr<ExpList_t>(); | ||
1416 | for (const auto& item : extraExprs) { | ||
1417 | preExplist->exprs.push_back(item.get()); | ||
1418 | assign->values.push_back(item.get()); | ||
1419 | } | ||
1420 | preAssignment->expList.set(preExplist); | ||
1421 | str_list temp; | ||
1422 | temp.push_back(getPreDefineLine(assignment)); | ||
1423 | temp.push_back(indent() + "do"s + nll(assignment)); | ||
1424 | pushScope(); | ||
1425 | transformAssignmentCommon(preAssignment, temp); | ||
1426 | transformAssignment(assignment, temp); | ||
1427 | popScope(); | ||
1428 | temp.push_back(indent() + "end"s + nll(assignment)); | ||
1429 | out.push_back(join(temp)); | ||
1430 | return; | ||
1431 | BLOCK_END | ||
1345 | } | 1432 | } |
1346 | auto x = assignment; | ||
1347 | const auto& exprs = assignment->expList->exprs.objects(); | ||
1348 | const auto& values = assign->values.objects(); | ||
1349 | auto vit = values.begin(); | 1433 | auto vit = values.begin(); |
1350 | for (auto it = exprs.begin(); it != exprs.end(); ++it) { | 1434 | for (auto it = exprs.begin(); it != exprs.end(); ++it) { |
1351 | BLOCK_START | 1435 | BLOCK_START |
@@ -1398,7 +1482,11 @@ private: | |||
1398 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 1482 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
1399 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | 1483 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); |
1400 | auto assign = x->new_ptr<Assign_t>(); | 1484 | auto assign = x->new_ptr<Assign_t>(); |
1401 | assign->values.push_back(*vit); | 1485 | if (vit != values.end()) { |
1486 | assign->values.push_back(*vit); | ||
1487 | } else { | ||
1488 | assign->values.push_back(toAst<Exp_t>("nil"sv, *vit)); | ||
1489 | } | ||
1402 | newAssignment->action.set(assign); | 1490 | newAssignment->action.set(assign); |
1403 | transformAssignment(newAssignment, temp); | 1491 | transformAssignment(newAssignment, temp); |
1404 | if (isScoped) { | 1492 | if (isScoped) { |
@@ -1445,7 +1533,7 @@ private: | |||
1445 | auto expList = assignment->expList.get(); | 1533 | auto expList = assignment->expList.get(); |
1446 | str_list temp; | 1534 | str_list temp; |
1447 | auto defs = transformAssignDefs(expList, DefOp::Mark); | 1535 | auto defs = transformAssignDefs(expList, DefOp::Mark); |
1448 | if (!defs.empty()) temp.push_back(getPredefine(defs) + nll(expList)); | 1536 | if (!defs.empty()) temp.push_back(toLocalDecl(defs) + nll(expList)); |
1449 | transformIf(static_cast<If_t*>(value), temp, ExpUsage::Assignment, expList); | 1537 | transformIf(static_cast<If_t*>(value), temp, ExpUsage::Assignment, expList); |
1450 | out.push_back(join(temp)); | 1538 | out.push_back(join(temp)); |
1451 | return; | 1539 | return; |
@@ -1453,76 +1541,76 @@ private: | |||
1453 | case id<Switch_t>(): { | 1541 | case id<Switch_t>(): { |
1454 | auto switchNode = static_cast<Switch_t*>(value); | 1542 | auto switchNode = static_cast<Switch_t*>(value); |
1455 | auto assignList = assignment->expList.get(); | 1543 | auto assignList = assignment->expList.get(); |
1456 | std::string preDefine = getPredefine(assignment); | 1544 | std::string preDefine = getPreDefineLine(assignment); |
1457 | transformSwitch(switchNode, out, ExpUsage::Assignment, assignList); | 1545 | transformSwitch(switchNode, out, ExpUsage::Assignment, assignList); |
1458 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1546 | out.back().insert(0, preDefine); |
1459 | return; | 1547 | return; |
1460 | } | 1548 | } |
1461 | case id<With_t>(): { | 1549 | case id<With_t>(): { |
1462 | auto withNode = static_cast<With_t*>(value); | 1550 | auto withNode = static_cast<With_t*>(value); |
1463 | auto expList = assignment->expList.get(); | 1551 | auto expList = assignment->expList.get(); |
1464 | std::string preDefine = getPredefine(assignment); | 1552 | std::string preDefine = getPreDefineLine(assignment); |
1465 | transformWith(withNode, out, expList); | 1553 | transformWith(withNode, out, expList); |
1466 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1554 | out.back().insert(0, preDefine); |
1467 | return; | 1555 | return; |
1468 | } | 1556 | } |
1469 | case id<Do_t>(): { | 1557 | case id<Do_t>(): { |
1470 | auto expList = assignment->expList.get(); | 1558 | auto expList = assignment->expList.get(); |
1471 | auto doNode = static_cast<Do_t*>(value); | 1559 | auto doNode = static_cast<Do_t*>(value); |
1472 | std::string preDefine = getPredefine(assignment); | 1560 | std::string preDefine = getPreDefineLine(assignment); |
1473 | transformDo(doNode, out, ExpUsage::Assignment, expList); | 1561 | transformDo(doNode, out, ExpUsage::Assignment, expList); |
1474 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1562 | out.back().insert(0, preDefine); |
1475 | return; | 1563 | return; |
1476 | } | 1564 | } |
1477 | case id<Comprehension_t>(): { | 1565 | case id<Comprehension_t>(): { |
1478 | auto expList = assignment->expList.get(); | 1566 | auto expList = assignment->expList.get(); |
1479 | std::string preDefine = getPredefine(assignment); | 1567 | std::string preDefine = getPreDefineLine(assignment); |
1480 | transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Assignment, expList); | 1568 | transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Assignment, expList); |
1481 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1569 | out.back().insert(0, preDefine); |
1482 | return; | 1570 | return; |
1483 | } | 1571 | } |
1484 | case id<TblComprehension_t>(): { | 1572 | case id<TblComprehension_t>(): { |
1485 | auto expList = assignment->expList.get(); | 1573 | auto expList = assignment->expList.get(); |
1486 | std::string preDefine = getPredefine(assignment); | 1574 | std::string preDefine = getPreDefineLine(assignment); |
1487 | transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Assignment, expList); | 1575 | transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Assignment, expList); |
1488 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1576 | out.back().insert(0, preDefine); |
1489 | return; | 1577 | return; |
1490 | } | 1578 | } |
1491 | case id<For_t>(): { | 1579 | case id<For_t>(): { |
1492 | auto expList = assignment->expList.get(); | 1580 | auto expList = assignment->expList.get(); |
1493 | std::string preDefine = getPredefine(assignment); | 1581 | std::string preDefine = getPreDefineLine(assignment); |
1494 | transformForInPlace(static_cast<For_t*>(value), out, expList); | 1582 | transformForInPlace(static_cast<For_t*>(value), out, expList); |
1495 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1583 | out.back().insert(0, preDefine); |
1496 | return; | 1584 | return; |
1497 | } | 1585 | } |
1498 | case id<ForEach_t>(): { | 1586 | case id<ForEach_t>(): { |
1499 | auto expList = assignment->expList.get(); | 1587 | auto expList = assignment->expList.get(); |
1500 | std::string preDefine = getPredefine(assignment); | 1588 | std::string preDefine = getPreDefineLine(assignment); |
1501 | transformForEachInPlace(static_cast<ForEach_t*>(value), out, expList); | 1589 | transformForEachInPlace(static_cast<ForEach_t*>(value), out, expList); |
1502 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1590 | out.back().insert(0, preDefine); |
1503 | return; | 1591 | return; |
1504 | } | 1592 | } |
1505 | case id<ClassDecl_t>(): { | 1593 | case id<ClassDecl_t>(): { |
1506 | auto expList = assignment->expList.get(); | 1594 | auto expList = assignment->expList.get(); |
1507 | std::string preDefine = getPredefine(assignment); | 1595 | std::string preDefine = getPreDefineLine(assignment); |
1508 | transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Assignment, expList); | 1596 | transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Assignment, expList); |
1509 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1597 | out.back().insert(0, preDefine); |
1510 | return; | 1598 | return; |
1511 | } | 1599 | } |
1512 | case id<While_t>(): { | 1600 | case id<While_t>(): { |
1513 | auto expList = assignment->expList.get(); | 1601 | auto expList = assignment->expList.get(); |
1514 | std::string preDefine = getPredefine(assignment); | 1602 | std::string preDefine = getPreDefineLine(assignment); |
1515 | transformWhileInPlace(static_cast<While_t*>(value), out, expList); | 1603 | transformWhileInPlace(static_cast<While_t*>(value), out, expList); |
1516 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1604 | out.back().insert(0, preDefine); |
1517 | return; | 1605 | return; |
1518 | } | 1606 | } |
1519 | case id<TableLit_t>(): { | 1607 | case id<TableLit_t>(): { |
1520 | auto tableLit = static_cast<TableLit_t*>(value); | 1608 | auto tableLit = static_cast<TableLit_t*>(value); |
1521 | if (hasSpreadExp(tableLit->values.objects())) { | 1609 | if (hasSpreadExp(tableLit->values.objects())) { |
1522 | auto expList = assignment->expList.get(); | 1610 | auto expList = assignment->expList.get(); |
1523 | std::string preDefine = getPredefine(assignment); | 1611 | std::string preDefine = getPreDefineLine(assignment); |
1524 | transformSpreadTable(tableLit->values.objects(), out, ExpUsage::Assignment, expList); | 1612 | transformSpreadTable(tableLit->values.objects(), out, ExpUsage::Assignment, expList); |
1525 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1613 | out.back().insert(0, preDefine); |
1526 | return; | 1614 | return; |
1527 | } | 1615 | } |
1528 | } | 1616 | } |
@@ -1530,9 +1618,9 @@ private: | |||
1530 | auto tableBlock = static_cast<TableBlock_t*>(value); | 1618 | auto tableBlock = static_cast<TableBlock_t*>(value); |
1531 | if (hasSpreadExp(tableBlock->values.objects())) { | 1619 | if (hasSpreadExp(tableBlock->values.objects())) { |
1532 | auto expList = assignment->expList.get(); | 1620 | auto expList = assignment->expList.get(); |
1533 | std::string preDefine = getPredefine(assignment); | 1621 | std::string preDefine = getPreDefineLine(assignment); |
1534 | transformSpreadTable(tableBlock->values.objects(), out, ExpUsage::Assignment, expList); | 1622 | transformSpreadTable(tableBlock->values.objects(), out, ExpUsage::Assignment, expList); |
1535 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1623 | out.back().insert(0, preDefine); |
1536 | return; | 1624 | return; |
1537 | } | 1625 | } |
1538 | } | 1626 | } |
@@ -1556,9 +1644,9 @@ private: | |||
1556 | switch (type) { | 1644 | switch (type) { |
1557 | case ChainType::HasEOP: | 1645 | case ChainType::HasEOP: |
1558 | case ChainType::EndWithColon: { | 1646 | case ChainType::EndWithColon: { |
1559 | std::string preDefine = getPredefine(assignment); | 1647 | std::string preDefine = getPreDefineLine(assignment); |
1560 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList); | 1648 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList); |
1561 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1649 | out.back().insert(0, preDefine); |
1562 | return; | 1650 | return; |
1563 | } | 1651 | } |
1564 | case ChainType::HasKeyword: | 1652 | case ChainType::HasKeyword: |
@@ -2090,8 +2178,6 @@ private: | |||
2090 | break; | 2178 | break; |
2091 | } | 2179 | } |
2092 | } | 2180 | } |
2093 | } else { | ||
2094 | throw std::logic_error(_info.errorMessage("an explicit destructure target required"sv, destructNode)); | ||
2095 | } | 2181 | } |
2096 | destructPairs.push_back({i, j}); | 2182 | destructPairs.push_back({i, j}); |
2097 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); | 2183 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); |
@@ -2318,17 +2404,17 @@ private: | |||
2318 | chain->items.dup(tmpChain->items); | 2404 | chain->items.dup(tmpChain->items); |
2319 | auto op = _parser.toString(update->op); | 2405 | auto op = _parser.toString(update->op); |
2320 | if (op == "??"sv) { | 2406 | if (op == "??"sv) { |
2321 | auto defs = getPredefine(assignment); | 2407 | auto defs = getPreDefineLine(assignment); |
2408 | temp.push_back(defs); | ||
2322 | auto rightExp = x->new_ptr<Exp_t>(); | 2409 | auto rightExp = x->new_ptr<Exp_t>(); |
2323 | rightExp->pipeExprs.dup(leftExp->pipeExprs); | 2410 | rightExp->pipeExprs.dup(leftExp->pipeExprs); |
2324 | rightExp->opValues.dup(leftExp->opValues); | 2411 | rightExp->opValues.dup(leftExp->opValues); |
2325 | rightExp->nilCoalesed.set(update->value); | 2412 | rightExp->nilCoalesed.set(update->value); |
2326 | transformNilCoalesedExp(rightExp, temp, ExpUsage::Assignment, assignment->expList, true); | 2413 | transformNilCoalesedExp(rightExp, temp, ExpUsage::Assignment, assignment->expList, true); |
2327 | if (!defs.empty()) temp.back().insert(0, defs + nll(x)); | ||
2328 | out.push_back(join(temp)); | 2414 | out.push_back(join(temp)); |
2329 | return; | 2415 | return; |
2330 | } | 2416 | } |
2331 | auto defs = getPredefine(assignment); | 2417 | auto defs = getPreDefine(assignment); |
2332 | transformValue(leftValue, temp); | 2418 | transformValue(leftValue, temp); |
2333 | auto left = std::move(temp.back()); | 2419 | auto left = std::move(temp.back()); |
2334 | temp.pop_back(); | 2420 | temp.pop_back(); |
@@ -2364,7 +2450,7 @@ private: | |||
2364 | for (auto value : assign->values.objects()) { | 2450 | for (auto value : assign->values.objects()) { |
2365 | transformAssignItem(value, temp); | 2451 | transformAssignItem(value, temp); |
2366 | } | 2452 | } |
2367 | std::string preDefine = getPredefine(defs); | 2453 | std::string preDefine = toLocalDecl(defs); |
2368 | for (const auto& def : defs) { | 2454 | for (const auto& def : defs) { |
2369 | addToScope(def); | 2455 | addToScope(def); |
2370 | } | 2456 | } |
@@ -2377,7 +2463,7 @@ private: | |||
2377 | out.push_back(preDefine + " = "s + join(temp, ", "sv) + nll(assignment)); | 2463 | out.push_back(preDefine + " = "s + join(temp, ", "sv) + nll(assignment)); |
2378 | } | 2464 | } |
2379 | } else { | 2465 | } else { |
2380 | std::string preDefine = getPredefine(defs); | 2466 | std::string preDefine = toLocalDecl(defs); |
2381 | for (const auto& def : defs) { | 2467 | for (const auto& def : defs) { |
2382 | addToScope(def); | 2468 | addToScope(def); |
2383 | } | 2469 | } |
@@ -2779,9 +2865,7 @@ private: | |||
2779 | bool extraScope = false; | 2865 | bool extraScope = false; |
2780 | if (!nilBranchOnly) { | 2866 | if (!nilBranchOnly) { |
2781 | assign->values.push_back(exp); | 2867 | assign->values.push_back(exp); |
2782 | std::string& predefine = temp.emplace_back(); | 2868 | temp.push_back(getPreDefineLine(assignment)); |
2783 | auto defs = getPredefine(assignment); | ||
2784 | if (!defs.empty()) predefine = defs + nll(x); | ||
2785 | extraScope = prepareValue(true); | 2869 | extraScope = prepareValue(true); |
2786 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | 2870 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); |
2787 | temp.push_back(clearBuf()); | 2871 | temp.push_back(clearBuf()); |
@@ -2796,8 +2880,7 @@ private: | |||
2796 | } else { | 2880 | } else { |
2797 | assign->values.clear(); | 2881 | assign->values.clear(); |
2798 | assign->values.push_back(exp->nilCoalesed); | 2882 | assign->values.push_back(exp->nilCoalesed); |
2799 | auto defs = getPredefine(assignment); | 2883 | temp.push_back(getPreDefineLine(assignment)); |
2800 | if (!defs.empty()) temp.push_back(defs + nll(x)); | ||
2801 | transformExp(left, temp, ExpUsage::Closure); | 2884 | transformExp(left, temp, ExpUsage::Closure); |
2802 | _buf << indent() << "if "sv << temp.back() << " == nil then"sv << nll(x); | 2885 | _buf << indent() << "if "sv << temp.back() << " == nil then"sv << nll(x); |
2803 | temp.pop_back(); | 2886 | temp.pop_back(); |
@@ -6891,7 +6974,7 @@ private: | |||
6891 | } | 6974 | } |
6892 | } | 6975 | } |
6893 | if (objAssign) { | 6976 | if (objAssign) { |
6894 | auto preDef = getPredefine(transformAssignDefs(expList, DefOp::Mark)); | 6977 | auto preDef = toLocalDecl(transformAssignDefs(expList, DefOp::Mark)); |
6895 | if (!preDef.empty()) { | 6978 | if (!preDef.empty()) { |
6896 | temp.push_back(preDef + nll(import)); | 6979 | temp.push_back(preDef + nll(import)); |
6897 | } | 6980 | } |
@@ -7350,7 +7433,7 @@ private: | |||
7350 | defs.push_back(decl); | 7433 | defs.push_back(decl); |
7351 | } | 7434 | } |
7352 | } | 7435 | } |
7353 | auto preDefine = getPredefine(defs); | 7436 | auto preDefine = toLocalDecl(defs); |
7354 | if (!preDefine.empty()) { | 7437 | if (!preDefine.empty()) { |
7355 | out.push_back(preDefine + nll(local)); | 7438 | out.push_back(preDefine + nll(local)); |
7356 | } | 7439 | } |