aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-07-26 11:34:34 +0800
committerLi Jin <dragon-fly@qq.com>2022-07-26 11:34:34 +0800
commitf7150a004e26f446fbf7a47bae368f209248fa67 (patch)
tree28cbfc756cfef955a6a40f62d3395920938256db
parent13c7eb4252e8c4228fabf1ade13b7b9bcbd80656 (diff)
downloadyuescript-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.yue8
-rw-r--r--spec/inputs/local.yue2
-rw-r--r--spec/inputs/syntax.yue2
-rw-r--r--spec/outputs/destructure.lua21
-rw-r--r--spec/outputs/local.lua2
-rw-r--r--spec/outputs/syntax.lua2
-rw-r--r--src/yue.cpp8
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp191
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
187do 187do
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
191do
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
9do 9do
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
3a = 1 + 2* 3 / 6 3a = 1 + 2* 3 / 6
4 4
5a, bunch, go, here = another, world 5a, bunch, go, here = another, world, nil, nil
6 6
7func arg1, arg2, another, arg3 7func 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
409end 409end
410do
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
430end
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
6end 6end
7do 7do
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 @@
1local a = 1 + 2 * 3 / 6 1local a = 1 + 2 * 3 / 6
2local bunch, go, here 2local bunch, go, here
3a, bunch, go, here = another, world 3a, bunch, go, here = another, world, nil, nil
4func(arg1, arg2, another, arg3) 4func(arg1, arg2, another, arg3)
5local we 5local we
6here, we = function() end, yeah 6here, 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
55typedef std::list<std::string> str_list; 55typedef std::list<std::string> str_list;
56 56
57const std::string_view version = "0.14.0"sv; 57const std::string_view version = "0.14.1"sv;
58const std::string_view extension = "yue"sv; 58const std::string_view extension = "yue"sv;
59 59
60class YueCompilerImpl { 60class 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 }