aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-07-26 18:05:23 +0800
committerLi Jin <dragon-fly@qq.com>2022-07-26 18:05:23 +0800
commit0f5bdeaeba0f04e49c47f4a2be55b14185a7dfdd (patch)
treeb5baa6c385ce58c60615ff0577a1e2b6850f044d /src
parente191defb6545509a4ae0b402f2fac1fbe18551cd (diff)
downloadyuescript-0f5bdeaeba0f04e49c47f4a2be55b14185a7dfdd.tar.gz
yuescript-0f5bdeaeba0f04e49c47f4a2be55b14185a7dfdd.tar.bz2
yuescript-0f5bdeaeba0f04e49c47f4a2be55b14185a7dfdd.zip
fix missing checks and issues related to destrucuring in if branches.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp200
1 files changed, 114 insertions, 86 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 2a703d0..1a44832 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.1"sv; 57const std::string_view version = "0.14.2"sv;
58const std::string_view extension = "yue"sv; 58const std::string_view extension = "yue"sv;
59 59
60class YueCompilerImpl { 60class YueCompilerImpl {
@@ -1355,13 +1355,31 @@ private:
1355 } 1355 }
1356 throw std::logic_error(_info.errorMessage(clearBuf(), values.front())); 1356 throw std::logic_error(_info.errorMessage(clearBuf(), values.front()));
1357 } 1357 }
1358 bool checkValuesLater = false;
1358 if (exprs.size() > values.size()) { 1359 if (exprs.size() > values.size()) {
1359 BLOCK_START 1360 BLOCK_START
1361 switch (values.back()->getId()) {
1362 case id<If_t>():
1363 case id<Switch_t>():
1364 checkValuesLater = true;
1365 break;
1366 }
1367 BREAK_IF(checkValuesLater);
1360 auto value = singleValueFrom(values.back()); 1368 auto value = singleValueFrom(values.back());
1361 BREAK_IF(!value); 1369 BREAK_IF(!value);
1370 if (auto val = value->item.as<SimpleValue_t>()) {
1371 switch (val->value->getId()) {
1372 case id<If_t>():
1373 case id<Switch_t>():
1374 case id<Do_t>():
1375 case id<Try_t>():
1376 checkValuesLater = true;
1377 break;
1378 }
1379 BREAK_IF(checkValuesLater);
1380 }
1362 auto chainValue = value->item.as<ChainValue_t>(); 1381 auto chainValue = value->item.as<ChainValue_t>();
1363 BREAK_IF(!chainValue); 1382 if (!chainValue || !ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) {
1364 if (!ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) {
1365 _buf << exprs.size() << " right values expected, got "sv << values.size(); 1383 _buf << exprs.size() << " right values expected, got "sv << values.size();
1366 throw std::logic_error(_info.errorMessage(clearBuf(), values.front())); 1384 throw std::logic_error(_info.errorMessage(clearBuf(), values.front()));
1367 } 1385 }
@@ -1430,96 +1448,107 @@ private:
1430 return; 1448 return;
1431 BLOCK_END 1449 BLOCK_END
1432 } 1450 }
1433 auto vit = values.begin(); 1451 if (!checkValuesLater) {
1434 for (auto it = exprs.begin(); it != exprs.end(); ++it) { 1452 auto vit = values.begin();
1435 BLOCK_START 1453 for (auto it = exprs.begin(); it != exprs.end(); ++it) {
1436 auto value = singleValueFrom(*it); 1454 BLOCK_START
1437 BREAK_IF(!value); 1455 auto value = singleValueFrom(*it);
1438 auto chainValue = value->item.as<ChainValue_t>(); 1456 BREAK_IF(!value);
1439 BREAK_IF(!chainValue); 1457 auto chainValue = value->item.as<ChainValue_t>();
1440 str_list temp; 1458 BREAK_IF(!chainValue);
1441 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { 1459 str_list temp;
1442 BREAK_IF(!dot->name.is<Metatable_t>()); 1460 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) {
1443 str_list args; 1461 BREAK_IF(!dot->name.is<Metatable_t>());
1444 chainValue->items.pop_back(); 1462 str_list args;
1445 if (chainValue->items.empty()) { 1463 auto tmpChain = chainValue->new_ptr<ChainValue_t>();
1446 if (_withVars.empty()) { 1464 tmpChain->items.dup(chainValue->items);
1447 throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); 1465 tmpChain->items.pop_back();
1466 if (tmpChain->items.empty()) {
1467 if (_withVars.empty()) {
1468 throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x));
1469 } else {
1470 args.push_back(_withVars.top());
1471 }
1448 } else { 1472 } else {
1449 args.push_back(_withVars.top()); 1473 auto value = tmpChain->new_ptr<Value_t>();
1474 value->item.set(tmpChain);
1475 transformExp(newExp(value, tmpChain), args, ExpUsage::Closure);
1450 } 1476 }
1451 } else { 1477 if (vit == values.end()) {
1452 transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure); 1478 throw std::logic_error(_info.errorMessage("right value missing"sv, values.front()));
1453 } 1479 }
1454 if (vit != values.end()) transformAssignItem(*vit, args); 1480 transformAssignItem(*vit, args);
1455 else args.push_back("nil"s); 1481 _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x);
1456 _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); 1482 temp.push_back(clearBuf());
1457 temp.push_back(clearBuf()); 1483 } else if (ast_is<table_appending_op_t>(chainValue->items.back())) {
1458 } else if (ast_is<table_appending_op_t>(chainValue->items.back())) { 1484 auto tmpChain = chainValue->new_ptr<ChainValue_t>();
1459 chainValue->items.pop_back(); 1485 tmpChain->items.dup(chainValue->items);
1460 if (chainValue->items.empty()) { 1486 tmpChain->items.pop_back();
1461 if (_withVars.empty()) { 1487 if (tmpChain->items.empty()) {
1462 throw std::logic_error(_info.errorMessage("short table appending must be called within a with block"sv, x)); 1488 if (_withVars.empty()) {
1463 } else { 1489 throw std::logic_error(_info.errorMessage("short table appending must be called within a with block"sv, x));
1464 chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue)); 1490 } else {
1491 tmpChain->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue));
1492 }
1493 }
1494 auto varName = singleVariableFrom(tmpChain);
1495 bool isScoped = false;
1496 if (varName.empty() || !isLocal(varName)) {
1497 isScoped = true;
1498 temp.push_back(indent() + "do"s + nll(x));
1499 pushScope();
1500 auto objVar = getUnusedName("_obj_"sv);
1501 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1502 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
1503 auto assign = x->new_ptr<Assign_t>();
1504 auto value = tmpChain->new_ptr<Value_t>();
1505 value->item.set(tmpChain);
1506 assign->values.push_back(newExp(value, tmpChain));
1507 newAssignment->action.set(assign);
1508 transformAssignment(newAssignment, temp);
1509 varName = objVar;
1465 } 1510 }
1466 }
1467 auto varName = singleVariableFrom(chainValue);
1468 bool isScoped = false;
1469 if (varName.empty() || !isLocal(varName)) {
1470 isScoped = true;
1471 temp.push_back(indent() + "do"s + nll(x));
1472 pushScope();
1473 auto objVar = getUnusedName("_obj_"sv);
1474 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1511 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1475 newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); 1512 newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x));
1476 auto assign = x->new_ptr<Assign_t>(); 1513 auto assign = x->new_ptr<Assign_t>();
1477 assign->values.push_back(*it); 1514 if (vit == values.end()) {
1515 throw std::logic_error(_info.errorMessage("right value missing"sv, values.front()));
1516 }
1517 assign->values.push_back(*vit);
1478 newAssignment->action.set(assign); 1518 newAssignment->action.set(assign);
1479 transformAssignment(newAssignment, temp); 1519 transformAssignment(newAssignment, temp);
1480 varName = objVar; 1520 if (isScoped) {
1481 } 1521 popScope();
1522 temp.push_back(indent() + "end"s + nlr(x));
1523 }
1524 } else break;
1525 auto newExpList = x->new_ptr<ExpList_t>();
1526 auto newAssign = x->new_ptr<Assign_t>();
1482 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1527 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1483 newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); 1528 newAssignment->expList.set(newExpList);
1484 auto assign = x->new_ptr<Assign_t>(); 1529 newAssignment->action.set(newAssign);
1485 if (vit != values.end()) { 1530 for (auto exp : exprs) {
1486 assign->values.push_back(*vit); 1531 if (exp != *it) newExpList->exprs.push_back(exp);
1487 } else {
1488 assign->values.push_back(toAst<Exp_t>("nil"sv, *vit));
1489 } 1532 }
1490 newAssignment->action.set(assign); 1533 for (auto value : values) {
1491 transformAssignment(newAssignment, temp); 1534 if (value != *vit) newAssign->values.push_back(value);
1492 if (isScoped) {
1493 popScope();
1494 temp.push_back(indent() + "end"s + nlr(x));
1495 } 1535 }
1496 } else break; 1536 if (newExpList->exprs.empty() && newAssign->values.empty()) {
1497 auto newExpList = x->new_ptr<ExpList_t>(); 1537 out.push_back(join(temp));
1498 auto newAssign = x->new_ptr<Assign_t>(); 1538 return;
1499 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1539 }
1500 newAssignment->expList.set(newExpList); 1540 if (newExpList->exprs.size() < newAssign->values.size()) {
1501 newAssignment->action.set(newAssign); 1541 auto exp = toAst<Exp_t>("_"sv, x);
1502 for (auto exp : exprs) { 1542 while (newExpList->exprs.size() < newAssign->values.size()) {
1503 if (exp != *it) newExpList->exprs.push_back(exp); 1543 newExpList->exprs.push_back(exp);
1504 } 1544 }
1505 for (auto value : values) { 1545 }
1506 if (value != *vit) newAssign->values.push_back(value); 1546 transformAssignment(newAssignment, temp);
1507 }
1508 if (newExpList->exprs.empty() && newAssign->values.empty()) {
1509 out.push_back(join(temp)); 1547 out.push_back(join(temp));
1510 return; 1548 return;
1549 BLOCK_END
1550 if (vit != values.end()) ++vit;
1511 } 1551 }
1512 if (newExpList->exprs.size() < newAssign->values.size()) {
1513 auto exp = toAst<Exp_t>("_"sv, x);
1514 while (newExpList->exprs.size() < newAssign->values.size()) {
1515 newExpList->exprs.push_back(exp);
1516 }
1517 }
1518 transformAssignment(newAssignment, temp);
1519 out.push_back(join(temp));
1520 return;
1521 BLOCK_END
1522 if (vit != values.end()) ++vit;
1523 } 1552 }
1524 BREAK_IF(assign->values.objects().size() != 1); 1553 BREAK_IF(assign->values.objects().size() != 1);
1525 auto value = assign->values.objects().back(); 1554 auto value = assign->values.objects().back();
@@ -1530,12 +1559,11 @@ private:
1530 } 1559 }
1531 switch (value->getId()) { 1560 switch (value->getId()) {
1532 case id<If_t>(): { 1561 case id<If_t>(): {
1533 auto expList = assignment->expList.get(); 1562 auto ifNode = static_cast<If_t*>(value);
1534 str_list temp; 1563 auto assignList = assignment->expList.get();
1535 auto defs = transformAssignDefs(expList, DefOp::Mark); 1564 std::string preDefine = getPreDefineLine(assignment);
1536 if (!defs.empty()) temp.push_back(toLocalDecl(defs) + nll(expList)); 1565 transformIf(ifNode, out, ExpUsage::Assignment, assignList);
1537 transformIf(static_cast<If_t*>(value), temp, ExpUsage::Assignment, expList); 1566 out.back().insert(0, preDefine);
1538 out.push_back(join(temp));
1539 return; 1567 return;
1540 } 1568 }
1541 case id<Switch_t>(): { 1569 case id<Switch_t>(): {