aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/inputs/switch.yue14
-rw-r--r--spec/inputs/whitespace.yue47
-rw-r--r--spec/outputs/codes_from_doc_de.lua4
-rw-r--r--spec/outputs/codes_from_doc_en.lua4
-rw-r--r--spec/outputs/codes_from_doc_id-id.lua4
-rw-r--r--spec/outputs/codes_from_doc_pt-br.lua4
-rw-r--r--spec/outputs/codes_from_doc_zh.lua4
-rw-r--r--spec/outputs/macro.lua8
-rw-r--r--spec/outputs/metatable.lua2
-rw-r--r--spec/outputs/switch.lua44
-rw-r--r--spec/outputs/test/attrib_spec.lua4
-rw-r--r--spec/outputs/test/close_attribute_spec.lua2
-rw-r--r--spec/outputs/test/in_expression_spec.lua6
-rw-r--r--spec/outputs/test/tables_advanced_spec.lua2
-rw-r--r--spec/outputs/unicode/macro.lua8
-rw-r--r--spec/outputs/unicode/metatable.lua2
-rw-r--r--spec/outputs/whitespace.lua43
-rw-r--r--src/yuescript/ast.hpp3
-rw-r--r--src/yuescript/yue_ast.h2
-rw-r--r--src/yuescript/yue_compiler.cpp240
-rw-r--r--src/yuescript/yue_parser.cpp6
21 files changed, 330 insertions, 123 deletions
diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue
index 2b0669c..b969a17 100644
--- a/spec/inputs/switch.yue
+++ b/spec/inputs/switch.yue
@@ -289,4 +289,18 @@ do
289 289
290 handlePath ["admin", "logs", "view"] 290 handlePath ["admin", "logs", "view"]
291 291
292do
293 _check_cond_expr = (iftyp, n, args) ->
294 sw = { ct: iftyp, op: op }
295 why = switch sw
296 -- woo
297 when ct: 'if', op: '=='
298 'never'
299 when ct: 'if', op: '!='
300 'always'
301 when ct: 'unless', op: '=='
302 'always'
303 when ct: 'unless', op: '!='
304 'never'
305
292nil 306nil
diff --git a/spec/inputs/whitespace.yue b/spec/inputs/whitespace.yue
index a999143..d0acdde 100644
--- a/spec/inputs/whitespace.yue
+++ b/spec/inputs/whitespace.yue
@@ -198,5 +198,52 @@ do
198 -- two 198 -- two
199 b: -> -- 2 199 b: -> -- 2
200 200
201do
202 tb = {
203
204 -- hello
205 print 123
206 -- abc
207
208
209
210
211
212
213
214 abc: 1
215
216
217 -- xyz
218 c: ""
219
220
221 z: 998
222
223 <close>: ->
224
225 -- hello
226 <eq>: ->
227 --[[OK]] --[[OK]]--good
228 <call>: ->
229 }
230
231 class CY
232 -- init xa
233 xa = 1
234 -- init xb
235 local xb = 2
236
237 -- new
238 new: => print xa, xb, xc, xd
239
240
241 -- init xc
242 const xc = 3
243
244 -- wait
245
246 -- init xd
247 close xd = <close>: =>
201 248
202nil 249nil
diff --git a/spec/outputs/codes_from_doc_de.lua b/spec/outputs/codes_from_doc_de.lua
index 385dbae..70783f1 100644
--- a/spec/outputs/codes_from_doc_de.lua
+++ b/spec/outputs/codes_from_doc_de.lua
@@ -2820,7 +2820,7 @@ end), 0, function(a, b)
2820 return a + b 2820 return a + b
2821end)) 2821end))
2822local apple = setmetatable({ 2822local apple = setmetatable({
2823 size = 15, 2823 size = 15
2824}, { 2824}, {
2825 __index = { 2825 __index = {
2826 color = 0x00ffff 2826 color = 0x00ffff
@@ -2898,7 +2898,7 @@ end), 0, function(a, b)
2898 return a + b 2898 return a + b
2899end)) 2899end))
2900local apple = setmetatable({ 2900local apple = setmetatable({
2901 size = 15, 2901 size = 15
2902}, { 2902}, {
2903 __index = { 2903 __index = {
2904 color = 0x00ffff 2904 color = 0x00ffff
diff --git a/spec/outputs/codes_from_doc_en.lua b/spec/outputs/codes_from_doc_en.lua
index 2d9c8cf..4cfcaee 100644
--- a/spec/outputs/codes_from_doc_en.lua
+++ b/spec/outputs/codes_from_doc_en.lua
@@ -2820,7 +2820,7 @@ end), 0, function(a, b)
2820 return a + b 2820 return a + b
2821end)) 2821end))
2822local apple = setmetatable({ 2822local apple = setmetatable({
2823 size = 15, 2823 size = 15
2824}, { 2824}, {
2825 __index = { 2825 __index = {
2826 color = 0x00ffff 2826 color = 0x00ffff
@@ -2898,7 +2898,7 @@ end), 0, function(a, b)
2898 return a + b 2898 return a + b
2899end)) 2899end))
2900local apple = setmetatable({ 2900local apple = setmetatable({
2901 size = 15, 2901 size = 15
2902}, { 2902}, {
2903 __index = { 2903 __index = {
2904 color = 0x00ffff 2904 color = 0x00ffff
diff --git a/spec/outputs/codes_from_doc_id-id.lua b/spec/outputs/codes_from_doc_id-id.lua
index 7af01b7..a960fd6 100644
--- a/spec/outputs/codes_from_doc_id-id.lua
+++ b/spec/outputs/codes_from_doc_id-id.lua
@@ -2820,7 +2820,7 @@ end), 0, function(a, b)
2820 return a + b 2820 return a + b
2821end)) 2821end))
2822local apple = setmetatable({ 2822local apple = setmetatable({
2823 size = 15, 2823 size = 15
2824}, { 2824}, {
2825 __index = { 2825 __index = {
2826 color = 0x00ffff 2826 color = 0x00ffff
@@ -2898,7 +2898,7 @@ end), 0, function(a, b)
2898 return a + b 2898 return a + b
2899end)) 2899end))
2900local apple = setmetatable({ 2900local apple = setmetatable({
2901 size = 15, 2901 size = 15
2902}, { 2902}, {
2903 __index = { 2903 __index = {
2904 color = 0x00ffff 2904 color = 0x00ffff
diff --git a/spec/outputs/codes_from_doc_pt-br.lua b/spec/outputs/codes_from_doc_pt-br.lua
index dfe0108..d047596 100644
--- a/spec/outputs/codes_from_doc_pt-br.lua
+++ b/spec/outputs/codes_from_doc_pt-br.lua
@@ -2820,7 +2820,7 @@ end), 0, function(a, b)
2820 return a + b 2820 return a + b
2821end)) 2821end))
2822local apple = setmetatable({ 2822local apple = setmetatable({
2823 size = 15, 2823 size = 15
2824}, { 2824}, {
2825 __index = { 2825 __index = {
2826 color = 0x00ffff 2826 color = 0x00ffff
@@ -2898,7 +2898,7 @@ end), 0, function(a, b)
2898 return a + b 2898 return a + b
2899end)) 2899end))
2900local apple = setmetatable({ 2900local apple = setmetatable({
2901 size = 15, 2901 size = 15
2902}, { 2902}, {
2903 __index = { 2903 __index = {
2904 color = 0x00ffff 2904 color = 0x00ffff
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua
index 6db4a43..2065307 100644
--- a/spec/outputs/codes_from_doc_zh.lua
+++ b/spec/outputs/codes_from_doc_zh.lua
@@ -2820,7 +2820,7 @@ end), 0, function(a, b)
2820 return a + b 2820 return a + b
2821end)) 2821end))
2822local apple = setmetatable({ 2822local apple = setmetatable({
2823 size = 15, 2823 size = 15
2824}, { 2824}, {
2825 __index = { 2825 __index = {
2826 color = 0x00ffff 2826 color = 0x00ffff
@@ -2898,7 +2898,7 @@ end), 0, function(a, b)
2898 return a + b 2898 return a + b
2899end)) 2899end))
2900local apple = setmetatable({ 2900local apple = setmetatable({
2901 size = 15, 2901 size = 15
2902}, { 2902}, {
2903 __index = { 2903 __index = {
2904 color = 0x00ffff 2904 color = 0x00ffff
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua
index 89c6e63..91048e6 100644
--- a/spec/outputs/macro.lua
+++ b/spec/outputs/macro.lua
@@ -301,28 +301,28 @@ end):Destroy()
301end 301end
302print((setmetatable({ 302print((setmetatable({
303 'abc', 303 'abc',
304 a = 123, 304 a = 123
305}, { 305}, {
306 __call = function(self) 306 __call = function(self)
307 return 998 307 return 998
308 end 308 end
309}))[1], (setmetatable({ 309}))[1], (setmetatable({
310 'abc', 310 'abc',
311 a = 123, 311 a = 123
312}, { 312}, {
313 __call = function(self) 313 __call = function(self)
314 return 998 314 return 998
315 end 315 end
316})).a, (setmetatable({ 316})).a, (setmetatable({
317 'abc', 317 'abc',
318 a = 123, 318 a = 123
319}, { 319}, {
320 __call = function(self) 320 __call = function(self)
321 return 998 321 return 998
322 end 322 end
323}))(), setmetatable({ 323}))(), setmetatable({
324 'abc', 324 'abc',
325 a = 123, 325 a = 123
326}, { 326}, {
327 __call = function(self) 327 __call = function(self)
328 return 998 328 return 998
diff --git a/spec/outputs/metatable.lua b/spec/outputs/metatable.lua
index 974a6e4..eda5dee 100644
--- a/spec/outputs/metatable.lua
+++ b/spec/outputs/metatable.lua
@@ -1,5 +1,5 @@
1local a = setmetatable({ 1local a = setmetatable({
2 close = true, 2 close = true
3}, { 3}, {
4 __close = function(self) 4 __close = function(self)
5 return print("out of scope") 5 return print("out of scope")
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua
index 7c1004b..fb674e9 100644
--- a/spec/outputs/switch.lua
+++ b/spec/outputs/switch.lua
@@ -777,4 +777,48 @@ do
777 "view" 777 "view"
778 }) 778 })
779end 779end
780do
781 local _check_cond_expr
782 _check_cond_expr = function(iftyp, n, args)
783 local sw = {
784 ct = iftyp,
785 op = op
786 }
787 local why
788 local _type_0 = type(sw)
789 local _tab_0 = "table" == _type_0 or "userdata" == _type_0
790 local _match_0 = false
791 if _tab_0 then
792 if 'if' == sw.ct and '==' == sw.op then
793 _match_0 = true
794 why = 'never'
795 end
796 end
797 if not _match_0 then
798 local _match_1 = false
799 if _tab_0 then
800 if 'if' == sw.ct and '!=' == sw.op then
801 _match_1 = true
802 why = 'always'
803 end
804 end
805 if not _match_1 then
806 local _match_2 = false
807 if _tab_0 then
808 if 'unless' == sw.ct and '==' == sw.op then
809 _match_2 = true
810 why = 'always'
811 end
812 end
813 if not _match_2 then
814 if _tab_0 then
815 if 'unless' == sw.ct and '!=' == sw.op then
816 why = 'never'
817 end
818 end
819 end
820 end
821 end
822 end
823end
780return nil 824return nil
diff --git a/spec/outputs/test/attrib_spec.lua b/spec/outputs/test/attrib_spec.lua
index d459bbb..7408fa7 100644
--- a/spec/outputs/test/attrib_spec.lua
+++ b/spec/outputs/test/attrib_spec.lua
@@ -78,13 +78,13 @@ return describe("attrib", function()
78 local result 78 local result
79 if true then 79 if true then
80 result = setmetatable({ 80 result = setmetatable({
81 value = 42, 81 value = 42
82 }, { 82 }, {
83 __close = function() end 83 __close = function() end
84 }) 84 })
85 else 85 else
86 result = setmetatable({ 86 result = setmetatable({
87 value = 0, 87 value = 0
88 }, { 88 }, {
89 __close = function() end 89 __close = function() end
90 }) 90 })
diff --git a/spec/outputs/test/close_attribute_spec.lua b/spec/outputs/test/close_attribute_spec.lua
index cc64da8..40a3a0d 100644
--- a/spec/outputs/test/close_attribute_spec.lua
+++ b/spec/outputs/test/close_attribute_spec.lua
@@ -72,7 +72,7 @@ return describe("close attribute", function()
72 it("should work with fat arrow", function() 72 it("should work with fat arrow", function()
73 local closed = false 73 local closed = false
74 local obj = setmetatable({ 74 local obj = setmetatable({
75 value = 10, 75 value = 10
76 }, { 76 }, {
77 __close = function(self) 77 __close = function(self)
78 closed = true 78 closed = true
diff --git a/spec/outputs/test/in_expression_spec.lua b/spec/outputs/test/in_expression_spec.lua
index e5af45b..83c542c 100644
--- a/spec/outputs/test/in_expression_spec.lua
+++ b/spec/outputs/test/in_expression_spec.lua
@@ -341,19 +341,19 @@ return describe("in expression", function()
341 local nested = { 341 local nested = {
342 setmetatable({ 342 setmetatable({
343 1, 343 1,
344 2, 344 2
345 }, { 345 }, {
346 __eq = eq 346 __eq = eq
347 }), 347 }),
348 setmetatable({ 348 setmetatable({
349 3, 349 3,
350 4, 350 4
351 }, { 351 }, {
352 __eq = eq 352 __eq = eq
353 }), 353 }),
354 setmetatable({ 354 setmetatable({
355 5, 355 5,
356 6, 356 6
357 }, { 357 }, {
358 __eq = eq 358 __eq = eq
359 }) 359 })
diff --git a/spec/outputs/test/tables_advanced_spec.lua b/spec/outputs/test/tables_advanced_spec.lua
index de36953..9723313 100644
--- a/spec/outputs/test/tables_advanced_spec.lua
+++ b/spec/outputs/test/tables_advanced_spec.lua
@@ -214,7 +214,7 @@ return describe("advanced tables", function()
214 item = "test", 214 item = "test",
215 new = function() 215 new = function()
216 return "created" 216 return "created"
217 end, 217 end
218 }, { 218 }, {
219 __close = function() 219 __close = function()
220 return "closed" 220 return "closed"
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua
index b4e78cd..e7e3ada 100644
--- a/spec/outputs/unicode/macro.lua
+++ b/spec/outputs/unicode/macro.lua
@@ -319,28 +319,28 @@ end):_u6467_u6bc1()
319end 319end
320_u6253_u5370((setmetatable({ 320_u6253_u5370((setmetatable({
321 'abc', 321 'abc',
322 ["字段a"] = 123, 322 ["字段a"] = 123
323}, { 323}, {
324 __call = function(self) 324 __call = function(self)
325 return 998 325 return 998
326 end 326 end
327}))[1], (setmetatable({ 327}))[1], (setmetatable({
328 'abc', 328 'abc',
329 ["字段a"] = 123, 329 ["字段a"] = 123
330}, { 330}, {
331 __call = function(self) 331 __call = function(self)
332 return 998 332 return 998
333 end 333 end
334}))["字段a"], (setmetatable({ 334}))["字段a"], (setmetatable({
335 'abc', 335 'abc',
336 ["字段a"] = 123, 336 ["字段a"] = 123
337}, { 337}, {
338 __call = function(self) 338 __call = function(self)
339 return 998 339 return 998
340 end 340 end
341}))(), setmetatable({ 341}))(), setmetatable({
342 'abc', 342 'abc',
343 ["字段a"] = 123, 343 ["字段a"] = 123
344}, { 344}, {
345 __call = function(self) 345 __call = function(self)
346 return 998 346 return 998
diff --git a/spec/outputs/unicode/metatable.lua b/spec/outputs/unicode/metatable.lua
index 970e52c..4419634 100644
--- a/spec/outputs/unicode/metatable.lua
+++ b/spec/outputs/unicode/metatable.lua
@@ -1,5 +1,5 @@
1local _u53d8_u91cfa = setmetatable({ 1local _u53d8_u91cfa = setmetatable({
2 ["关闭"] = true, 2 ["关闭"] = true
3}, { 3}, {
4 __close = function(self) 4 __close = function(self)
5 return _u6253_u5370("离开作用域") 5 return _u6253_u5370("离开作用域")
diff --git a/spec/outputs/whitespace.lua b/spec/outputs/whitespace.lua
index 60e98bb..a0d225f 100644
--- a/spec/outputs/whitespace.lua
+++ b/spec/outputs/whitespace.lua
@@ -140,4 +140,47 @@ do
140 _base_0.__class = _class_0 140 _base_0.__class = _class_0
141 tb3 = _class_0 141 tb3 = _class_0
142end 142end
143do
144 local tb = setmetatable({
145 print(123),
146 abc = 1,
147 c = "",
148 z = 998
149 }, {
150 __close = function() end,
151 __eq = function() end,
152 __call = function() end
153 })
154 local CY
155 local _class_0
156 local xa, xb, xc, xd
157 local _base_0 = { }
158 if _base_0.__index == nil then
159 _base_0.__index = _base_0
160 end
161 _class_0 = setmetatable({
162 __init = function(self)
163 return print(xa, xb, xc, xd)
164 end,
165 __base = _base_0,
166 __name = "CY"
167 }, {
168 __index = _base_0,
169 __call = function(cls, ...)
170 local _self_0 = setmetatable({ }, _base_0)
171 cls.__init(_self_0, ...)
172 return _self_0
173 end
174 })
175 _base_0.__class = _class_0
176 local self = _class_0;
177 xa = 1
178 xb = 2
179 xc = 3
180 xd = setmetatable({ }, {
181 __close = function(self) end
182 })
183 local _close_0 <close> = xd
184 CY = _class_0
185end
143return nil 186return nil
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp
index d94caca..b3b0d23 100644
--- a/src/yuescript/ast.hpp
+++ b/src/yuescript/ast.hpp
@@ -13,6 +13,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13 13
14#include <cassert> 14#include <cassert>
15#include <list> 15#include <list>
16#include <deque>
16#include <stdexcept> 17#include <stdexcept>
17#include <string_view> 18#include <string_view>
18#include <type_traits> 19#include <type_traits>
@@ -34,7 +35,7 @@ class ast;
34/** type of AST node stack. 35/** type of AST node stack.
35 */ 36 */
36typedef std::vector<ast_node*> ast_stack; 37typedef std::vector<ast_node*> ast_stack;
37typedef std::list<ast_node*> node_container; 38typedef std::deque<ast_node*> node_container;
38 39
39template <size_t Num> 40template <size_t Num>
40struct Counter { 41struct Counter {
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 6919f7a..7d9a4a1 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -920,7 +920,7 @@ AST_NODE(BreakLoop)
920 ast_sel<true, Break_t, Continue_t> type; 920 ast_sel<true, Break_t, Continue_t> type;
921 ast_ptr<false, ExpList_t> valueList; 921 ast_ptr<false, ExpList_t> valueList;
922 AST_MEMBER(BreakLoop, &type, &valueList) 922 AST_MEMBER(BreakLoop, &type, &valueList)
923 std::list<std::string> vars; 923 std::deque<std::string> vars;
924AST_END(BreakLoop) 924AST_END(BreakLoop)
925 925
926AST_NODE(PipeBody) 926AST_NODE(PipeBody)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 7624d81..9f13098 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -65,7 +65,7 @@ namespace yue {
65 + ",\n[Error] "s + msg, \ 65 + ",\n[Error] "s + msg, \
66 node) 66 node)
67 67
68typedef std::list<std::string> str_list; 68typedef std::deque<std::string> str_list;
69 69
70static std::unordered_set<std::string> Metamethods = { 70static std::unordered_set<std::string> Metamethods = {
71 "add"s, "sub"s, "mul"s, "div"s, "mod"s, 71 "add"s, "sub"s, "mul"s, "div"s, "mod"s,
@@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = {
78 "close"s // Lua 5.4 78 "close"s // Lua 5.4
79}; 79};
80 80
81const std::string_view version = "0.33.3"sv; 81const std::string_view version = "0.33.4"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class CompileError : public std::logic_error {
@@ -1749,22 +1749,7 @@ private:
1749 out.push_back("\n"s); 1749 out.push_back("\n"s);
1750 return; 1750 return;
1751 } 1751 }
1752 str_list temp; 1752 out.push_back(indent() + comment->to_string(&_config) + '\n');
1753 for (auto node : comment->comments.objects()) {
1754 switch (node->get_id()) {
1755 case id<YueLineComment_t>(): {
1756 auto content = static_cast<YueLineComment_t*>(node);
1757 temp.emplace_back(indent() + "--"s + _parser.toString(content));
1758 break;
1759 }
1760 case id<YueMultilineComment_t>(): {
1761 auto content = static_cast<YueMultilineComment_t*>(node);
1762 temp.emplace_back(indent() + "--[["s + _parser.toString(content) + "]]"s);
1763 break;
1764 }
1765 }
1766 }
1767 out.push_back(join(temp, " "sv) + '\n');
1768 } 1753 }
1769 1754
1770 void transformStatement(Statement_t* statement, str_list& out) { 1755 void transformStatement(Statement_t* statement, str_list& out) {
@@ -4477,7 +4462,7 @@ private:
4477 for (const auto& arg : vars) { 4462 for (const auto& arg : vars) {
4478 finalArgs.push_back(arg); 4463 finalArgs.push_back(arg);
4479 } 4464 }
4480 finalArgs.sort(); 4465 std::sort(finalArgs.begin(), finalArgs.end());
4481 for (const auto& arg : *ensureArgListInTheEnd) { 4466 for (const auto& arg : *ensureArgListInTheEnd) {
4482 finalArgs.push_back(arg); 4467 finalArgs.push_back(arg);
4483 } 4468 }
@@ -4488,7 +4473,7 @@ private:
4488 } 4473 }
4489 args = std::move(finalArgs); 4474 args = std::move(finalArgs);
4490 } else { 4475 } else {
4491 args.sort(); 4476 std::sort(args.begin(), args.end());
4492 if (usedVar) { 4477 if (usedVar) {
4493 args.push_back("..."s); 4478 args.push_back("..."s);
4494 } 4479 }
@@ -8217,26 +8202,23 @@ private:
8217 auto x = values.front(); 8202 auto x = values.front();
8218 str_list temp; 8203 str_list temp;
8219 incIndentOffset(); 8204 incIndentOffset();
8220 auto metatable = x->new_ptr<SimpleTable_t>(); 8205 auto metatable = x->new_ptr<TableLit_t>();
8221 ast_sel<false, Exp_t, TableBlock_t> metatableItem; 8206 struct MetatableItem {
8222 ast_node* lastValueNode = values.back(); 8207 ast_sel<false, Exp_t, TableBlock_t> item;
8223 int lastValueLine = x->m_begin.m_line; 8208 std::vector<ast_node*> commentOrEmpty;
8224 bool prevWasEmptyLine = false; 8209 };
8225 if (!_config.reserveComment) { 8210 std::optional<MetatableItem> metatableItem;
8226 for (auto it = values.rbegin(); it != values.rend(); ++it) { 8211 std::vector<ast_node*> commentOrEmpty;
8227 auto node = *it; 8212 std::vector<ast_node*> tableItems;
8228 if (!ast_is<YueComment_t, EmptyLine_t>(node)) {
8229 lastValueNode = node;
8230 break;
8231 }
8232 }
8233 }
8234 for (auto value : values) { 8213 for (auto value : values) {
8235 if (!_config.reserveComment && ast_is<YueComment_t, EmptyLine_t>(value)) {
8236 continue;
8237 }
8238 auto item = value; 8214 auto item = value;
8239 switch (item->get_id()) { 8215 switch (item->get_id()) {
8216 case id<EmptyLine_t>():
8217 case id<YueComment_t>():
8218 if (_config.reserveComment) {
8219 commentOrEmpty.emplace_back(item);
8220 }
8221 break;
8240 case id<VariablePairDef_t>(): { 8222 case id<VariablePairDef_t>(): {
8241 auto pair = static_cast<VariablePairDef_t*>(item); 8223 auto pair = static_cast<VariablePairDef_t*>(item);
8242 if (pair->defVal) { 8224 if (pair->defVal) {
@@ -8278,29 +8260,8 @@ private:
8278 break; 8260 break;
8279 } 8261 }
8280 } 8262 }
8281 bool isMetamethod = false;
8282 bool skipComma = false;
8283 switch (item->get_id()) { 8263 switch (item->get_id()) {
8284 case id<Exp_t>(): transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); break;
8285 case id<YueComment_t>(): {
8286 if (_config.reserveComment && !prevWasEmptyLine && value->m_begin.m_line > lastValueLine + 1) {
8287 temp.emplace_back(Empty);
8288 }
8289 auto comment = static_cast<YueComment_t*>(item);
8290 temp.emplace_back(comment->to_string(&_config));
8291 skipComma = true;
8292 break;
8293 }
8294 case id<EmptyLine_t>():
8295 temp.emplace_back(Empty);
8296 skipComma = true;
8297 break;
8298 case id<VariablePair_t>(): transform_variable_pair(static_cast<VariablePair_t*>(item), temp); break;
8299 case id<NormalPair_t>(): transform_normal_pair(static_cast<NormalPair_t*>(item), temp, false); break;
8300 case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(item), temp); break;
8301 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(item), temp); break;
8302 case id<MetaVariablePair_t>(): { 8264 case id<MetaVariablePair_t>(): {
8303 isMetamethod = true;
8304 auto mp = static_cast<MetaVariablePair_t*>(item); 8265 auto mp = static_cast<MetaVariablePair_t*>(item);
8305 if (metatableItem) { 8266 if (metatableItem) {
8306 throw CompileError("too many metatable declarations"sv, mp->name); 8267 throw CompileError("too many metatable declarations"sv, mp->name);
@@ -8309,11 +8270,16 @@ private:
8309 checkMetamethod(name, mp->name); 8270 checkMetamethod(name, mp->name);
8310 _buf << "__"sv << name << ':' << name; 8271 _buf << "__"sv << name << ':' << name;
8311 auto newPair = toAst<NormalPair_t>(clearBuf(), item); 8272 auto newPair = toAst<NormalPair_t>(clearBuf(), item);
8312 metatable->pairs.push_back(newPair); 8273 if (!commentOrEmpty.empty()) {
8274 for (auto c : commentOrEmpty) {
8275 metatable->values.push_back(c);
8276 }
8277 commentOrEmpty.clear();
8278 }
8279 metatable->values.push_back(newPair);
8313 break; 8280 break;
8314 } 8281 }
8315 case id<MetaNormalPair_t>(): { 8282 case id<MetaNormalPair_t>(): {
8316 isMetamethod = true;
8317 auto mp = static_cast<MetaNormalPair_t*>(item); 8283 auto mp = static_cast<MetaNormalPair_t*>(item);
8318 auto newPair = item->new_ptr<NormalPair_t>(); 8284 auto newPair = item->new_ptr<NormalPair_t>();
8319 if (mp->key) { 8285 if (mp->key) {
@@ -8340,28 +8306,73 @@ private:
8340 default: YUEE("AST node mismatch", mp->key); break; 8306 default: YUEE("AST node mismatch", mp->key); break;
8341 } 8307 }
8342 newPair->value.set(mp->value); 8308 newPair->value.set(mp->value);
8343 metatable->pairs.push_back(newPair); 8309 if (!commentOrEmpty.empty()) {
8310 for (auto c : commentOrEmpty) {
8311 metatable->values.push_back(c);
8312 }
8313 commentOrEmpty.clear();
8314 }
8315 metatable->values.push_back(newPair);
8344 } else { 8316 } else {
8345 if (!metatable->pairs.empty()) { 8317 if (!metatable->values.empty()) {
8346 throw CompileError("too many metatable declarations"sv, mp->value); 8318 throw CompileError("too many metatable declarations"sv, mp->value);
8347 } 8319 }
8348 metatableItem.set(mp->value); 8320 metatableItem = MetatableItem{};
8321 if (!commentOrEmpty.empty()) {
8322 metatableItem.value().commentOrEmpty = std::move(commentOrEmpty);
8323 }
8324 metatableItem.value().item.set(mp->value);
8349 } 8325 }
8350 break; 8326 break;
8351 } 8327 }
8352 default: YUEE("AST node mismatch", item); break; 8328 case id<EmptyLine_t>():
8329 case id<YueComment_t>():
8330 break;
8331 default: {
8332 if (!commentOrEmpty.empty()) {
8333 for (auto c : commentOrEmpty) {
8334 tableItems.emplace_back(c);
8335 }
8336 commentOrEmpty.clear();
8337 }
8338 tableItems.emplace_back(item);
8339 break;
8340 }
8353 } 8341 }
8354 if (!isMetamethod) { 8342 }
8355 if (skipComma) { 8343
8356 temp.back() = indent() + temp.back() + '\n'; 8344 ast_node* lastValueNode = tableItems.empty() ? nullptr : tableItems.back();
8357 } else { 8345 for (auto* item : tableItems) {
8358 temp.back() = indent() + (value == lastValueNode ? temp.back() : temp.back() + ',') + nl(value); 8346 bool skipComma = false;
8347 switch (item->get_id()) {
8348 case id<Exp_t>(): {
8349 transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure);
8350 break;
8351 }
8352 case id<YueComment_t>(): {
8353 auto comment = static_cast<YueComment_t*>(item);
8354 temp.emplace_back(comment->to_string(&_config));
8355 skipComma = true;
8356 break;
8357 }
8358 case id<EmptyLine_t>(): {
8359 temp.emplace_back(Empty);
8360 skipComma = true;
8361 break;
8359 } 8362 }
8363 case id<VariablePair_t>(): transform_variable_pair(static_cast<VariablePair_t*>(item), temp); break;
8364 case id<NormalPair_t>(): transform_normal_pair(static_cast<NormalPair_t*>(item), temp, false); break;
8365 case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(item), temp); break;
8366 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(item), temp); break;
8367 default: YUEE("AST node mismatch", item); break;
8368 }
8369 if (skipComma) {
8370 temp.back() = indent() + temp.back() + '\n';
8371 } else {
8372 temp.back() = indent() + (item == lastValueNode ? temp.back() : temp.back() + ',') + nl(item);
8360 } 8373 }
8361 lastValueLine = value->m_end.m_line;
8362 prevWasEmptyLine = ast_is<EmptyLine_t>(value);
8363 } 8374 }
8364 if (metatable->pairs.empty() && !metatableItem) { 8375 if (metatable->values.empty() && !metatableItem) {
8365 out.push_back('{' + nl(x) + join(temp)); 8376 out.push_back('{' + nl(x) + join(temp));
8366 decIndentOffset(); 8377 decIndentOffset();
8367 out.back() += (indent() + '}'); 8378 out.back() += (indent() + '}');
@@ -8378,17 +8389,28 @@ private:
8378 } 8389 }
8379 tabStr += ", "sv; 8390 tabStr += ", "sv;
8380 str_list tmp; 8391 str_list tmp;
8381 if (!metatable->pairs.empty()) { 8392 if (metatableItem) {
8382 transform_simple_table(metatable, tmp); 8393 if (_config.reserveComment) {
8383 } else 8394 for (auto item : metatableItem.value().commentOrEmpty) {
8384 switch (metatableItem->get_id()) { 8395 if (ast_is<EmptyLine_t>(item)) {
8396 tmp.push_back("\n"s);
8397 } else {
8398 transformComment(ast_to<YueComment_t>(item), tmp);
8399 }
8400 }
8401 }
8402 auto mt = metatableItem.value().item.get();
8403 switch (mt->get_id()) {
8385 case id<Exp_t>(): 8404 case id<Exp_t>():
8386 transformExp(static_cast<Exp_t*>(metatableItem.get()), tmp, ExpUsage::Closure); 8405 transformExp(static_cast<Exp_t*>(mt), tmp, ExpUsage::Closure);
8387 break; 8406 break;
8388 case id<TableBlock_t>(): 8407 case id<TableBlock_t>():
8389 transformTableBlock(static_cast<TableBlock_t*>(metatableItem.get()), tmp); 8408 transformTableBlock(static_cast<TableBlock_t*>(mt), tmp);
8390 break; 8409 break;
8391 } 8410 }
8411 } else {
8412 transformTableLit(metatable, tmp);
8413 }
8392 tabStr += tmp.back(); 8414 tabStr += tmp.back();
8393 tabStr += ')'; 8415 tabStr += ')';
8394 out.push_back(tabStr); 8416 out.push_back(tabStr);
@@ -9817,8 +9839,19 @@ private:
9817 str_list classConstVars; 9839 str_list classConstVars;
9818 if (body) { 9840 if (body) {
9819 str_list varDefs; 9841 str_list varDefs;
9842 std::vector<ast_node*> commentOrEmpty;
9820 for (auto item : body->contents.objects()) { 9843 for (auto item : body->contents.objects()) {
9821 if (auto statement = ast_cast<Statement_t>(item)) { 9844 if (ast_is<YueComment_t, EmptyLine_t>(item)) {
9845 if (_config.reserveComment) {
9846 commentOrEmpty.emplace_back(item);
9847 }
9848 } else if (auto statement = ast_cast<Statement_t>(item)) {
9849 if (!commentOrEmpty.empty()) {
9850 for (auto c : commentOrEmpty) {
9851 block->statementOrComments.push_back(c);
9852 }
9853 commentOrEmpty.clear();
9854 }
9822 ClassDecl_t* clsDecl = nullptr; 9855 ClassDecl_t* clsDecl = nullptr;
9823 if (auto assignment = assignmentFrom(statement)) { 9856 if (auto assignment = assignmentFrom(statement)) {
9824 block->statementOrComments.push_back(statement); 9857 block->statementOrComments.push_back(statement);
@@ -9937,6 +9970,8 @@ private:
9937 std::tie(clsName, newDefined, clsTextName) = defineClassVariable(clsDecl->name); 9970 std::tie(clsName, newDefined, clsTextName) = defineClassVariable(clsDecl->name);
9938 if (newDefined) varDefs.push_back(clsName); 9971 if (newDefined) varDefs.push_back(clsName);
9939 } 9972 }
9973 } else {
9974 commentOrEmpty.clear();
9940 } 9975 }
9941 } 9976 }
9942 if (!varDefs.empty()) { 9977 if (!varDefs.empty()) {
@@ -9959,6 +9994,15 @@ private:
9959 std::list<ClassMemberEntry> builtinFields; 9994 std::list<ClassMemberEntry> builtinFields;
9960 std::list<ClassMemberEntry> classFields; 9995 std::list<ClassMemberEntry> classFields;
9961 std::list<ClassMemberEntry> commentOrEmpty; 9996 std::list<ClassMemberEntry> commentOrEmpty;
9997 auto appendCommentOrEmpty = [&](std::list<ClassMemberEntry>& target) {
9998 if (!commentOrEmpty.empty()) {
9999 for (auto& item : commentOrEmpty) {
10000 auto [content, newLine, isComment] = std::move(item);
10001 target.emplace_back(indent(1) + content, newLine, isComment);
10002 }
10003 commentOrEmpty.clear();
10004 }
10005 };
9962 str_list initStatements; 10006 str_list initStatements;
9963 if (body) { 10007 if (body) {
9964 std::list<ClassMember> members; 10008 std::list<ClassMember> members;
@@ -9971,18 +10015,19 @@ private:
9971 for (; it != members.end(); ++it) { 10015 for (; it != members.end(); ++it) {
9972 auto& member = *it; 10016 auto& member = *it;
9973 if (member.type == MemType::Property) { 10017 if (member.type == MemType::Property) {
9974 initStatements.push_back(indent() + member.item + nl(content));
9975 } else if (member.type == MemType::Builtin) {
9976 if (!commentOrEmpty.empty()) { 10018 if (!commentOrEmpty.empty()) {
9977 builtinFields.insert(builtinFields.end(), commentOrEmpty.begin(), commentOrEmpty.end()); 10019 for (auto& item : commentOrEmpty) {
10020 auto [content, newLine, _] = std::move(item);
10021 initStatements.emplace_back(indent() + content + newLine);
10022 }
9978 commentOrEmpty.clear(); 10023 commentOrEmpty.clear();
9979 } 10024 }
10025 initStatements.emplace_back(indent() + member.item + nl(content));
10026 } else if (member.type == MemType::Builtin) {
10027 appendCommentOrEmpty(builtinFields);
9980 builtinFields.emplace_back(indent(1) + member.item, nl(member.node), false); 10028 builtinFields.emplace_back(indent(1) + member.item, nl(member.node), false);
9981 } else { 10029 } else {
9982 if (!commentOrEmpty.empty()) { 10030 appendCommentOrEmpty(classFields);
9983 classFields.insert(classFields.end(), commentOrEmpty.begin(), commentOrEmpty.end());
9984 commentOrEmpty.clear();
9985 }
9986 classFields.emplace_back(indent(1) + member.item, nl(member.node), false); 10031 classFields.emplace_back(indent(1) + member.item, nl(member.node), false);
9987 } 10032 }
9988 } 10033 }
@@ -9991,7 +10036,7 @@ private:
9991 case id<YueComment_t>(): { 10036 case id<YueComment_t>(): {
9992 if (_config.reserveComment) { 10037 if (_config.reserveComment) {
9993 auto comment = static_cast<YueComment_t*>(content); 10038 auto comment = static_cast<YueComment_t*>(content);
9994 commentOrEmpty.emplace_back(indent(1) + comment->to_string(&_config), "\n"s, true); 10039 commentOrEmpty.emplace_back(comment->to_string(&_config), "\n"s, true);
9995 } 10040 }
9996 break; 10041 break;
9997 } 10042 }
@@ -10001,8 +10046,10 @@ private:
10001 } 10046 }
10002 break; 10047 break;
10003 } 10048 }
10004 case id<Statement_t>(): 10049 case id<Statement_t>(): {
10050 commentOrEmpty.clear();
10005 break; 10051 break;
10052 }
10006 default: YUEE("AST node mismatch", content); break; 10053 default: YUEE("AST node mismatch", content); break;
10007 } 10054 }
10008 } 10055 }
@@ -10010,9 +10057,20 @@ private:
10010 forceAddToScope(classVar); 10057 forceAddToScope(classVar);
10011 } 10058 }
10012 forceAddToScope("self"s); 10059 forceAddToScope("self"s);
10013 for (auto stmt_ : block->statementOrComments.objects()) { 10060 for (auto s : block->statementOrComments.objects()) {
10014 if (auto stmt = ast_cast<Statement_t>(stmt_)) { 10061 switch (s->get_id()) {
10015 transformStatement(stmt, initStatements); 10062 case id<Statement_t>():
10063 transformStatement(static_cast<Statement_t*>(s), initStatements);
10064 break;
10065 case id<EmptyLine_t>():
10066 initStatements.push_back("\n"s);
10067 break;
10068 case id<YueComment_t>():
10069 transformComment(static_cast<YueComment_t*>(s), initStatements);
10070 break;
10071 default:
10072 YUEE("AST node mismatch", s);
10073 break;
10016 } 10074 }
10017 } 10075 }
10018 if (!classFields.empty()) { 10076 if (!classFields.empty()) {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 421acee..7ea2c97 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -905,7 +905,7 @@ YueParser::YueParser() {
905 white >> '}' 905 white >> '}'
906 ); 906 );
907 907
908 table_block_inner = Seperator >> key_value_line >> *(+plain_space_break >> key_value_line); 908 table_block_inner = Seperator >> key_value_line >> *(line_break >> key_value_line);
909 TableBlock = +plain_space_break >> advance_match >> ensure(table_block_inner, pop_indent); 909 TableBlock = +plain_space_break >> advance_match >> ensure(table_block_inner, pop_indent);
910 TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule( 910 TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule(
911 space >> key_value_list >> -(space >> ',') >> 911 space >> key_value_list >> -(space >> ',') >>
@@ -916,7 +916,7 @@ YueParser::YueParser() {
916 ClassBlock = 916 ClassBlock =
917 +plain_space_break >> 917 +plain_space_break >>
918 advance_match >> Seperator >> 918 advance_match >> Seperator >>
919 class_line >> *(+plain_space_break >> class_line) >> 919 class_line >> *(line_break >> class_line) >>
920 pop_indent; 920 pop_indent;
921 921
922 ClassDecl = 922 ClassDecl =
@@ -1007,7 +1007,7 @@ YueParser::YueParser() {
1007 MetaNormalPairDef = MetaNormalPair >> destruct_def; 1007 MetaNormalPairDef = MetaNormalPair >> destruct_def;
1008 NormalDef = Exp >> Seperator >> destruct_def; 1008 NormalDef = Exp >> Seperator >> destruct_def;
1009 1009
1010 yue_comment_block = -EmptyLine >> YueComment >> *(line_break >> -EmptyLine >> YueComment) >> line_break; 1010 yue_comment_block = -EmptyLine >> YueComment >> *(line_break >> -EmptyLine >> YueComment) >> line_break >> -EmptyLine | EmptyLine;
1011 1011
1012 key_value = 1012 key_value =
1013 VariablePair | 1013 VariablePair |