aboutsummaryrefslogtreecommitdiff
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
parente191defb6545509a4ae0b402f2fac1fbe18551cd (diff)
downloadyuescript-0f5bdeaeba0f04e49c47f4a2be55b14185a7dfdd.tar.gz
yuescript-0f5bdeaeba0f04e49c47f4a2be55b14185a7dfdd.tar.bz2
yuescript-0f5bdeaeba0f04e49c47f4a2be55b14185a7dfdd.zip
fix missing checks and issues related to destrucuring in if branches.
-rw-r--r--spec/inputs/assign.yue50
-rw-r--r--spec/inputs/cond.yue2
-rw-r--r--spec/inputs/global.yue4
-rw-r--r--spec/inputs/metatable.yue2
-rw-r--r--spec/inputs/using.yue7
-rw-r--r--spec/outputs/assign.lua93
-rw-r--r--spec/outputs/cond.lua2
-rw-r--r--spec/outputs/global.lua4
-rw-r--r--spec/outputs/metatable.lua2
-rw-r--r--spec/outputs/using.lua7
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp200
11 files changed, 273 insertions, 100 deletions
diff --git a/spec/inputs/assign.yue b/spec/inputs/assign.yue
index dac2ba3..d04bcb8 100644
--- a/spec/inputs/assign.yue
+++ b/spec/inputs/assign.yue
@@ -8,20 +8,20 @@ _ = ->
8 8
9 a,b,c,d = 1,2,3,4 9 a,b,c,d = 1,2,3,4
10 10
11 hello[232], (5+5)[121], hello, x[99] = 100, 200, 300 11 hello[232], (5+5)[121], hello, x[99] = 100, 200, 300, 400
12 12
13 joop = 12 13 joop = 12
14 14
15joop = 2345 15joop = 2345
16 16
17a, b = if hello 17a, b = if hello
18 "hello" 18 "hello", nil
19else 19else
20 "nothing", "yeah" 20 "nothing", "yeah"
21 21
22 22
23a, b = if hello 23a, b = if hello
24 if yeah then "one", "two" else "mmhh" 24 if yeah then "one", "two" else "mmhh", nil
25else 25else
26 print "the other" 26 print "the other"
27 "nothing", "yeah" 27 "nothing", "yeah"
@@ -31,3 +31,47 @@ c, d = 1, 2 if true
31x = (do 31x = (do
32 f! 32 f!
33 123) if f = getHandler! 33 123) if f = getHandler!
34
35(using nil) <- _
36
37a.# = do
38 print 123
39 {}
40
41do
42 {a, b} = switch c
43 when "a"
44 tb
45 when "b"
46 f!
47
48a[] = if x
49 1
50else
51 2
52
53do
54 a, b[] = if x
55 switch y
56 when 1
57 f!
58
59do
60 a, {b} = if x
61 f!
62 else
63 123, tb
64
65do
66 a, b[], c, d.add# = if x
67 switch y
68 when 1
69 f!
70 elseif x2
71 if y2
72 f1!
73 else
74 print "hello"
75 do
76 print 123
77 1, f2!
diff --git a/spec/inputs/cond.yue b/spec/inputs/cond.yue
index 773ef91..9981e93 100644
--- a/spec/inputs/cond.yue
+++ b/spec/inputs/cond.yue
@@ -158,7 +158,7 @@ do
158---------------- 158----------------
159 159
160a = 12 160a = 12
161a,c,b = "cool" if something 161a,c,b = "cool", nil, nil if something
162 162
163 163
164 164
diff --git a/spec/inputs/global.yue b/spec/inputs/global.yue
index 7d6cfde..59cf764 100644
--- a/spec/inputs/global.yue
+++ b/spec/inputs/global.yue
@@ -1,6 +1,6 @@
1 1
2do 2do
3 global a,b,c = 223, 343 3 global a,b,c = 223, 343, nil
4 global cool = "dad" 4 global cool = "dad"
5 5
6do 6do
@@ -9,7 +9,7 @@ do
9 9
10do 10do
11 global a,b,c 11 global a,b,c
12 a,b,c,d = "hello" 12 a,b,c,d = "hello", nil, nil, nil
13 13
14 14
15do 15do
diff --git a/spec/inputs/metatable.yue b/spec/inputs/metatable.yue
index 7e9b4f2..86991c2 100644
--- a/spec/inputs/metatable.yue
+++ b/spec/inputs/metatable.yue
@@ -24,7 +24,7 @@ do
24 24
25x.abc, a.b.# = 123, {} 25x.abc, a.b.# = 123, {}
26func!.# = mt --, extra 26func!.# = mt --, extra
27a, b.c.#, d, e = 1, mt, "abc" 27a, b.c.#, d, e = 1, mt, "abc", nil
28 28
29is_same = a.#.__index == a.index# 29is_same = a.#.__index == a.index#
30 30
diff --git a/spec/inputs/using.yue b/spec/inputs/using.yue
index 9944b60..31afaab 100644
--- a/spec/inputs/using.yue
+++ b/spec/inputs/using.yue
@@ -20,3 +20,10 @@ _ = (a,e,f using a,b,c, hello) ->
20 20
21_ = (using nil) -> 21_ = (using nil) ->
22 hello or= 2 22 hello or= 2
23
24do
25 a = {}
26 (using nil) <- _
27 {x, y} = a
28
29nil
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua
index 628f763..c7f2e20 100644
--- a/spec/outputs/assign.lua
+++ b/spec/outputs/assign.lua
@@ -7,14 +7,14 @@ _ = function()
7 local a, b, c 7 local a, b, c
8 a, b, c, d = 1, 2, 3, 4 8 a, b, c, d = 1, 2, 3, 4
9 local hello 9 local hello
10 hello[232], (5 + 5)[121], hello, x[99] = 100, 200, 300 10 hello[232], (5 + 5)[121], hello, x[99] = 100, 200, 300, 400
11 joop = 12 11 joop = 12
12 end 12 end
13end 13end
14local joop = 2345 14local joop = 2345
15local a, b 15local a, b
16if hello then 16if hello then
17 a, b = "hello" 17 a, b = "hello", nil
18else 18else
19 a, b = "nothing", "yeah" 19 a, b = "nothing", "yeah"
20end 20end
@@ -22,7 +22,7 @@ if hello then
22 if yeah then 22 if yeah then
23 a, b = "one", "two" 23 a, b = "one", "two"
24 else 24 else
25 a, b = "mmhh" 25 a, b = "mmhh", nil
26 end 26 end
27else 27else
28 print("the other") 28 print("the other")
@@ -42,3 +42,90 @@ do
42 end)()) 42 end)())
43 end 43 end
44end 44end
45return _(function()
46 setmetatable(a, (function()
47 print(123)
48 return { }
49 end)())
50 do
51 local a, b
52 if "a" == c then
53 do
54 local _obj_0 = tb
55 a, b = _obj_0[1], _obj_0[2]
56 end
57 elseif "b" == c then
58 do
59 local _obj_0 = f()
60 a, b = _obj_0[1], _obj_0[2]
61 end
62 end
63 end
64 if x then
65 a[#a + 1] = 1
66 else
67 a[#a + 1] = 2
68 end
69 do
70 local a
71 if x then
72 do
73 local _exp_0 = y
74 if 1 == _exp_0 then
75 do
76 local _obj_0, _obj_1 = f()
77 b[#b + 1] = _obj_1
78 a = _obj_0
79 end
80 end
81 end
82 end
83 end
84 do
85 local a
86 local b
87 if x then
88 do
89 local _obj_0, _obj_1 = f()
90 a = _obj_0
91 b = _obj_1[1]
92 end
93 else
94 a = 123
95 b = tb[1]
96 end
97 end
98 do
99 local a, c
100 if x then
101 do
102 local _exp_0 = y
103 if 1 == _exp_0 then
104 do
105 local _obj_0, _obj_1, _obj_2, _obj_3 = f()
106 b[#b + 1] = _obj_1
107 a, c, getmetatable(d).__add = _obj_0, _obj_2, _obj_3
108 end
109 end
110 end
111 elseif x2 then
112 if y2 then
113 do
114 local _obj_0, _obj_1, _obj_2, _obj_3 = f1()
115 b[#b + 1] = _obj_1
116 a, c, getmetatable(d).__add = _obj_0, _obj_2, _obj_3
117 end
118 end
119 else
120 print("hello")
121 do
122 print(123)
123 do
124 local _obj_0, _obj_1, _obj_2 = f2()
125 b[#b + 1] = _obj_0
126 a, c, getmetatable(d).__add = 1, _obj_1, _obj_2
127 end
128 end
129 end
130 end
131end)
diff --git a/spec/outputs/cond.lua b/spec/outputs/cond.lua
index 178bf9b..7764439 100644
--- a/spec/outputs/cond.lua
+++ b/spec/outputs/cond.lua
@@ -251,7 +251,7 @@ end
251local a = 12 251local a = 12
252local c, b 252local c, b
253if something then 253if something then
254 a, c, b = "cool" 254 a, c, b = "cool", nil, nil
255end 255end
256local j 256local j
257if 1 then 257if 1 then
diff --git a/spec/outputs/global.lua b/spec/outputs/global.lua
index ef73823..930ecf6 100644
--- a/spec/outputs/global.lua
+++ b/spec/outputs/global.lua
@@ -1,5 +1,5 @@
1do 1do
2 a, b, c = 223, 343 2 a, b, c = 223, 343, nil
3 cool = "dad" 3 cool = "dad"
4end 4end
5do 5do
@@ -29,7 +29,7 @@ do
29end 29end
30do 30do
31 local d 31 local d
32 a, b, c, d = "hello" 32 a, b, c, d = "hello", nil, nil, nil
33end 33end
34do 34do
35 local What 35 local What
diff --git a/spec/outputs/metatable.lua b/spec/outputs/metatable.lua
index 2d72e1d..6f5ceed 100644
--- a/spec/outputs/metatable.lua
+++ b/spec/outputs/metatable.lua
@@ -66,7 +66,7 @@ setmetatable(a.b, { })
66x.abc = 123 66x.abc = 123
67setmetatable(func(), mt) 67setmetatable(func(), mt)
68setmetatable(b.c, mt) 68setmetatable(b.c, mt)
69a, d, e = 1, "abc" 69a, d, e = 1, "abc", nil
70local is_same = getmetatable(a).__index == getmetatable(a).__index 70local is_same = getmetatable(a).__index == getmetatable(a).__index
71setmetatable(a, { 71setmetatable(a, {
72 __index = tb 72 __index = tb
diff --git a/spec/outputs/using.lua b/spec/outputs/using.lua
index 6d0d888..ff23a30 100644
--- a/spec/outputs/using.lua
+++ b/spec/outputs/using.lua
@@ -21,3 +21,10 @@ end
21_ = function() 21_ = function()
22 local hello = hello or 2 22 local hello = hello or 2
23end 23end
24do
25 local a = { };
26 _(function()
27 local x, y = a[1], a[2]
28 end)
29end
30return nil
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>(): {