summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-10-31 17:29:45 +0800
committerLi Jin <dragon-fly@qq.com>2021-10-31 17:29:45 +0800
commitaed806476fe50899c0f01750175531ac41267b9d (patch)
treec46f212a2987a9088b03e2c0225f18cd9a5d4265
parent60a979e224f26117f5be82bfca757a2483cef0fd (diff)
downloadyuescript-aed806476fe50899c0f01750175531ac41267b9d.tar.gz
yuescript-aed806476fe50899c0f01750175531ac41267b9d.tar.bz2
yuescript-aed806476fe50899c0f01750175531ac41267b9d.zip
partially fix issue #69, fix a few case the generated code leaks some temp variables.
-rw-r--r--spec/inputs/nil_coalesing.yue40
-rw-r--r--spec/outputs/export.lua32
-rw-r--r--spec/outputs/multiline_chain.lua12
-rw-r--r--spec/outputs/nil_coalesing.lua138
-rw-r--r--spec/outputs/switch.lua110
-rwxr-xr-xsrc/yuescript/yue_ast.h3
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp255
-rwxr-xr-xsrc/yuescript/yue_parser.cpp7
8 files changed, 490 insertions, 107 deletions
diff --git a/spec/inputs/nil_coalesing.yue b/spec/inputs/nil_coalesing.yue
new file mode 100644
index 0000000..45b34f4
--- /dev/null
+++ b/spec/inputs/nil_coalesing.yue
@@ -0,0 +1,40 @@
1do
2 a = b ?? c
3
4do
5 :a = b ?? c
6
7do
8 a = func!
9 a ??= false
10
11do
12 a ??= func!
13
14do
15 local a, b, c, d, e
16 a = b ?? c ?? d ?? e
17
18do
19 a = b ?? c ?? d ?? e
20
21do
22 func x ?? "hello"
23
24do
25 with funcA! ?? funcB!
26 print .field
27
28do
29 a = 1 + 2 + b ?? c + 3 + 4
30
31do
32 a = 1 + 2 + (b ?? c) + 3 + 4
33
34do
35 :a, :b = func!
36 a or= 1
37 b ??= c ?? 2
38
39nil
40
diff --git a/spec/outputs/export.lua b/spec/outputs/export.lua
index 02546ec..4d81cc0 100644
--- a/spec/outputs/export.lua
+++ b/spec/outputs/export.lua
@@ -65,22 +65,26 @@ y = function()
65 local k = 100 65 local k = 100
66end 66end
67_module_0["y"] = y 67_module_0["y"] = y
68local _exp_0 = h 68do
69if 100 == _exp_0 or 150 == _exp_0 then 69 local _exp_0 = h
70 _module_0[#_module_0 + 1] = 200 70 if 100 == _exp_0 or 150 == _exp_0 then
71elseif 200 == _exp_0 then 71 _module_0[#_module_0 + 1] = 200
72 _module_0[#_module_0 + 1] = 300 72 elseif 200 == _exp_0 then
73else 73 _module_0[#_module_0 + 1] = 300
74 _module_0[#_module_0 + 1] = 0 74 else
75 _module_0[#_module_0 + 1] = 0
76 end
75end 77end
76local Constant 78local Constant
77local _exp_1 = value 79do
78if "good" == _exp_1 then 80 local _exp_0 = value
79 Constant = 1 81 if "good" == _exp_0 then
80elseif "better" == _exp_1 then 82 Constant = 1
81 Constant = 2 83 elseif "better" == _exp_0 then
82elseif "best" == _exp_1 then 84 Constant = 2
83 Constant = 3 85 elseif "best" == _exp_0 then
86 Constant = 3
87 end
84end 88end
85_module_0["Constant"] = Constant 89_module_0["Constant"] = Constant
86local item = func(123) 90local item = func(123)
diff --git a/spec/outputs/multiline_chain.lua b/spec/outputs/multiline_chain.lua
index fea7bc6..ecd2ca8 100644
--- a/spec/outputs/multiline_chain.lua
+++ b/spec/outputs/multiline_chain.lua
@@ -56,11 +56,13 @@ do
56 _with_0:callMethod():chainCall() 56 _with_0:callMethod():chainCall()
57 _with_0:callMethod():chainCall() 57 _with_0:callMethod():chainCall()
58 _with_0:chainCall() 58 _with_0:chainCall()
59 local _exp_0 = _with_0.itemFieldB:getValue() 59 do
60 if "Valid" == _exp_0 or _with_0:getItemState() == _exp_0 then 60 local _exp_0 = _with_0.itemFieldB:getValue()
61 _with_0:itemMethodA():getValue() 61 if "Valid" == _exp_0 or _with_0:getItemState() == _exp_0 then
62 else 62 _with_0:itemMethodA():getValue()
63 _with_0:itemMethodB():getValue() 63 else
64 _with_0:itemMethodB():getValue()
65 end
64 end 66 end
65 local a 67 local a
66 if _with_0.itemFieldC then 68 if _with_0.itemFieldC then
diff --git a/spec/outputs/nil_coalesing.lua b/spec/outputs/nil_coalesing.lua
new file mode 100644
index 0000000..36a6644
--- /dev/null
+++ b/spec/outputs/nil_coalesing.lua
@@ -0,0 +1,138 @@
1do
2 local a
3 do
4 local _exp_0 = b
5 if _exp_0 ~= nil then
6 a = _exp_0
7 else
8 a = c
9 end
10 end
11end
12do
13 local a
14 do
15 local _exp_0 = b
16 if _exp_0 ~= nil then
17 a = _exp_0.a
18 else
19 a = c.a
20 end
21 end
22end
23do
24 local a = func()
25 if a == nil then
26 a = false
27 end
28end
29do
30 local a
31 if a == nil then
32 a = func()
33 end
34end
35do
36 local a, b, c, d, e
37 if b ~= nil then
38 a = b
39 else
40 if c ~= nil then
41 a = c
42 else
43 if d ~= nil then
44 a = d
45 else
46 a = e
47 end
48 end
49 end
50end
51do
52 local a
53 do
54 local _exp_0 = b
55 if _exp_0 ~= nil then
56 a = _exp_0
57 else
58 do
59 local _exp_1 = c
60 if _exp_1 ~= nil then
61 a = _exp_1
62 else
63 do
64 local _exp_2 = d
65 if _exp_2 ~= nil then
66 a = _exp_2
67 else
68 a = e
69 end
70 end
71 end
72 end
73 end
74 end
75end
76do
77 func((function()
78 local _exp_0 = x
79 if _exp_0 ~= nil then
80 return _exp_0
81 else
82 return "hello"
83 end
84 end)())
85end
86do
87 do
88 local _with_0
89 do
90 local _exp_0 = funcA()
91 if _exp_0 ~= nil then
92 _with_0 = _exp_0
93 else
94 _with_0 = funcB()
95 end
96 end
97 print(_with_0.field)
98 end
99end
100do
101 local a = 1 + 2 + (function()
102 local _exp_0 = b
103 if _exp_0 ~= nil then
104 return _exp_0
105 else
106 return c + 3 + 4
107 end
108 end)()
109end
110do
111 local a = 1 + 2 + ((function()
112 local _exp_0 = b
113 if _exp_0 ~= nil then
114 return _exp_0
115 else
116 return c
117 end
118 end)()) + 3 + 4
119end
120do
121 local a, b
122 do
123 local _obj_0 = func()
124 a, b = _obj_0.a, _obj_0.b
125 end
126 a = a or 1
127 if b == nil then
128 do
129 local _exp_0 = c
130 if _exp_0 ~= nil then
131 b = _exp_0
132 else
133 b = 2
134 end
135 end
136 end
137end
138return nil
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua
index 1c8839f..81f6d5a 100644
--- a/spec/outputs/switch.lua
+++ b/spec/outputs/switch.lua
@@ -1,70 +1,86 @@
1local _exp_0 = value 1do
2if "cool" == _exp_0 then 2 local _exp_0 = value
3 print("hello world") 3 if "cool" == _exp_0 then
4 print("hello world")
5 end
4end 6end
5local _exp_1 = value 7do
6if "cool" == _exp_1 then 8 local _exp_0 = value
7 print("hello world") 9 if "cool" == _exp_0 then
8else 10 print("hello world")
9 print("okay rad") 11 else
12 print("okay rad")
13 end
10end 14end
11local _exp_2 = value 15do
12if "cool" == _exp_2 then 16 local _exp_0 = value
13 print("hello world") 17 if "cool" == _exp_0 then
14elseif "yeah" == _exp_2 then 18 print("hello world")
15 local _ = [[FFFF]] + [[MMMM]] 19 elseif "yeah" == _exp_0 then
16elseif (2323 + 32434) == _exp_2 then 20 local _ = [[FFFF]] + [[MMMM]]
17 print("okay") 21 elseif (2323 + 32434) == _exp_0 then
18else 22 print("okay")
19 print("okay rad") 23 else
24 print("okay rad")
25 end
20end 26end
21local out 27local out
22local _exp_3 = value 28do
23if "cool" == _exp_3 then 29 local _exp_0 = value
24 out = print("hello world") 30 if "cool" == _exp_0 then
25else 31 out = print("hello world")
26 out = print("okay rad") 32 else
33 out = print("okay rad")
34 end
27end 35end
28local _exp_4 = value 36do
29if "cool" == _exp_4 then 37 local _exp_0 = value
30 out = xxxx 38 if "cool" == _exp_0 then
31elseif "umm" == _exp_4 then 39 out = xxxx
32 out = 34340 40 elseif "umm" == _exp_0 then
33else 41 out = 34340
34 out = error("this failed big time") 42 else
43 out = error("this failed big time")
44 end
35end 45end
36do 46do
37 local _with_0 = something 47 local _with_0 = something
38 local _exp_5 = _with_0:value() 48 do
39 if _with_0.okay == _exp_5 then 49 local _exp_0 = _with_0:value()
40 local _ = "world" 50 if _with_0.okay == _exp_0 then
41 else 51 local _ = "world"
42 local _ = "yesh" 52 else
53 local _ = "yesh"
54 end
43 end 55 end
44end 56end
45fix(this) 57fix(this)
46call_func((function() 58call_func((function()
47 local _exp_5 = something 59 local _exp_0 = something
48 if 1 == _exp_5 then 60 if 1 == _exp_0 then
49 return "yes" 61 return "yes"
50 else 62 else
51 return "no" 63 return "no"
52 end 64 end
53end)()) 65end)())
54local _exp_5 = hi 66do
55if (hello or world) == _exp_5 then 67 local _exp_0 = hi
56 local _ = greene 68 if (hello or world) == _exp_0 then
69 local _ = greene
70 end
57end 71end
58local _exp_6 = hi 72do
59if "one" == _exp_6 or "two" == _exp_6 then 73 local _exp_0 = hi
60 print("cool") 74 if "one" == _exp_0 or "two" == _exp_0 then
61elseif "dad" == _exp_6 then 75 print("cool")
62 local _ = no 76 elseif "dad" == _exp_0 then
77 local _ = no
78 end
63end 79end
64local _exp_7 = hi 80local _exp_0 = hi
65if (3 + 1) == _exp_7 or hello() == _exp_7 or (function() 81if (3 + 1) == _exp_0 or hello() == _exp_0 or (function()
66 return 4 82 return 4
67end)() == _exp_7 then 83end)() == _exp_0 then
68 return yello 84 return yello
69else 85else
70 return print("cool") 86 return print("cool")
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 38da1fa..719b1cd 100755
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -404,7 +404,8 @@ AST_NODE(Exp)
404 ast_ptr<true, Seperator_t> sep; 404 ast_ptr<true, Seperator_t> sep;
405 ast_list<true, unary_exp_t> pipeExprs; 405 ast_list<true, unary_exp_t> pipeExprs;
406 ast_list<false, exp_op_value_t> opValues; 406 ast_list<false, exp_op_value_t> opValues;
407 AST_MEMBER(Exp, &sep, &pipeExprs, &opValues) 407 ast_ptr<false, Exp_t> nilCoalesed;
408 AST_MEMBER(Exp, &sep, &pipeExprs, &opValues, &nilCoalesed)
408AST_END(Exp) 409AST_END(Exp)
409 410
410class Parens_t; 411class Parens_t;
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 3ff032c..415fcd3 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -856,6 +856,10 @@ private:
856 return exp->opValues.empty() && exp->pipeExprs.size() > 1; 856 return exp->opValues.empty() && exp->pipeExprs.size() > 1;
857 } 857 }
858 858
859 bool isPureNilCoalesed(Exp_t* exp) const {
860 return exp->nilCoalesed && exp->opValues.empty();
861 }
862
859 bool isMacroChain(ChainValue_t* chainValue) const { 863 bool isMacroChain(ChainValue_t* chainValue) const {
860 const auto& chainList = chainValue->items.objects(); 864 const auto& chainList = chainValue->items.objects();
861 BLOCK_START 865 BLOCK_START
@@ -1345,6 +1349,10 @@ private:
1345 auto expList = assignment->expList.get(); 1349 auto expList = assignment->expList.get();
1346 transformExp(exp, out, ExpUsage::Assignment, expList); 1350 transformExp(exp, out, ExpUsage::Assignment, expList);
1347 return; 1351 return;
1352 } else if (isPureNilCoalesed(exp)) {
1353 auto expList = assignment->expList.get();
1354 transformNilCoalesedExp(exp, out, ExpUsage::Assignment, expList);
1355 return;
1348 } 1356 }
1349 auto singleVal = singleValueFrom(exp); 1357 auto singleVal = singleValueFrom(exp);
1350 BREAK_IF(!singleVal); 1358 BREAK_IF(!singleVal);
@@ -2020,12 +2028,12 @@ private:
2020 auto var = singleVariableFrom(exp); 2028 auto var = singleVariableFrom(exp);
2021 BREAK_IF(!var.empty()); 2029 BREAK_IF(!var.empty());
2022 auto upVar = getUnusedName("_update_"sv); 2030 auto upVar = getUnusedName("_update_"sv);
2023 auto assignment = x->new_ptr<ExpListAssign_t>(); 2031 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2024 assignment->expList.set(toAst<ExpList_t>(upVar, x)); 2032 newAssignment->expList.set(toAst<ExpList_t>(upVar, x));
2025 auto assign = x->new_ptr<Assign_t>(); 2033 auto assign = x->new_ptr<Assign_t>();
2026 assign->values.push_back(exp); 2034 assign->values.push_back(exp);
2027 assignment->action.set(assign); 2035 newAssignment->action.set(assign);
2028 transformAssignment(assignment, temp); 2036 transformAssignment(newAssignment, temp);
2029 tmpChain->items.push_back(toAst<Exp_t>(upVar, x)); 2037 tmpChain->items.push_back(toAst<Exp_t>(upVar, x));
2030 itemAdded = true; 2038 itemAdded = true;
2031 BLOCK_END 2039 BLOCK_END
@@ -2034,6 +2042,17 @@ private:
2034 chain->items.clear(); 2042 chain->items.clear();
2035 chain->items.dup(tmpChain->items); 2043 chain->items.dup(tmpChain->items);
2036 } 2044 }
2045 auto op = _parser.toString(update->op);
2046 if (op == "??"sv) {
2047 auto defs = getPredefine(assignment);
2048 auto rightExp = x->new_ptr<Exp_t>();
2049 rightExp->pipeExprs.dup(leftExp->pipeExprs);
2050 rightExp->opValues.dup(leftExp->opValues);
2051 rightExp->nilCoalesed.set(update->value);
2052 transformNilCoalesedExp(rightExp, out, ExpUsage::Assignment, assignment->expList, true);
2053 if (!defs.empty()) out.back().insert(0, defs + nll(x));
2054 return;
2055 }
2037 auto defs = getPredefine(assignment); 2056 auto defs = getPredefine(assignment);
2038 transformValue(leftValue, temp); 2057 transformValue(leftValue, temp);
2039 auto left = std::move(temp.back()); 2058 auto left = std::move(temp.back());
@@ -2048,7 +2067,7 @@ private:
2048 if (!defs.empty()) _buf << defs; 2067 if (!defs.empty()) _buf << defs;
2049 else _buf << indent() << left; 2068 else _buf << indent() << left;
2050 _buf << " = "sv << left << 2069 _buf << " = "sv << left <<
2051 ' ' << _parser.toString(update->op) << ' ' << right << nll(assignment); 2070 ' ' << op << ' ' << right << nll(assignment);
2052 out.push_back(clearBuf()); 2071 out.push_back(clearBuf());
2053 break; 2072 break;
2054 } 2073 }
@@ -2142,10 +2161,10 @@ private:
2142 str_list temp; 2161 str_list temp;
2143 std::string* funcStart = nullptr; 2162 std::string* funcStart = nullptr;
2144 if (usage == ExpUsage::Closure) { 2163 if (usage == ExpUsage::Closure) {
2164 _enableReturn.push(true);
2145 pushAnonVarArg(); 2165 pushAnonVarArg();
2146 funcStart = &temp.emplace_back(); 2166 funcStart = &temp.emplace_back();
2147 pushScope(); 2167 pushScope();
2148 _enableReturn.push(true);
2149 } 2168 }
2150 std::list<std::pair<IfCond_t*, ast_node*>> ifCondPairs; 2169 std::list<std::pair<IfCond_t*, ast_node*>> ifCondPairs;
2151 ifCondPairs.emplace_back(); 2170 ifCondPairs.emplace_back();
@@ -2255,11 +2274,11 @@ private:
2255 temp.push_back(indent() + "end"s + nlr(nodes.front())); 2274 temp.push_back(indent() + "end"s + nlr(nodes.front()));
2256 } 2275 }
2257 if (usage == ExpUsage::Closure) { 2276 if (usage == ExpUsage::Closure) {
2258 _enableReturn.pop();
2259 popScope(); 2277 popScope();
2260 *funcStart = anonFuncStart() + nll(nodes.front()); 2278 *funcStart = anonFuncStart() + nll(nodes.front());
2261 temp.push_back(indent() + anonFuncEnd()); 2279 temp.push_back(indent() + anonFuncEnd());
2262 popAnonVarArg(); 2280 popAnonVarArg();
2281 _enableReturn.pop();
2263 } 2282 }
2264 out.push_back(join(temp)); 2283 out.push_back(join(temp));
2265 } 2284 }
@@ -2375,15 +2394,19 @@ private:
2375 } 2394 }
2376 2395
2377 void transformExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 2396 void transformExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
2378 if (exp->opValues.empty()) { 2397 if (exp->opValues.empty() && !exp->nilCoalesed) {
2379 transform_pipe_exp(exp->pipeExprs.objects(), out, usage, assignList); 2398 transform_pipe_exp(exp->pipeExprs.objects(), out, usage, assignList);
2380 return; 2399 return;
2381 } 2400 }
2382 if (usage != ExpUsage::Closure) { 2401 if (usage != ExpUsage::Closure) {
2383 YUEE("invalid expression usage", exp); 2402 YUEE("invalid expression usage", exp);
2384 } 2403 }
2404 if (exp->nilCoalesed) {
2405 transformNilCoalesedExp(exp, out, ExpUsage::Closure);
2406 return;
2407 }
2385 str_list temp; 2408 str_list temp;
2386 transform_pipe_exp(exp->pipeExprs.objects(), temp, ExpUsage::Closure); 2409 transform_pipe_exp(exp->pipeExprs.objects(), temp, ExpUsage::Closure);
2387 for (auto _opValue : exp->opValues.objects()) { 2410 for (auto _opValue : exp->opValues.objects()) {
2388 auto opValue = static_cast<exp_op_value_t*>(_opValue); 2411 auto opValue = static_cast<exp_op_value_t*>(_opValue);
2389 transformBinaryOperator(opValue->op, temp); 2412 transformBinaryOperator(opValue->op, temp);
@@ -2392,6 +2415,129 @@ private:
2392 out.push_back(join(temp, " "sv)); 2415 out.push_back(join(temp, " "sv));
2393 } 2416 }
2394 2417
2418 void transformNilCoalesedExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool nilBranchOnly = false) {
2419 auto x = exp;
2420 str_list temp;
2421 std::string prefix;
2422 auto left = exp->new_ptr<Exp_t>();
2423 if (exp->opValues.empty()) {
2424 left->pipeExprs.dup(exp->pipeExprs);
2425 } else {
2426 if (usage != ExpUsage::Closure) {
2427 YUEE("invalid expression usage", exp);
2428 }
2429 transform_pipe_exp(exp->pipeExprs.objects(), temp, ExpUsage::Closure);
2430 auto last = exp->opValues.objects().back();
2431 for (auto _opValue : exp->opValues.objects()) {
2432 auto opValue = static_cast<exp_op_value_t*>(_opValue);
2433 transformBinaryOperator(opValue->op, temp);
2434 if (opValue == last) {
2435 left->pipeExprs.dup(opValue->pipeExprs);
2436 } else {
2437 transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure);
2438 }
2439 }
2440 prefix = join(temp, " "sv) + ' ';
2441 temp.clear();
2442 temp.push_back(prefix);
2443 }
2444 std::string* funcStart = nullptr;
2445 if (usage == ExpUsage::Closure) {
2446 _enableReturn.push(true);
2447 pushAnonVarArg();
2448 funcStart = &temp.emplace_back();
2449 pushScope();
2450 }
2451 auto objVar = singleVariableFrom(left);
2452 auto prepareValue = [&](bool forAssignment = false) {
2453 if (objVar.empty() || !isLocal(objVar)) {
2454 if (forAssignment) {
2455 temp.push_back(indent() + "do"s + nll(x));
2456 pushScope();
2457 }
2458 objVar = getUnusedName("_exp_"sv);
2459 auto expList = toAst<ExpList_t>(objVar, x);
2460 auto assign = x->new_ptr<Assign_t>();
2461 assign->values.push_back(left);
2462 auto assignment = x->new_ptr<ExpListAssign_t>();
2463 assignment->expList.set(expList);
2464 assignment->action.set(assign);
2465 transformAssignment(assignment, temp);
2466 return true;
2467 }
2468 return false;
2469 };
2470 switch (usage) {
2471 case ExpUsage::Common: YUEE("AST node mismatch", x); return;
2472 case ExpUsage::Return:
2473 case ExpUsage::Closure: {
2474 prepareValue();
2475 _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x);
2476 _buf << indent(1) << "return "s << objVar << nll(x);
2477 _buf << indent() << "else"s << nll(x);
2478 temp.push_back(clearBuf());
2479 auto ret = x->new_ptr<Return_t>();
2480 auto retList = x->new_ptr<ExpListLow_t>();
2481 retList->exprs.push_back(exp->nilCoalesed);
2482 ret->valueList.set(retList);
2483 incIndentOffset();
2484 transformReturn(ret, temp);
2485 decIndentOffset();
2486 temp.push_back(indent() + "end"s + nll(x));
2487 if (usage == ExpUsage::Closure) {
2488 popScope();
2489 *funcStart = anonFuncStart() + nll(x);
2490 temp.push_back(indent() + anonFuncEnd());
2491 popAnonVarArg();
2492 _enableReturn.pop();
2493 }
2494 break;
2495 }
2496 case ExpUsage::Assignment: {
2497 auto assign = x->new_ptr<Assign_t>();
2498 auto assignment = x->new_ptr<ExpListAssign_t>();
2499 assignment->expList.set(assignList);
2500 assignment->action.set(assign);
2501 bool extraScope = false;
2502 if (!nilBranchOnly) {
2503 assign->values.push_back(exp);
2504 std::string& predefine = temp.emplace_back();
2505 auto defs = getPredefine(assignment);
2506 if (!defs.empty()) predefine = defs + nll(x);
2507 extraScope = prepareValue(true);
2508 _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x);
2509 temp.push_back(clearBuf());
2510 pushScope();
2511 assign->values.clear();
2512 assign->values.push_back(toAst<Exp_t>(objVar, x));
2513 transformAssignment(assignment, temp);
2514 popScope();
2515 temp.push_back(indent() + "else"s + nll(x));
2516 assign->values.clear();
2517 assign->values.push_back(exp->nilCoalesed);
2518 } else {
2519 assign->values.clear();
2520 assign->values.push_back(exp->nilCoalesed);
2521 auto defs = getPredefine(assignment);
2522 if (!defs.empty()) temp.push_back(defs + nll(x));
2523 prepareValue();
2524 _buf << indent() << "if "sv << objVar << " == nil then"sv << nll(x);
2525 temp.push_back(clearBuf());
2526 }
2527 pushScope();
2528 transformAssignment(assignment, temp);
2529 popScope();
2530 temp.push_back(indent() + "end"s + nlr(x));
2531 if (extraScope) {
2532 popScope();
2533 temp.push_back(indent() + "end"s + nlr(x));
2534 }
2535 break;
2536 }
2537 }
2538 out.push_back(join(temp));
2539 }
2540
2395 void transformValue(Value_t* value, str_list& out) { 2541 void transformValue(Value_t* value, str_list& out) {
2396 auto item = value->item.get(); 2542 auto item = value->item.get();
2397 switch (item->getId()) { 2543 switch (item->getId()) {
@@ -3022,6 +3168,9 @@ private:
3022 if (isPureBackcall(exp)) { 3168 if (isPureBackcall(exp)) {
3023 transformExp(exp, out, ExpUsage::Return); 3169 transformExp(exp, out, ExpUsage::Return);
3024 return; 3170 return;
3171 } else if (isPureNilCoalesed(exp)) {
3172 transformNilCoalesedExp(exp, out, ExpUsage::Return);
3173 return;
3025 } 3174 }
3026 } 3175 }
3027 if (auto singleValue = singleValueFrom(valueList)) { 3176 if (auto singleValue = singleValueFrom(valueList)) {
@@ -3294,10 +3443,10 @@ private:
3294 str_list temp; 3443 str_list temp;
3295 std::string* funcStart = nullptr; 3444 std::string* funcStart = nullptr;
3296 if (usage == ExpUsage::Closure) { 3445 if (usage == ExpUsage::Closure) {
3446 _enableReturn.push(true);
3297 pushAnonVarArg(); 3447 pushAnonVarArg();
3298 funcStart = &temp.emplace_back(); 3448 funcStart = &temp.emplace_back();
3299 pushScope(); 3449 pushScope();
3300 _enableReturn.push(true);
3301 } 3450 }
3302 auto partOne = x->new_ptr<ChainValue_t>(); 3451 auto partOne = x->new_ptr<ChainValue_t>();
3303 for (auto it = chainList.begin();it != opIt;++it) { 3452 for (auto it = chainList.begin();it != opIt;++it) {
@@ -3428,11 +3577,11 @@ private:
3428 break; 3577 break;
3429 case ExpUsage::Closure: 3578 case ExpUsage::Closure:
3430 temp.push_back(indent() + "return nil"s + nlr(x)); 3579 temp.push_back(indent() + "return nil"s + nlr(x));
3431 _enableReturn.pop();
3432 popScope(); 3580 popScope();
3433 *funcStart = anonFuncStart() + nll(x); 3581 *funcStart = anonFuncStart() + nll(x);
3434 temp.push_back(indent() + anonFuncEnd()); 3582 temp.push_back(indent() + anonFuncEnd());
3435 popAnonVarArg(); 3583 popAnonVarArg();
3584 _enableReturn.pop();
3436 break; 3585 break;
3437 default: 3586 default:
3438 break; 3587 break;
@@ -3454,10 +3603,10 @@ private:
3454 pushScope(); 3603 pushScope();
3455 break; 3604 break;
3456 case ExpUsage::Closure: 3605 case ExpUsage::Closure:
3606 _enableReturn.push(true);
3457 pushAnonVarArg(); 3607 pushAnonVarArg();
3458 funcStart = &temp.emplace_back(); 3608 funcStart = &temp.emplace_back();
3459 pushScope(); 3609 pushScope();
3460 _enableReturn.push(true);
3461 break; 3610 break;
3462 default: 3611 default:
3463 break; 3612 break;
@@ -3529,11 +3678,11 @@ private:
3529 temp.push_back(indent() + "end"s + nlr(x)); 3678 temp.push_back(indent() + "end"s + nlr(x));
3530 break; 3679 break;
3531 case ExpUsage::Closure: 3680 case ExpUsage::Closure:
3532 _enableReturn.pop();
3533 popScope(); 3681 popScope();
3534 *funcStart = anonFuncStart() + nll(x); 3682 *funcStart = anonFuncStart() + nll(x);
3535 temp.push_back(indent() + anonFuncEnd()); 3683 temp.push_back(indent() + anonFuncEnd());
3536 popAnonVarArg(); 3684 popAnonVarArg();
3685 _enableReturn.pop();
3537 break; 3686 break;
3538 default: 3687 default:
3539 break; 3688 break;
@@ -4263,8 +4412,8 @@ private:
4263 switch (usage) { 4412 switch (usage) {
4264 case ExpUsage::Closure: 4413 case ExpUsage::Closure:
4265 _enableReturn.push(true); 4414 _enableReturn.push(true);
4266 pushScope();
4267 pushAnonVarArg(); 4415 pushAnonVarArg();
4416 pushScope();
4268 break; 4417 break;
4269 case ExpUsage::Assignment: 4418 case ExpUsage::Assignment:
4270 pushScope(); 4419 pushScope();
@@ -4320,13 +4469,13 @@ private:
4320 case ExpUsage::Common: 4469 case ExpUsage::Common:
4321 break; 4470 break;
4322 case ExpUsage::Closure: { 4471 case ExpUsage::Closure: {
4323 _enableReturn.pop();
4324 out.push_back(clearBuf()); 4472 out.push_back(clearBuf());
4325 out.back().append(indent() + "return "s + accumVar + nlr(comp)); 4473 out.back().append(indent() + "return "s + accumVar + nlr(comp));
4326 popScope(); 4474 popScope();
4327 out.back().insert(0, anonFuncStart() + nll(comp)); 4475 out.back().insert(0, anonFuncStart() + nll(comp));
4328 out.back().append(indent() + anonFuncEnd()); 4476 out.back().append(indent() + anonFuncEnd());
4329 popAnonVarArg(); 4477 popAnonVarArg();
4478 _enableReturn.pop();
4330 break; 4479 break;
4331 } 4480 }
4332 case ExpUsage::Assignment: { 4481 case ExpUsage::Assignment: {
@@ -4352,11 +4501,12 @@ private:
4352 } 4501 }
4353 } 4502 }
4354 4503
4355 void transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out) { 4504 bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool isStatement = false) {
4356 auto x = nameList; 4505 auto x = nameList;
4357 str_list temp; 4506 str_list temp;
4358 str_list vars; 4507 str_list vars;
4359 str_list varBefore, varAfter; 4508 str_list varBefore, varAfter;
4509 bool extraScope = false;
4360 std::list<std::pair<ast_node*, ast_ptr<false, ast_node>>> destructPairs; 4510 std::list<std::pair<ast_node*, ast_ptr<false, ast_node>>> destructPairs;
4361 for (auto _item : nameList->items.objects()) { 4511 for (auto _item : nameList->items.objects()) {
4362 auto item = static_cast<NameOrDestructure_t*>(_item)->item.get(); 4512 auto item = static_cast<NameOrDestructure_t*>(_item)->item.get();
@@ -4422,16 +4572,28 @@ private:
4422 temp.pop_back(); 4572 temp.pop_back();
4423 } 4573 }
4424 if (listVar.empty()) { 4574 if (listVar.empty()) {
4575 std::string prefix;
4576 if (isStatement) {
4577 extraScope = true;
4578 prefix = indent() + "do"s + nll(x);
4579 pushScope();
4580 }
4425 listVar = getUnusedName("_list_"sv); 4581 listVar = getUnusedName("_list_"sv);
4426 varBefore.push_back(listVar); 4582 varBefore.push_back(listVar);
4427 transformChainValue(chain, temp, ExpUsage::Closure); 4583 transformChainValue(chain, temp, ExpUsage::Closure);
4428 _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); 4584 _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList);
4429 } 4585 }
4430 std::string maxVar; 4586 std::string maxVar;
4431 if (!stopValue.empty()) { 4587 if (!stopValue.empty()) {
4588 std::string prefix;
4589 if (isStatement && !extraScope) {
4590 extraScope = true;
4591 prefix = indent() + "do"s + nll(x);
4592 pushScope();
4593 }
4432 maxVar = getUnusedName("_max_"sv); 4594 maxVar = getUnusedName("_max_"sv);
4433 varBefore.push_back(maxVar); 4595 varBefore.push_back(maxVar);
4434 _buf << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); 4596 _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList);
4435 } 4597 }
4436 _buf << indent() << "for "sv << indexVar << " = "sv; 4598 _buf << indent() << "for "sv << indexVar << " = "sv;
4437 _buf << startValue << ", "sv; 4599 _buf << startValue << ", "sv;
@@ -4497,6 +4659,7 @@ private:
4497 } 4659 }
4498 out.back().append(join(temp)); 4660 out.back().append(join(temp));
4499 } 4661 }
4662 return extraScope;
4500 } 4663 }
4501 4664
4502 void transformCompForEach(CompForEach_t* comp, str_list& out) { 4665 void transformCompForEach(CompForEach_t* comp, str_list& out) {
@@ -4651,17 +4814,17 @@ private:
4651 4814
4652 void transformForClosure(For_t* forNode, str_list& out) { 4815 void transformForClosure(For_t* forNode, str_list& out) {
4653 str_list temp; 4816 str_list temp;
4817 _enableReturn.push(true);
4654 pushAnonVarArg(); 4818 pushAnonVarArg();
4655 std::string& funcStart = temp.emplace_back(); 4819 std::string& funcStart = temp.emplace_back();
4656 pushScope(); 4820 pushScope();
4657 _enableReturn.push(true);
4658 auto accum = transformForInner(forNode, temp); 4821 auto accum = transformForInner(forNode, temp);
4659 temp.push_back(indent() + "return "s + accum + nlr(forNode)); 4822 temp.push_back(indent() + "return "s + accum + nlr(forNode));
4660 _enableReturn.pop();
4661 popScope(); 4823 popScope();
4662 funcStart = anonFuncStart() + nll(forNode); 4824 funcStart = anonFuncStart() + nll(forNode);
4663 temp.push_back(indent() + anonFuncEnd()); 4825 temp.push_back(indent() + anonFuncEnd());
4664 popAnonVarArg(); 4826 popAnonVarArg();
4827 _enableReturn.pop();
4665 out.push_back(join(temp)); 4828 out.push_back(join(temp));
4666 } 4829 }
4667 4830
@@ -4697,10 +4860,14 @@ private:
4697 4860
4698 void transformForEach(ForEach_t* forEach, str_list& out) { 4861 void transformForEach(ForEach_t* forEach, str_list& out) {
4699 str_list temp; 4862 str_list temp;
4700 transformForEachHead(forEach->nameList, forEach->loopValue, temp); 4863 bool extraScope = transformForEachHead(forEach->nameList, forEach->loopValue, temp, true);
4701 transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common); 4864 transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common);
4702 popScope(); 4865 popScope();
4703 out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); 4866 out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach));
4867 if (extraScope) {
4868 popScope();
4869 out.back().append(indent() + "end"s + nlr(forEach));
4870 }
4704 } 4871 }
4705 4872
4706 std::string transformForEachInner(ForEach_t* forEach, str_list& out) { 4873 std::string transformForEachInner(ForEach_t* forEach, str_list& out) {
@@ -4723,17 +4890,17 @@ private:
4723 4890
4724 void transformForEachClosure(ForEach_t* forEach, str_list& out) { 4891 void transformForEachClosure(ForEach_t* forEach, str_list& out) {
4725 str_list temp; 4892 str_list temp;
4893 _enableReturn.push(true);
4726 pushAnonVarArg(); 4894 pushAnonVarArg();
4727 std::string& funcStart = temp.emplace_back(); 4895 std::string& funcStart = temp.emplace_back();
4728 pushScope(); 4896 pushScope();
4729 _enableReturn.push(true);
4730 auto accum = transformForEachInner(forEach, temp); 4897 auto accum = transformForEachInner(forEach, temp);
4731 temp.push_back(indent() + "return "s + accum + nlr(forEach)); 4898 temp.push_back(indent() + "return "s + accum + nlr(forEach));
4732 _enableReturn.pop();
4733 popScope(); 4899 popScope();
4734 funcStart = anonFuncStart() + nll(forEach); 4900 funcStart = anonFuncStart() + nll(forEach);
4735 temp.push_back(indent() + anonFuncEnd()); 4901 temp.push_back(indent() + anonFuncEnd());
4736 popAnonVarArg(); 4902 popAnonVarArg();
4903 _enableReturn.pop();
4737 out.push_back(join(temp)); 4904 out.push_back(join(temp));
4738 } 4905 }
4739 4906
@@ -4878,16 +5045,16 @@ private:
4878 5045
4879 void transformClassDeclClosure(ClassDecl_t* classDecl, str_list& out) { 5046 void transformClassDeclClosure(ClassDecl_t* classDecl, str_list& out) {
4880 str_list temp; 5047 str_list temp;
5048 _enableReturn.push(true);
4881 pushAnonVarArg(); 5049 pushAnonVarArg();
4882 std::string& funcStart = temp.emplace_back(); 5050 std::string& funcStart = temp.emplace_back();
4883 pushScope(); 5051 pushScope();
4884 _enableReturn.push(true);
4885 transformClassDecl(classDecl, temp, ExpUsage::Return); 5052 transformClassDecl(classDecl, temp, ExpUsage::Return);
4886 _enableReturn.pop();
4887 popScope(); 5053 popScope();
4888 funcStart = anonFuncStart() + nll(classDecl); 5054 funcStart = anonFuncStart() + nll(classDecl);
4889 temp.push_back(indent() + anonFuncEnd()); 5055 temp.push_back(indent() + anonFuncEnd());
4890 popAnonVarArg(); 5056 popAnonVarArg();
5057 _enableReturn.pop();
4891 out.push_back(join(temp)); 5058 out.push_back(join(temp));
4892 } 5059 }
4893 5060
@@ -5256,16 +5423,16 @@ private:
5256 5423
5257 void transformWithClosure(With_t* with, str_list& out) { 5424 void transformWithClosure(With_t* with, str_list& out) {
5258 str_list temp; 5425 str_list temp;
5426 _enableReturn.push(true);
5259 pushAnonVarArg(); 5427 pushAnonVarArg();
5260 std::string& funcStart = temp.emplace_back(); 5428 std::string& funcStart = temp.emplace_back();
5261 pushScope(); 5429 pushScope();
5262 _enableReturn.push(true);
5263 transformWith(with, temp, nullptr, true); 5430 transformWith(with, temp, nullptr, true);
5264 _enableReturn.pop();
5265 popScope(); 5431 popScope();
5266 funcStart = anonFuncStart() + nll(with); 5432 funcStart = anonFuncStart() + nll(with);
5267 temp.push_back(indent() + anonFuncEnd()); 5433 temp.push_back(indent() + anonFuncEnd());
5268 popAnonVarArg(); 5434 popAnonVarArg();
5435 _enableReturn.pop();
5269 out.push_back(join(temp)); 5436 out.push_back(join(temp));
5270 } 5437 }
5271 5438
@@ -5674,9 +5841,9 @@ private:
5674 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 5841 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
5675 switch (usage) { 5842 switch (usage) {
5676 case ExpUsage::Closure: 5843 case ExpUsage::Closure:
5677 pushScope();
5678 _enableReturn.push(true); 5844 _enableReturn.push(true);
5679 pushAnonVarArg(); 5845 pushAnonVarArg();
5846 pushScope();
5680 break; 5847 break;
5681 case ExpUsage::Assignment: 5848 case ExpUsage::Assignment:
5682 pushScope(); 5849 pushScope();
@@ -5733,10 +5900,10 @@ private:
5733 case ExpUsage::Closure: 5900 case ExpUsage::Closure:
5734 out.push_back(clearBuf() + indent() + "return "s + tbl + nlr(comp)); 5901 out.push_back(clearBuf() + indent() + "return "s + tbl + nlr(comp));
5735 popScope(); 5902 popScope();
5736 _enableReturn.pop();
5737 out.back().insert(0, anonFuncStart() + nll(comp)); 5903 out.back().insert(0, anonFuncStart() + nll(comp));
5738 out.back().append(indent() + anonFuncEnd()); 5904 out.back().append(indent() + anonFuncEnd());
5739 popAnonVarArg(); 5905 popAnonVarArg();
5906 _enableReturn.pop();
5740 break; 5907 break;
5741 case ExpUsage::Assignment: { 5908 case ExpUsage::Assignment: {
5742 out.push_back(clearBuf()); 5909 out.push_back(clearBuf());
@@ -5802,10 +5969,10 @@ private:
5802 transformBody(doNode->body, temp, usage, assignList); 5969 transformBody(doNode->body, temp, usage, assignList);
5803 popScope(); 5970 popScope();
5804 if (usage == ExpUsage::Closure) { 5971 if (usage == ExpUsage::Closure) {
5805 _enableReturn.pop();
5806 *funcStart = anonFuncStart() + nll(doNode); 5972 *funcStart = anonFuncStart() + nll(doNode);
5807 temp.push_back(indent() + anonFuncEnd()); 5973 temp.push_back(indent() + anonFuncEnd());
5808 popAnonVarArg(); 5974 popAnonVarArg();
5975 _enableReturn.pop();
5809 } else { 5976 } else {
5810 temp.push_back(indent() + "end"s + nlr(doNode)); 5977 temp.push_back(indent() + "end"s + nlr(doNode));
5811 } 5978 }
@@ -6111,10 +6278,10 @@ private:
6111 void transformWhileClosure(While_t* whileNode, str_list& out) { 6278 void transformWhileClosure(While_t* whileNode, str_list& out) {
6112 auto x = whileNode; 6279 auto x = whileNode;
6113 str_list temp; 6280 str_list temp;
6281 _enableReturn.push(true);
6114 pushAnonVarArg(); 6282 pushAnonVarArg();
6115 std::string& funcStart = temp.emplace_back(); 6283 std::string& funcStart = temp.emplace_back();
6116 pushScope(); 6284 pushScope();
6117 _enableReturn.push(true);
6118 auto accumVar = getUnusedName("_accum_"sv); 6285 auto accumVar = getUnusedName("_accum_"sv);
6119 addToScope(accumVar); 6286 addToScope(accumVar);
6120 auto lenVar = getUnusedName("_len_"sv); 6287 auto lenVar = getUnusedName("_len_"sv);
@@ -6131,11 +6298,11 @@ private:
6131 popScope(); 6298 popScope();
6132 temp.push_back(indent() + "end"s + nlr(whileNode)); 6299 temp.push_back(indent() + "end"s + nlr(whileNode));
6133 temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); 6300 temp.push_back(indent() + "return "s + accumVar + nlr(whileNode));
6134 _enableReturn.pop();
6135 popScope(); 6301 popScope();
6136 funcStart = anonFuncStart() + nll(whileNode); 6302 funcStart = anonFuncStart() + nll(whileNode);
6137 temp.push_back(indent() + anonFuncEnd()); 6303 temp.push_back(indent() + anonFuncEnd());
6138 popAnonVarArg(); 6304 popAnonVarArg();
6305 _enableReturn.pop();
6139 out.push_back(join(temp)); 6306 out.push_back(join(temp));
6140 } 6307 }
6141 6308
@@ -6165,21 +6332,31 @@ private:
6165 } 6332 }
6166 6333
6167 void transformSwitch(Switch_t* switchNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 6334 void transformSwitch(Switch_t* switchNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
6335 auto x = switchNode;
6168 str_list temp; 6336 str_list temp;
6169 std::string* funcStart = nullptr; 6337 std::string* funcStart = nullptr;
6170 if (usage == ExpUsage::Closure) { 6338 if (usage == ExpUsage::Closure) {
6339 _enableReturn.push(true);
6171 pushAnonVarArg(); 6340 pushAnonVarArg();
6172 funcStart = &temp.emplace_back(); 6341 funcStart = &temp.emplace_back();
6173 pushScope(); 6342 pushScope();
6174 _enableReturn.push(true);
6175 } 6343 }
6344 bool extraScope = false;
6176 auto objVar = singleVariableFrom(switchNode->target); 6345 auto objVar = singleVariableFrom(switchNode->target);
6177 if (objVar.empty() || !isLocal(objVar)) { 6346 if (objVar.empty() || !isLocal(objVar)) {
6347 if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) {
6348 extraScope = true;
6349 temp.push_back(indent() + "do"s + nll(x));
6350 pushScope();
6351 }
6178 objVar = getUnusedName("_exp_"sv); 6352 objVar = getUnusedName("_exp_"sv);
6179 addToScope(objVar); 6353 auto expList = toAst<ExpList_t>(objVar, x);
6180 transformExp(switchNode->target, temp, ExpUsage::Closure); 6354 auto assign = x->new_ptr<Assign_t>();
6181 _buf << indent() << "local "sv << objVar << " = "sv << temp.back() << nll(switchNode); 6355 assign->values.push_back(switchNode->target);
6182 temp.back() = clearBuf(); 6356 auto assignment = x->new_ptr<ExpListAssign_t>();
6357 assignment->expList.set(expList);
6358 assignment->action.set(assign);
6359 transformAssignment(assignment, temp);
6183 } 6360 }
6184 const auto& branches = switchNode->branches.objects(); 6361 const auto& branches = switchNode->branches.objects();
6185 for (auto branch_ : branches) { 6362 for (auto branch_ : branches) {
@@ -6215,6 +6392,10 @@ private:
6215 temp.push_back(indent() + anonFuncEnd()); 6392 temp.push_back(indent() + anonFuncEnd());
6216 popAnonVarArg(); 6393 popAnonVarArg();
6217 } 6394 }
6395 if (extraScope) {
6396 popScope();
6397 temp.push_back(indent() + "end"s + nlr(switchNode));
6398 }
6218 out.push_back(join(temp)); 6399 out.push_back(join(temp));
6219 } 6400 }
6220 6401
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 6ecd369..5628062 100755
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -323,7 +323,8 @@ YueParser::YueParser() {
323 expr("&") | 323 expr("&") |
324 expr("|") | 324 expr("|") |
325 expr(">>") | 325 expr(">>") |
326 expr("<<"); 326 expr("<<") |
327 expr("??");
327 328
328 Update = Space >> update_op >> expr("=") >> Exp; 329 Update = Space >> update_op >> expr("=") >> Exp;
329 330
@@ -360,7 +361,7 @@ YueParser::YueParser() {
360 expr("//") | 361 expr("//") |
361 set("+-*/%><|&~"); 362 set("+-*/%><|&~");
362 exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> pipe_exp; 363 exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> pipe_exp;
363 Exp = Seperator >> pipe_exp >> *exp_op_value; 364 Exp = Seperator >> pipe_exp >> *exp_op_value >> -(Space >> expr("??") >> Exp);
364 365
365 DisableChain = pl::user(true_(), [](const item_t& item) { 366 DisableChain = pl::user(true_(), [](const item_t& item) {
366 State* st = reinterpret_cast<State*>(item.user_data); 367 State* st = reinterpret_cast<State*>(item.user_data);
@@ -424,7 +425,7 @@ YueParser::YueParser() {
424 Metatable = expr('#'); 425 Metatable = expr('#');
425 Metamethod = Name >> expr('#'); 426 Metamethod = Name >> expr('#');
426 427
427 existential_op = expr('?'); 428 existential_op = expr('?') >> not_(expr('?'));
428 chain_call = (Callable | String) >> -existential_op >> ChainItems; 429 chain_call = (Callable | String) >> -existential_op >> ChainItems;
429 chain_item = and_(set(".\\")) >> ChainItems; 430 chain_item = and_(set(".\\")) >> ChainItems;
430 chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; 431 chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems;