aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2024-09-29 16:45:06 +0800
committerLi Jin <dragon-fly@qq.com>2024-09-29 16:46:51 +0800
commit6af288657f5a7c43570ffbe91e1b727a4af5362d (patch)
tree72f0cb77d3fec4e6d6ab413c112278887ed44d3f
parentd6d29a4288b96d42c7cabf424beb286bfbd24456 (diff)
downloadyuescript-6af288657f5a7c43570ffbe91e1b727a4af5362d.tar.gz
yuescript-6af288657f5a7c43570ffbe91e1b727a4af5362d.tar.bz2
yuescript-6af288657f5a7c43570ffbe91e1b727a4af5362d.zip
Disallowed some semantically incorrect syntax to improve code consistency.
-rw-r--r--spec/inputs/upvalue_func.yue13
-rw-r--r--spec/outputs/5.1/attrib.lua144
-rw-r--r--src/yuescript/ast.cpp4
-rw-r--r--src/yuescript/parser.cpp6
-rw-r--r--src/yuescript/parser.hpp4
-rw-r--r--src/yuescript/yue_ast.h2
-rw-r--r--src/yuescript/yue_compiler.cpp58
-rw-r--r--src/yuescript/yue_parser.cpp2
8 files changed, 121 insertions, 112 deletions
diff --git a/spec/inputs/upvalue_func.yue b/spec/inputs/upvalue_func.yue
index d4b3273..378bf60 100644
--- a/spec/inputs/upvalue_func.yue
+++ b/spec/inputs/upvalue_func.yue
@@ -208,20 +208,21 @@ GameEngine\schedule (deltaTime) -> -- closure 1
208-- test cases from issue 208-- test cases from issue
209do 209do
210 buff_strength = (char, item) -> 210 buff_strength = (char, item) ->
211 item.buffer.strength? char.stats.strength?::ref() 211 item.buffer.strength? char.stats.strength?::ref!
212 212
213 local debug_env_before, debug_env_after 213 local debug_env_before, debug_env_after
214 214
215 exe_func = (func, env) -> 215 exe_func = (func, env) ->
216 ok, ... = try 216 ok, ... = try
217 debug_env_before(env) 217 debug_env_before env
218 func(env) 218 func env
219 debug_env_after(env) 219 debug_env_after env
220 catch ex 220 catch ex
221 -- accessing ex and error 221 -- accessing ex and error
222 error ex 222 error ex
223 return ex 223 -- implicit return
224 ex
224 if ok 225 if ok
225 return ... 226 return ...
226 else 227 else
227 os.exit(1) 228 os.exit 1
diff --git a/spec/outputs/5.1/attrib.lua b/spec/outputs/5.1/attrib.lua
index c48c72c..dc1285c 100644
--- a/spec/outputs/5.1/attrib.lua
+++ b/spec/outputs/5.1/attrib.lua
@@ -44,18 +44,6 @@ do
44 } 44 }
45 a, b = _obj_0[1], _obj_0[2] 45 a, b = _obj_0[1], _obj_0[2]
46end 46end
47local _anon_func_0 = function(_close_1, error, f, _arg_0, ...)
48 do
49 local _ok_0 = _arg_0
50 _close_1(f)
51 if _ok_0 then
52 return ...
53 else
54 return error(...)
55 end
56 end
57end
58local _anon_func_1 = function() end
59do 47do
60 local v 48 local v
61 if flag then 49 if flag then
@@ -82,28 +70,17 @@ do
82 f = _with_0 70 f = _with_0
83 end 71 end
84 local _close_1 = assert(getmetatable(f).__close) 72 local _close_1 = assert(getmetatable(f).__close)
85 return _anon_func_0(_close_1, error, f, pcall(_anon_func_1)) 73 return (function(_arg_0, ...)
74 local _ok_0 = _arg_0
75 _close_1(f)
76 if _ok_0 then
77 return ...
78 else
79 return error(...)
80 end
81 end)(pcall(function() end))
86 end)) 82 end))
87end 83end
88local _anon_func_2 = function(_close_1, d, error, _arg_0, ...)
89 do
90 local _ok_0 = _arg_0
91 _close_1(d)
92 if _ok_0 then
93 return ...
94 else
95 return error(...)
96 end
97 end
98end
99local _anon_func_3 = function(a, b)
100 if a ~= nil then
101 return a
102 else
103 return b
104 end
105end
106local _anon_func_4 = function() end
107do 84do
108 local a 85 local a
109 if true then 86 if true then
@@ -133,37 +110,29 @@ do
133 end 110 end
134 end 111 end
135 local d 112 local d
136 if _anon_func_3(a, b) then 113 if (function()
114 if a ~= nil then
115 return a
116 else
117 return b
118 end
119 end)() then
137 d = { 120 d = {
138 value = value 121 value = value
139 } 122 }
140 end 123 end
141 local _close_1 = assert(getmetatable(d).__close) 124 local _close_1 = assert(getmetatable(d).__close)
142 return _anon_func_2(_close_1, d, error, pcall(_anon_func_4)) 125 return (function(_arg_0, ...)
126 local _ok_0 = _arg_0
127 _close_1(d)
128 if _ok_0 then
129 return ...
130 else
131 return error(...)
132 end
133 end)(pcall(function() end))
143 end)) 134 end))
144end 135end
145local _anon_func_5 = function(_, _close_1, error, _arg_0, ...)
146 do
147 local _ok_0 = _arg_0
148 _close_1(_)
149 if _ok_0 then
150 return ...
151 else
152 return error(...)
153 end
154 end
155end
156local _anon_func_6 = function(_, _close_2, error, _arg_0, ...)
157 do
158 local _ok_0 = _arg_0
159 _close_2(_)
160 if _ok_0 then
161 return ...
162 else
163 return error(...)
164 end
165 end
166end
167do 136do
168 local _ 137 local _
169 do 138 do
@@ -187,14 +156,30 @@ do
187 end 156 end
188 }) 157 })
189 local _close_1 = assert(getmetatable(_).__close) 158 local _close_1 = assert(getmetatable(_).__close)
190 return _anon_func_5(_, _close_1, error, pcall(function() 159 return (function(_arg_0, ...)
160 local _ok_0 = _arg_0
161 _close_1(_)
162 if _ok_0 then
163 return ...
164 else
165 return error(...)
166 end
167 end)(pcall(function()
191 local _ = setmetatable({ }, { 168 local _ = setmetatable({ }, {
192 __close = function() 169 __close = function()
193 return print("first") 170 return print("first")
194 end 171 end
195 }) 172 })
196 local _close_2 = assert(getmetatable(_).__close) 173 local _close_2 = assert(getmetatable(_).__close)
197 return _anon_func_6(_, _close_2, error, pcall(function() 174 return (function(_arg_0, ...)
175 local _ok_0 = _arg_0
176 _close_2(_)
177 if _ok_0 then
178 return ...
179 else
180 return error(...)
181 end
182 end)(pcall(function()
198 return print("third") 183 return print("third")
199 end)) 184 end))
200 end)) 185 end))
@@ -211,29 +196,6 @@ def = function(item)
211 _defers[#_defers + 1] = item 196 _defers[#_defers + 1] = item
212 return _defers 197 return _defers
213end 198end
214local _anon_func_7 = function(_, _close_1, error, _arg_0, ...)
215 do
216 local _ok_0 = _arg_0
217 _close_1(_)
218 if _ok_0 then
219 return ...
220 else
221 return error(...)
222 end
223 end
224end
225local _anon_func_8 = function(_, _close_2, error, _arg_0, ...)
226 do
227 local _ok_0 = _arg_0
228 _close_2(_)
229 if _ok_0 then
230 return ...
231 else
232 return error(...)
233 end
234 end
235end
236local _anon_func_9 = function() end
237do 199do
238 local _ = def(function() 200 local _ = def(function()
239 return print(3) 201 return print(3)
@@ -252,12 +214,28 @@ do
252 return print(2) 214 return print(2)
253 end) 215 end)
254 local _close_1 = assert(getmetatable(_).__close) 216 local _close_1 = assert(getmetatable(_).__close)
255 return _anon_func_7(_, _close_1, error, pcall(function() 217 return (function(_arg_0, ...)
218 local _ok_0 = _arg_0
219 _close_1(_)
220 if _ok_0 then
221 return ...
222 else
223 return error(...)
224 end
225 end)(pcall(function()
256 local _ = def(function() 226 local _ = def(function()
257 return print(1) 227 return print(1)
258 end) 228 end)
259 local _close_2 = assert(getmetatable(_).__close) 229 local _close_2 = assert(getmetatable(_).__close)
260 return _anon_func_8(_, _close_2, error, pcall(_anon_func_9)) 230 return (function(_arg_0, ...)
231 local _ok_0 = _arg_0
232 _close_2(_)
233 if _ok_0 then
234 return ...
235 else
236 return error(...)
237 end
238 end)(pcall(function() end))
261 end)) 239 end))
262 end)) 240 end))
263end 241end
diff --git a/src/yuescript/ast.cpp b/src/yuescript/ast.cpp
index 2bdac81..99ab8f5 100644
--- a/src/yuescript/ast.cpp
+++ b/src/yuescript/ast.cpp
@@ -54,8 +54,8 @@ bool ast_node::visit_child(const std::function<bool(ast_node*)>&) {
54*/ 54*/
55void ast_container::construct(ast_stack& st) { 55void ast_container::construct(ast_stack& st) {
56 for (ast_member_vector::reverse_iterator it = m_members.rbegin(); 56 for (ast_member_vector::reverse_iterator it = m_members.rbegin();
57 it != m_members.rend(); 57 it != m_members.rend();
58 ++it) { 58 ++it) {
59 ast_member* member = *it; 59 ast_member* member = *it;
60 member->construct(st); 60 member->construct(st);
61 } 61 }
diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp
index 5d0773c..f0ddd06 100644
--- a/src/yuescript/parser.cpp
+++ b/src/yuescript/parser.cpp
@@ -160,8 +160,8 @@ public:
160 // execute all the parse procs 160 // execute all the parse procs
161 void do_parse_procs(void* d) const { 161 void do_parse_procs(void* d) const {
162 for (_match_vector::const_iterator it = m_matches.begin(); 162 for (_match_vector::const_iterator it = m_matches.begin();
163 it != m_matches.end(); 163 it != m_matches.end();
164 ++it) { 164 ++it) {
165 const _match& m = *it; 165 const _match& m = *it;
166 parse_proc p = _private::get_parse_proc(*m.m_rule); 166 parse_proc p = _private::get_parse_proc(*m.m_rule);
167 p(m.m_begin, m.m_end, d); 167 p(m.m_begin, m.m_end, d);
@@ -262,7 +262,7 @@ private:
262 bool _parse(_context& con) const { 262 bool _parse(_context& con) const {
263 for (auto it = m_string.begin(), 263 for (auto it = m_string.begin(),
264 end = m_string.end(); 264 end = m_string.end();
265 ;) { 265 ;) {
266 if (it == end) return true; 266 if (it == end) return true;
267 if (con.end()) break; 267 if (con.end()) break;
268 if (con.symbol() != *it) break; 268 if (con.symbol() != *it) break;
diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp
index 5ab327f..c544785 100644
--- a/src/yuescript/parser.hpp
+++ b/src/yuescript/parser.hpp
@@ -433,8 +433,8 @@ bool start_with(input& i, rule& g, error_list& el, void* st, void* ud);
433template <class T> 433template <class T>
434T& operator<<(T& stream, const input_range& ir) { 434T& operator<<(T& stream, const input_range& ir) {
435 for (input::const_iterator it = ir.m_begin.m_it; 435 for (input::const_iterator it = ir.m_begin.m_it;
436 it != ir.m_end.m_it; 436 it != ir.m_end.m_it;
437 ++it) { 437 ++it) {
438 stream << (typename T::char_type) * it; 438 stream << (typename T::char_type) * it;
439 } 439 }
440 return stream; 440 return stream;
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index cffc92d..8063517 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -277,6 +277,7 @@ AST_END(ExpList)
277 277
278AST_NODE(Return) 278AST_NODE(Return)
279 bool allowBlockMacroReturn = false; 279 bool allowBlockMacroReturn = false;
280 bool explicitReturn = true;
280 ast_sel<false, TableBlock_t, ExpListLow_t> valueList; 281 ast_sel<false, TableBlock_t, ExpListLow_t> valueList;
281 AST_MEMBER(Return, &valueList) 282 AST_MEMBER(Return, &valueList)
282AST_END(Return) 283AST_END(Return)
@@ -766,6 +767,7 @@ AST_NODE(FunLit)
766 ast_ptr<true, FnArrow_t> arrow; 767 ast_ptr<true, FnArrow_t> arrow;
767 ast_ptr<false, Body_t> body; 768 ast_ptr<false, Body_t> body;
768 bool noRecursion = false; 769 bool noRecursion = false;
770 bool isAnon = false;
769 AST_MEMBER(FunLit, &argsDef, &defaultReturn, &arrow, &body) 771 AST_MEMBER(FunLit, &argsDef, &defaultReturn, &arrow, &body)
770AST_END(FunLit) 772AST_END(FunLit)
771 773
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index b44b697..ef8e59e 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
75 "close"s // Lua 5.4 75 "close"s // Lua 5.4
76}; 76};
77 77
78const std::string_view version = "0.25.3"sv; 78const std::string_view version = "0.25.4"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -3777,6 +3777,7 @@ private:
3777 } 3777 }
3778 case ExpUsage::Return: { 3778 case ExpUsage::Return: {
3779 auto ret = x->new_ptr<Return_t>(); 3779 auto ret = x->new_ptr<Return_t>();
3780 ret->explicitReturn = false;
3780 auto expListLow = x->new_ptr<ExpListLow_t>(); 3781 auto expListLow = x->new_ptr<ExpListLow_t>();
3781 expListLow->exprs.push_back(arg); 3782 expListLow->exprs.push_back(arg);
3782 ret->valueList.set(expListLow); 3783 ret->valueList.set(expListLow);
@@ -4007,6 +4008,7 @@ private:
4007 auto expListLow = exp->new_ptr<ExpListLow_t>(); 4008 auto expListLow = exp->new_ptr<ExpListLow_t>();
4008 expListLow->exprs.push_back(e); 4009 expListLow->exprs.push_back(e);
4009 auto returnNode = exp->new_ptr<Return_t>(); 4010 auto returnNode = exp->new_ptr<Return_t>();
4011 returnNode->explicitReturn = false;
4010 returnNode->valueList.set(expListLow); 4012 returnNode->valueList.set(expListLow);
4011 transformReturn(returnNode, out); 4013 transformReturn(returnNode, out);
4012 break; 4014 break;
@@ -4039,7 +4041,7 @@ private:
4039 }) != traversal::Stop; 4041 }) != traversal::Stop;
4040 } 4042 }
4041 4043
4042 std::optional<std::pair<std::string, str_list>> getUpValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd, bool noGlobalVarPassing) { 4044 std::optional<std::pair<std::string, str_list>> getUpValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd, bool noGlobalVarPassing, bool blockRewrite) {
4043 if (_funcLevel <= 1) return std::nullopt; 4045 if (_funcLevel <= 1) return std::nullopt;
4044 auto result = block->traverse([&](ast_node* node) { 4046 auto result = block->traverse([&](ast_node* node) {
4045 switch (node->get_id()) { 4047 switch (node->get_id()) {
@@ -4138,6 +4140,7 @@ private:
4138 } 4140 }
4139 } 4141 }
4140 auto funLit = toAst<FunLit_t>("("s + join(args, ","sv) + ")-> nil"s, x); 4142 auto funLit = toAst<FunLit_t>("("s + join(args, ","sv) + ")-> nil"s, x);
4143 funLit->isAnon = blockRewrite ? false : true;
4141 funLit->body->content.set(newBlock); 4144 funLit->body->content.set(newBlock);
4142 funLit->noRecursion = true; 4145 funLit->noRecursion = true;
4143 auto simpleValue = x->new_ptr<SimpleValue_t>(); 4146 auto simpleValue = x->new_ptr<SimpleValue_t>();
@@ -4159,16 +4162,17 @@ private:
4159 return std::nullopt; 4162 return std::nullopt;
4160 } 4163 }
4161 4164
4162 std::optional<std::pair<std::string, str_list>> upValueFuncFrom(Block_t* block, str_list* ensureArgListInTheEnd = nullptr, bool noGlobalVarPassing = false) { 4165 std::optional<std::pair<std::string, str_list>> upValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd, bool noGlobalVarPassing, bool blockRewrite) {
4163 if (checkUpValueFuncAvailable(block)) { 4166 if (checkUpValueFuncAvailable(block)) {
4164 return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, noGlobalVarPassing); 4167 return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, noGlobalVarPassing, blockRewrite);
4165 } 4168 }
4166 return std::nullopt; 4169 return std::nullopt;
4167 } 4170 }
4168 4171
4169 std::optional<std::pair<std::string, str_list>> upValueFuncFrom(Exp_t* exp, str_list* ensureArgListInTheEnd = nullptr) { 4172 std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) {
4170 if (checkUpValueFuncAvailable(exp)) { 4173 if (checkUpValueFuncAvailable(exp)) {
4171 auto returnNode = exp->new_ptr<Return_t>(); 4174 auto returnNode = exp->new_ptr<Return_t>();
4175 returnNode->explicitReturn = false;
4172 auto returnList = exp->new_ptr<ExpListLow_t>(); 4176 auto returnList = exp->new_ptr<ExpListLow_t>();
4173 returnList->exprs.push_back(exp); 4177 returnList->exprs.push_back(exp);
4174 returnNode->valueList.set(returnList); 4178 returnNode->valueList.set(returnList);
@@ -4176,13 +4180,13 @@ private:
4176 auto stmt = exp->new_ptr<Statement_t>(); 4180 auto stmt = exp->new_ptr<Statement_t>();
4177 stmt->content.set(returnNode); 4181 stmt->content.set(returnNode);
4178 block->statements.push_back(stmt); 4182 block->statements.push_back(stmt);
4179 return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false); 4183 return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite);
4180 } 4184 }
4181 return std::nullopt; 4185 return std::nullopt;
4182 } 4186 }
4183 4187
4184 bool transformAsUpValueFunc(Exp_t* exp, str_list& out) { 4188 bool transformAsUpValueFunc(Exp_t* exp, str_list& out) {
4185 auto result = upValueFuncFrom(exp); 4189 auto result = upValueFuncFromExp(exp, nullptr, false);
4186 if (result) { 4190 if (result) {
4187 auto [funcName, args] = std::move(*result); 4191 auto [funcName, args] = std::move(*result);
4188 auto newChainValue = toAst<ChainValue_t>(funcName + '(' + join(args, ","sv) + ')', exp); 4192 auto newChainValue = toAst<ChainValue_t>(funcName + '(' + join(args, ","sv) + ')', exp);
@@ -4258,6 +4262,7 @@ private:
4258 _buf << indent() << "else"s << nll(x); 4262 _buf << indent() << "else"s << nll(x);
4259 temp.push_back(clearBuf()); 4263 temp.push_back(clearBuf());
4260 auto ret = x->new_ptr<Return_t>(); 4264 auto ret = x->new_ptr<Return_t>();
4265 ret->explicitReturn = false;
4261 auto retList = x->new_ptr<ExpListLow_t>(); 4266 auto retList = x->new_ptr<ExpListLow_t>();
4262 retList->exprs.push_back(exp->nilCoalesed); 4267 retList->exprs.push_back(exp->nilCoalesed);
4263 ret->valueList.set(retList); 4268 ret->valueList.set(retList);
@@ -4385,7 +4390,11 @@ private:
4385 } 4390 }
4386 4391
4387 void transformFunLit(FunLit_t* funLit, str_list& out) { 4392 void transformFunLit(FunLit_t* funLit, str_list& out) {
4388 pushUserFunctionScope(); 4393 if (funLit->isAnon) {
4394 pushAnonFunctionScope();
4395 } else {
4396 pushUserFunctionScope();
4397 }
4389 _varArgs.push({false, false}); 4398 _varArgs.push({false, false});
4390 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; 4399 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv;
4391 pushScope(); 4400 pushScope();
@@ -4419,6 +4428,7 @@ private:
4419 } 4428 }
4420 if (funLit->defaultReturn.is<ExpListLow_t>()) { 4429 if (funLit->defaultReturn.is<ExpListLow_t>()) {
4421 auto returnNode = newBlock->new_ptr<Return_t>(); 4430 auto returnNode = newBlock->new_ptr<Return_t>();
4431 returnNode->explicitReturn = false;
4422 returnNode->valueList.set(funLit->defaultReturn); 4432 returnNode->valueList.set(funLit->defaultReturn);
4423 auto stmt = newBlock->new_ptr<Statement_t>(); 4433 auto stmt = newBlock->new_ptr<Statement_t>();
4424 stmt->content.set(returnNode); 4434 stmt->content.set(returnNode);
@@ -4594,7 +4604,7 @@ private:
4594 transformBlock(newBlock, out, usage, assignList, isRoot); 4604 transformBlock(newBlock, out, usage, assignList, isRoot);
4595 return; 4605 return;
4596 } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>(); 4606 } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>();
4597 expListAssign && expListAssign->action && expListAssign->action.is<Assign_t>()) { 4607 expListAssign && expListAssign->action && expListAssign->action.is<Assign_t>()) {
4598 BLOCK_START 4608 BLOCK_START
4599 auto unary = singleUnaryExpFrom(expListAssign->expList->exprs.back()); 4609 auto unary = singleUnaryExpFrom(expListAssign->expList->exprs.back());
4600 BREAK_IF(!unary); 4610 BREAK_IF(!unary);
@@ -4693,7 +4703,7 @@ private:
4693 doNode->body.set(newBody); 4703 doNode->body.set(newBody);
4694 auto simpleValue = x->new_ptr<SimpleValue_t>(); 4704 auto simpleValue = x->new_ptr<SimpleValue_t>();
4695 simpleValue->value.set(doNode); 4705 simpleValue->value.set(doNode);
4696 if (auto result = upValueFuncFrom(newExp(simpleValue, x), &argNames)) { 4706 if (auto result = upValueFuncFromExp(newExp(simpleValue, x), &argNames, true)) {
4697 auto [funcName, args] = std::move(*result); 4707 auto [funcName, args] = std::move(*result);
4698 str_list finalArgs; 4708 str_list finalArgs;
4699 for (const auto& arg : args) { 4709 for (const auto& arg : args) {
@@ -4903,6 +4913,7 @@ private:
4903 auto expListLow = x->new_ptr<ExpListLow_t>(); 4913 auto expListLow = x->new_ptr<ExpListLow_t>();
4904 expListLow->exprs.dup(expList->exprs); 4914 expListLow->exprs.dup(expList->exprs);
4905 auto returnNode = x->new_ptr<Return_t>(); 4915 auto returnNode = x->new_ptr<Return_t>();
4916 returnNode->explicitReturn = false;
4906 returnNode->valueList.set(expListLow); 4917 returnNode->valueList.set(expListLow);
4907 returnNode->allowBlockMacroReturn = true; 4918 returnNode->allowBlockMacroReturn = true;
4908 last->content.set(returnNode); 4919 last->content.set(returnNode);
@@ -5258,6 +5269,11 @@ private:
5258 if (!target) target = returnNode; 5269 if (!target) target = returnNode;
5259 throw CompileError("can not mix use of return and export statements in module scope"sv, target); 5270 throw CompileError("can not mix use of return and export statements in module scope"sv, target);
5260 } 5271 }
5272 if (returnNode->explicitReturn && _funcStates.top().isAnon) {
5273 ast_node* target = returnNode->valueList.get();
5274 if (!target) target = returnNode;
5275 throw CompileError("explicit return statement is not allowed in this context"sv, target);
5276 }
5261 if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { 5277 if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) {
5262 if (valueList->exprs.size() == 1) { 5278 if (valueList->exprs.size() == 1) {
5263 auto exp = static_cast<Exp_t*>(valueList->exprs.back()); 5279 auto exp = static_cast<Exp_t*>(valueList->exprs.back());
@@ -5712,6 +5728,7 @@ private:
5712 case ExpUsage::Closure: { 5728 case ExpUsage::Closure: {
5713 auto exp = newExp(partTwo, x); 5729 auto exp = newExp(partTwo, x);
5714 auto ret = x->new_ptr<Return_t>(); 5730 auto ret = x->new_ptr<Return_t>();
5731 ret->explicitReturn = false;
5715 auto expListLow = x->new_ptr<ExpListLow_t>(); 5732 auto expListLow = x->new_ptr<ExpListLow_t>();
5716 expListLow->exprs.push_back(exp); 5733 expListLow->exprs.push_back(exp);
5717 ret->valueList.set(expListLow); 5734 ret->valueList.set(expListLow);
@@ -5810,6 +5827,7 @@ private:
5810 case ExpUsage::Closure: 5827 case ExpUsage::Closure:
5811 case ExpUsage::Return: { 5828 case ExpUsage::Return: {
5812 auto returnNode = x->new_ptr<Return_t>(); 5829 auto returnNode = x->new_ptr<Return_t>();
5830 returnNode->explicitReturn = false;
5813 auto expListLow = x->new_ptr<ExpListLow_t>(); 5831 auto expListLow = x->new_ptr<ExpListLow_t>();
5814 expListLow->exprs.push_back(funLit); 5832 expListLow->exprs.push_back(funLit);
5815 returnNode->valueList.set(expListLow); 5833 returnNode->valueList.set(expListLow);
@@ -5944,6 +5962,7 @@ private:
5944 switch (usage) { 5962 switch (usage) {
5945 case ExpUsage::Closure: { 5963 case ExpUsage::Closure: {
5946 auto returnNode = x->new_ptr<Return_t>(); 5964 auto returnNode = x->new_ptr<Return_t>();
5965 returnNode->explicitReturn = false;
5947 auto values = x->new_ptr<ExpListLow_t>(); 5966 auto values = x->new_ptr<ExpListLow_t>();
5948 values->exprs.push_back(newChainExp); 5967 values->exprs.push_back(newChainExp);
5949 returnNode->valueList.set(values); 5968 returnNode->valueList.set(values);
@@ -5957,6 +5976,7 @@ private:
5957 } 5976 }
5958 case ExpUsage::Return: { 5977 case ExpUsage::Return: {
5959 auto returnNode = x->new_ptr<Return_t>(); 5978 auto returnNode = x->new_ptr<Return_t>();
5979 returnNode->explicitReturn = false;
5960 auto values = x->new_ptr<ExpListLow_t>(); 5980 auto values = x->new_ptr<ExpListLow_t>();
5961 values->exprs.push_back(newChainExp); 5981 values->exprs.push_back(newChainExp);
5962 returnNode->valueList.set(values); 5982 returnNode->valueList.set(values);
@@ -6629,6 +6649,7 @@ private:
6629 auto expListLow = x->new_ptr<ExpListLow_t>(); 6649 auto expListLow = x->new_ptr<ExpListLow_t>();
6630 expListLow->exprs.push_back(node); 6650 expListLow->exprs.push_back(node);
6631 auto returnNode = x->new_ptr<Return_t>(); 6651 auto returnNode = x->new_ptr<Return_t>();
6652 returnNode->explicitReturn = false;
6632 returnNode->valueList.set(expListLow); 6653 returnNode->valueList.set(expListLow);
6633 transformReturn(returnNode, out); 6654 transformReturn(returnNode, out);
6634 break; 6655 break;
@@ -7612,6 +7633,7 @@ private:
7612 simpleValue->value.set(tableLit); 7633 simpleValue->value.set(tableLit);
7613 auto exp = newExp(simpleValue, x); 7634 auto exp = newExp(simpleValue, x);
7614 auto returnNode = x->new_ptr<Return_t>(); 7635 auto returnNode = x->new_ptr<Return_t>();
7636 returnNode->explicitReturn = false;
7615 auto expList = x->new_ptr<ExpListLow_t>(); 7637 auto expList = x->new_ptr<ExpListLow_t>();
7616 expList->exprs.push_back(exp); 7638 expList->exprs.push_back(exp);
7617 returnNode->valueList.set(expList); 7639 returnNode->valueList.set(expList);
@@ -8296,6 +8318,7 @@ private:
8296 } else { 8318 } else {
8297 auto accum = transformForInner(forNode, temp); 8319 auto accum = transformForInner(forNode, temp);
8298 auto returnNode = x->new_ptr<Return_t>(); 8320 auto returnNode = x->new_ptr<Return_t>();
8321 returnNode->explicitReturn = false;
8299 auto expListLow = toAst<ExpListLow_t>(accum, x); 8322 auto expListLow = toAst<ExpListLow_t>(accum, x);
8300 returnNode->valueList.set(expListLow); 8323 returnNode->valueList.set(expListLow);
8301 transformReturn(returnNode, temp); 8324 transformReturn(returnNode, temp);
@@ -8395,6 +8418,7 @@ private:
8395 } else { 8418 } else {
8396 auto accum = transformForEachInner(forEach, temp); 8419 auto accum = transformForEachInner(forEach, temp);
8397 auto returnNode = x->new_ptr<Return_t>(); 8420 auto returnNode = x->new_ptr<Return_t>();
8421 returnNode->explicitReturn = false;
8398 auto expListLow = toAst<ExpListLow_t>(accum, x); 8422 auto expListLow = toAst<ExpListLow_t>(accum, x);
8399 returnNode->valueList.set(expListLow); 8423 returnNode->valueList.set(expListLow);
8400 transformReturn(returnNode, temp); 8424 transformReturn(returnNode, temp);
@@ -9618,11 +9642,13 @@ private:
9618 auto x = tryNode; 9642 auto x = tryNode;
9619 ast_ptr<true, Exp_t> errHandler; 9643 ast_ptr<true, Exp_t> errHandler;
9620 if (tryNode->catchBlock) { 9644 if (tryNode->catchBlock) {
9621 auto errHandleStr = "("s + variableToString(tryNode->catchBlock->err) + ")->"s; 9645 auto catchBlock = tryNode->catchBlock.get();
9622 errHandler.set(toAst<Exp_t>(errHandleStr, x->func)); 9646 auto errHandleStr = "("s + variableToString(catchBlock->err) + ")->"s;
9647 errHandler.set(toAst<Exp_t>(errHandleStr, catchBlock));
9623 auto funLit = simpleSingleValueFrom(errHandler)->value.to<FunLit_t>(); 9648 auto funLit = simpleSingleValueFrom(errHandler)->value.to<FunLit_t>();
9624 auto body = x->new_ptr<Body_t>(); 9649 funLit->isAnon = true;
9625 body->content.set(tryNode->catchBlock->block); 9650 auto body = catchBlock->block->new_ptr<Body_t>();
9651 body->content.set(catchBlock->block);
9626 funLit->body.set(body); 9652 funLit->body.set(body);
9627 } 9653 }
9628 ast_sel<false, Block_t, Exp_t> tryFunc; 9654 ast_sel<false, Block_t, Exp_t> tryFunc;
@@ -9700,7 +9726,7 @@ private:
9700 } 9726 }
9701 if (auto tryBlock = tryFunc.as<Block_t>()) { 9727 if (auto tryBlock = tryFunc.as<Block_t>()) {
9702 if (getLuaTarget(tryBlock) >= 502 || !errHandler) { 9728 if (getLuaTarget(tryBlock) >= 502 || !errHandler) {
9703 if (auto result = upValueFuncFrom(tryBlock, nullptr, true)) { 9729 if (auto result = upValueFuncFromBlock(tryBlock, nullptr, true, false)) {
9704 auto [funcName, args] = std::move(*result); 9730 auto [funcName, args] = std::move(*result);
9705 if (errHandler) { 9731 if (errHandler) {
9706 auto xpcall = toAst<ChainValue_t>("xpcall()", x); 9732 auto xpcall = toAst<ChainValue_t>("xpcall()", x);
@@ -9729,6 +9755,7 @@ private:
9729 } 9755 }
9730 auto tryExp = toAst<Exp_t>("->"sv, x); 9756 auto tryExp = toAst<Exp_t>("->"sv, x);
9731 auto funLit = simpleSingleValueFrom(tryExp)->value.to<FunLit_t>(); 9757 auto funLit = simpleSingleValueFrom(tryExp)->value.to<FunLit_t>();
9758 funLit->isAnon = true;
9732 auto body = x->new_ptr<Body_t>(); 9759 auto body = x->new_ptr<Body_t>();
9733 body->content.set(tryBlock); 9760 body->content.set(tryBlock);
9734 funLit->body.set(body); 9761 funLit->body.set(body);
@@ -9762,6 +9789,7 @@ private:
9762 if (errHandler && getLuaTarget(x) < 502) { 9789 if (errHandler && getLuaTarget(x) < 502) {
9763 auto tryExp = toAst<Exp_t>("->"sv, x); 9790 auto tryExp = toAst<Exp_t>("->"sv, x);
9764 auto funLit = simpleSingleValueFrom(tryExp)->value.to<FunLit_t>(); 9791 auto funLit = simpleSingleValueFrom(tryExp)->value.to<FunLit_t>();
9792 funLit->isAnon = true;
9765 auto expList = x->new_ptr<ExpList_t>(); 9793 auto expList = x->new_ptr<ExpList_t>();
9766 expList->exprs.push_back(tryFunc); 9794 expList->exprs.push_back(tryFunc);
9767 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 9795 auto expListAssign = x->new_ptr<ExpListAssign_t>();
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 93787cd..d7af780 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -1167,7 +1167,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCo
1167 } 1167 }
1168 auto line = Converter{}.to_bytes(std::wstring(begin, end)); 1168 auto line = Converter{}.to_bytes(std::wstring(begin, end));
1169 while (col < static_cast<int>(line.size()) 1169 while (col < static_cast<int>(line.size())
1170 && (line[col] == ' ' || line[col] == '\t')) { 1170 && (line[col] == ' ' || line[col] == '\t')) {
1171 col++; 1171 col++;
1172 } 1172 }
1173 Utils::replace(line, "\t"sv, " "sv); 1173 Utils::replace(line, "\t"sv, " "sv);