diff options
| author | Li Jin <dragon-fly@qq.com> | 2024-09-29 16:45:06 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2024-09-29 16:46:51 +0800 |
| commit | 6af288657f5a7c43570ffbe91e1b727a4af5362d (patch) | |
| tree | 72f0cb77d3fec4e6d6ab413c112278887ed44d3f | |
| parent | d6d29a4288b96d42c7cabf424beb286bfbd24456 (diff) | |
| download | yuescript-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.yue | 13 | ||||
| -rw-r--r-- | spec/outputs/5.1/attrib.lua | 144 | ||||
| -rw-r--r-- | src/yuescript/ast.cpp | 4 | ||||
| -rw-r--r-- | src/yuescript/parser.cpp | 6 | ||||
| -rw-r--r-- | src/yuescript/parser.hpp | 4 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 2 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 58 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 2 |
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 |
| 209 | do | 209 | do |
| 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] |
| 46 | end | 46 | end |
| 47 | local _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 | ||
| 57 | end | ||
| 58 | local _anon_func_1 = function() end | ||
| 59 | do | 47 | do |
| 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)) |
| 87 | end | 83 | end |
| 88 | local _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 | ||
| 98 | end | ||
| 99 | local _anon_func_3 = function(a, b) | ||
| 100 | if a ~= nil then | ||
| 101 | return a | ||
| 102 | else | ||
| 103 | return b | ||
| 104 | end | ||
| 105 | end | ||
| 106 | local _anon_func_4 = function() end | ||
| 107 | do | 84 | do |
| 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)) |
| 144 | end | 135 | end |
| 145 | local _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 | ||
| 155 | end | ||
| 156 | local _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 | ||
| 166 | end | ||
| 167 | do | 136 | do |
| 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 |
| 213 | end | 198 | end |
| 214 | local _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 | ||
| 224 | end | ||
| 225 | local _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 | ||
| 235 | end | ||
| 236 | local _anon_func_9 = function() end | ||
| 237 | do | 199 | do |
| 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)) |
| 263 | end | 241 | end |
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 | */ |
| 55 | void ast_container::construct(ast_stack& st) { | 55 | void 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); | |||
| 433 | template <class T> | 433 | template <class T> |
| 434 | T& operator<<(T& stream, const input_range& ir) { | 434 | T& 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 | ||
| 278 | AST_NODE(Return) | 278 | AST_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) |
| 282 | AST_END(Return) | 283 | AST_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) |
| 770 | AST_END(FunLit) | 772 | AST_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 | ||
| 78 | const std::string_view version = "0.25.3"sv; | 78 | const std::string_view version = "0.25.4"sv; |
| 79 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
| 80 | 80 | ||
| 81 | class CompileError : public std::logic_error { | 81 | class 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); |
