aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/inputs/test/format_spec.yue126
-rw-r--r--spec/outputs/test/format_spec.lua133
-rw-r--r--src/yue_wasm.cpp2
-rw-r--r--src/yuescript/yue_ast.cpp260
-rw-r--r--src/yuescript/yue_compiler.cpp2
-rw-r--r--src/yuescript/yue_parser.cpp42
-rw-r--r--src/yuescript/yue_parser.h3
-rw-r--r--src/yuescript/yuescript.cpp43
8 files changed, 535 insertions, 76 deletions
diff --git a/spec/inputs/test/format_spec.yue b/spec/inputs/test/format_spec.yue
new file mode 100644
index 0000000..5076445
--- /dev/null
+++ b/spec/inputs/test/format_spec.yue
@@ -0,0 +1,126 @@
1files = [
2 "spec/inputs/macro_export.yue"
3 "spec/inputs/attrib.yue"
4 "spec/inputs/macro.yue"
5 "spec/inputs/using.yue"
6 "spec/inputs/whitespace.yue"
7 "spec/inputs/nil_coalescing.yue"
8 "spec/inputs/stub.yue"
9 "spec/inputs/pipe.yue"
10 "spec/inputs/teal_lang.yue"
11 "spec/inputs/string.yue"
12 "spec/inputs/local.yue"
13 "spec/inputs/tables.yue"
14 "spec/inputs/operators.yue"
15 "spec/inputs/lists.yue"
16 "spec/inputs/compile_doc.yue"
17 "spec/inputs/switch.yue"
18 "spec/inputs/multiline_chain.yue"
19 "spec/inputs/existential.yue"
20 "spec/inputs/export_default.yue"
21 "spec/inputs/assign.yue"
22 "spec/inputs/literals.yue"
23 "spec/inputs/luarocks_upload.yue"
24 "spec/inputs/ambiguous.yue"
25 "spec/inputs/bubbling.yue"
26 "spec/inputs/try_catch.yue"
27 "spec/inputs/funcs.yue"
28 "spec/inputs/do.yue"
29 "spec/inputs/with.yue"
30 "spec/inputs/export.yue"
31 "spec/inputs/macro_todo.yue"
32 "spec/inputs/backcall.yue"
33 "spec/inputs/cond.yue"
34 "spec/inputs/in_expression.yue"
35 "spec/inputs/comprehension.yue"
36 "spec/inputs/macro_teal.yue"
37 "spec/inputs/import.yue"
38 "spec/inputs/unless_else.yue"
39 "spec/inputs/destructure.yue"
40 "spec/inputs/return.yue"
41 "spec/inputs/loops.yue"
42 "spec/inputs/class.yue"
43 "spec/inputs/vararg.yue"
44 "spec/inputs/goto.yue"
45 "spec/inputs/metatable.yue"
46 "spec/inputs/syntax.yue"
47 "spec/inputs/global.yue"
48 "spec/inputs/plus.yue"
49 "spec/inputs/test/class_spec.yue"
50 "spec/inputs/test/table_spreading_spec.yue"
51 "spec/inputs/test/loops_spec.yue"
52 "spec/inputs/test/format_spec.yue"
53 "spec/inputs/unicode/macro_export.yue"
54 "spec/inputs/unicode/attrib.yue"
55 "spec/inputs/unicode/macro.yue"
56 "spec/inputs/unicode/using.yue"
57 "spec/inputs/unicode/whitespace.yue"
58 "spec/inputs/unicode/nil_coalescing.yue"
59 "spec/inputs/unicode/stub.yue"
60 "spec/inputs/unicode/pipe.yue"
61 "spec/inputs/unicode/string.yue"
62 "spec/inputs/unicode/local.yue"
63 "spec/inputs/unicode/tables.yue"
64 "spec/inputs/unicode/operators.yue"
65 "spec/inputs/unicode/lists.yue"
66 "spec/inputs/unicode/switch.yue"
67 "spec/inputs/unicode/multiline_chain.yue"
68 "spec/inputs/unicode/existential.yue"
69 "spec/inputs/unicode/export_default.yue"
70 "spec/inputs/unicode/assign.yue"
71 "spec/inputs/unicode/literals.yue"
72 "spec/inputs/unicode/ambiguous.yue"
73 "spec/inputs/unicode/bubbling.yue"
74 "spec/inputs/unicode/try_catch.yue"
75 "spec/inputs/unicode/funcs.yue"
76 "spec/inputs/unicode/do.yue"
77 "spec/inputs/unicode/with.yue"
78 "spec/inputs/unicode/export.yue"
79 "spec/inputs/unicode/macro_todo.yue"
80 "spec/inputs/unicode/backcall.yue"
81 "spec/inputs/unicode/cond.yue"
82 "spec/inputs/unicode/in_expression.yue"
83 "spec/inputs/unicode/comprehension.yue"
84 "spec/inputs/unicode/import.yue"
85 "spec/inputs/unicode/unless_else.yue"
86 "spec/inputs/unicode/destructure.yue"
87 "spec/inputs/unicode/return.yue"
88 "spec/inputs/unicode/loops.yue"
89 "spec/inputs/unicode/class.yue"
90 "spec/inputs/unicode/vararg.yue"
91 "spec/inputs/unicode/goto.yue"
92 "spec/inputs/unicode/metatable.yue"
93 "spec/inputs/unicode/syntax.yue"
94 "spec/inputs/unicode/global.yue"
95 "spec/inputs/unicode/plus.yue"
96]
97
98import "yue"
99
100rewriteLineCol = (item)->
101 item[2] = 0
102 item[3] = 0
103 for i = 4, #item
104 switch type item[i] when "table"
105 if item[i][1] == "comment"
106 table.remove item, i
107 rewriteLineCol item
108 return
109 rewriteLineCol item[i]
110
111<- describe "format"
112for file in *files
113 <- it file
114 f = io.open file
115 code = f\read "a*"
116 f\close!
117
118 original_ast = yue.to_ast code
119 assert.is_not_nil original_ast
120 rewriteLineCol original_ast
121 formated = yue.format code
122 ast = yue.to_ast formated
123 assert.is_not_nil ast
124 rewriteLineCol ast
125 assert.same original_ast, ast
126
diff --git a/spec/outputs/test/format_spec.lua b/spec/outputs/test/format_spec.lua
new file mode 100644
index 0000000..b12fb04
--- /dev/null
+++ b/spec/outputs/test/format_spec.lua
@@ -0,0 +1,133 @@
1local files = {
2 "spec/inputs/macro_export.yue",
3 "spec/inputs/attrib.yue",
4 "spec/inputs/macro.yue",
5 "spec/inputs/using.yue",
6 "spec/inputs/whitespace.yue",
7 "spec/inputs/nil_coalescing.yue",
8 "spec/inputs/stub.yue",
9 "spec/inputs/pipe.yue",
10 "spec/inputs/teal_lang.yue",
11 "spec/inputs/string.yue",
12 "spec/inputs/local.yue",
13 "spec/inputs/tables.yue",
14 "spec/inputs/operators.yue",
15 "spec/inputs/lists.yue",
16 "spec/inputs/compile_doc.yue",
17 "spec/inputs/switch.yue",
18 "spec/inputs/multiline_chain.yue",
19 "spec/inputs/existential.yue",
20 "spec/inputs/export_default.yue",
21 "spec/inputs/assign.yue",
22 "spec/inputs/literals.yue",
23 "spec/inputs/luarocks_upload.yue",
24 "spec/inputs/ambiguous.yue",
25 "spec/inputs/bubbling.yue",
26 "spec/inputs/try_catch.yue",
27 "spec/inputs/funcs.yue",
28 "spec/inputs/do.yue",
29 "spec/inputs/with.yue",
30 "spec/inputs/export.yue",
31 "spec/inputs/macro_todo.yue",
32 "spec/inputs/backcall.yue",
33 "spec/inputs/cond.yue",
34 "spec/inputs/in_expression.yue",
35 "spec/inputs/comprehension.yue",
36 "spec/inputs/macro_teal.yue",
37 "spec/inputs/import.yue",
38 "spec/inputs/unless_else.yue",
39 "spec/inputs/destructure.yue",
40 "spec/inputs/return.yue",
41 "spec/inputs/loops.yue",
42 "spec/inputs/class.yue",
43 "spec/inputs/vararg.yue",
44 "spec/inputs/goto.yue",
45 "spec/inputs/metatable.yue",
46 "spec/inputs/syntax.yue",
47 "spec/inputs/global.yue",
48 "spec/inputs/plus.yue",
49 "spec/inputs/test/class_spec.yue",
50 "spec/inputs/test/table_spreading_spec.yue",
51 "spec/inputs/test/loops_spec.yue",
52 "spec/inputs/test/format_spec.yue",
53 "spec/inputs/unicode/macro_export.yue",
54 "spec/inputs/unicode/attrib.yue",
55 "spec/inputs/unicode/macro.yue",
56 "spec/inputs/unicode/using.yue",
57 "spec/inputs/unicode/whitespace.yue",
58 "spec/inputs/unicode/nil_coalescing.yue",
59 "spec/inputs/unicode/stub.yue",
60 "spec/inputs/unicode/pipe.yue",
61 "spec/inputs/unicode/string.yue",
62 "spec/inputs/unicode/local.yue",
63 "spec/inputs/unicode/tables.yue",
64 "spec/inputs/unicode/operators.yue",
65 "spec/inputs/unicode/lists.yue",
66 "spec/inputs/unicode/switch.yue",
67 "spec/inputs/unicode/multiline_chain.yue",
68 "spec/inputs/unicode/existential.yue",
69 "spec/inputs/unicode/export_default.yue",
70 "spec/inputs/unicode/assign.yue",
71 "spec/inputs/unicode/literals.yue",
72 "spec/inputs/unicode/ambiguous.yue",
73 "spec/inputs/unicode/bubbling.yue",
74 "spec/inputs/unicode/try_catch.yue",
75 "spec/inputs/unicode/funcs.yue",
76 "spec/inputs/unicode/do.yue",
77 "spec/inputs/unicode/with.yue",
78 "spec/inputs/unicode/export.yue",
79 "spec/inputs/unicode/macro_todo.yue",
80 "spec/inputs/unicode/backcall.yue",
81 "spec/inputs/unicode/cond.yue",
82 "spec/inputs/unicode/in_expression.yue",
83 "spec/inputs/unicode/comprehension.yue",
84 "spec/inputs/unicode/import.yue",
85 "spec/inputs/unicode/unless_else.yue",
86 "spec/inputs/unicode/destructure.yue",
87 "spec/inputs/unicode/return.yue",
88 "spec/inputs/unicode/loops.yue",
89 "spec/inputs/unicode/class.yue",
90 "spec/inputs/unicode/vararg.yue",
91 "spec/inputs/unicode/goto.yue",
92 "spec/inputs/unicode/metatable.yue",
93 "spec/inputs/unicode/syntax.yue",
94 "spec/inputs/unicode/global.yue",
95 "spec/inputs/unicode/plus.yue"
96}
97local yue = require("yue")
98local rewriteLineCol
99rewriteLineCol = function(item)
100 item[2] = 0
101 item[3] = 0
102 for i = 4, #item do
103 do
104 local _exp_0 = type(item[i])
105 if "table" == _exp_0 then
106 if item[i][1] == "comment" then
107 table.remove(item, i)
108 rewriteLineCol(item)
109 return
110 end
111 rewriteLineCol(item[i])
112 end
113 end
114 end
115end
116return describe("format", function()
117 for _index_0 = 1, #files do
118 local file = files[_index_0]
119 it(file, function()
120 local f = io.open(file)
121 local code = f:read("a*")
122 f:close()
123 local original_ast = yue.to_ast(code)
124 assert.is_not_nil(original_ast)
125 rewriteLineCol(original_ast)
126 local formated = yue.format(code)
127 local ast = yue.to_ast(formated)
128 assert.is_not_nil(ast)
129 rewriteLineCol(ast)
130 return assert.same(original_ast, ast)
131 end)
132 end
133end)
diff --git a/src/yue_wasm.cpp b/src/yue_wasm.cpp
index 4a054e6..daa5757 100644
--- a/src/yue_wasm.cpp
+++ b/src/yue_wasm.cpp
@@ -138,7 +138,7 @@ std::string exec(const std::string& codes) {
138 }; 138 };
139 139
140 execStr(R"yuescript( 140 execStr(R"yuescript(
141_G.__output = {} 141_G.__output = []
142_G.print = (...)-> 142_G.print = (...)->
143 _G.__output[] = table.concat [tostring select i, ... for i = 1, select "#", ...], " " 143 _G.__output[] = table.concat [tostring select i, ... for i = 1, select "#", ...], " "
144 _G.__output[] = "\n" 144 _G.__output[] = "\n"
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index 6126f71..6b2c96d 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -230,7 +230,7 @@ std::string LocalValues_t::to_string(void* ud) const {
230 temp.emplace_back(nameList->to_string(ud)); 230 temp.emplace_back(nameList->to_string(ud));
231 if (valueList) { 231 if (valueList) {
232 if (valueList.is<TableBlock_t>()) { 232 if (valueList.is<TableBlock_t>()) {
233 temp.emplace_back("="s + valueList->to_string(ud)); 233 temp.emplace_back("=\n"s + valueList->to_string(ud));
234 } else { 234 } else {
235 temp.emplace_back("="s); 235 temp.emplace_back("="s);
236 temp.emplace_back(valueList->to_string(ud)); 236 temp.emplace_back(valueList->to_string(ud));
@@ -312,7 +312,10 @@ std::string ShortTabAppending_t::to_string(void* ud) const {
312std::string Backcall_t::to_string(void* ud) const { 312std::string Backcall_t::to_string(void* ud) const {
313 str_list temp; 313 str_list temp;
314 if (argsDef) { 314 if (argsDef) {
315 temp.emplace_back(argsDef->to_string(ud)); 315 auto def = argsDef->to_string(ud);
316 if (!def.empty()) {
317 temp.emplace_back(def);
318 }
316 } 319 }
317 temp.emplace_back(arrow->to_string(ud)); 320 temp.emplace_back(arrow->to_string(ud));
318 temp.emplace_back(value->to_string(ud)); 321 temp.emplace_back(value->to_string(ud));
@@ -343,7 +346,7 @@ std::string ExpList_t::to_string(void* ud) const {
343std::string Return_t::to_string(void* ud) const { 346std::string Return_t::to_string(void* ud) const {
344 str_list temp{"return"s}; 347 str_list temp{"return"s};
345 if (valueList) { 348 if (valueList) {
346 temp.emplace_back(valueList.is<TableBlock_t>() ? ""s : " "s); 349 temp.emplace_back(valueList.is<TableBlock_t>() ? "\n"s : " "s);
347 temp.emplace_back(valueList->to_string(ud)); 350 temp.emplace_back(valueList->to_string(ud));
348 } 351 }
349 return join(temp); 352 return join(temp);
@@ -365,6 +368,9 @@ std::string With_t::to_string(void* ud) const {
365 } 368 }
366 info->pushScope(); 369 info->pushScope();
367 auto code = body->to_string(ud); 370 auto code = body->to_string(ud);
371 if (code.empty()) {
372 code = info->ind() + "--"s;
373 }
368 info->popScope(); 374 info->popScope();
369 return line + '\n' + code; 375 return line + '\n' + code;
370 } 376 }
@@ -383,6 +389,9 @@ std::string SwitchCase_t::to_string(void* ud) const {
383 } else { 389 } else {
384 info->pushScope(); 390 info->pushScope();
385 auto block = body->to_string(ud); 391 auto block = body->to_string(ud);
392 if (block.empty()) {
393 block = info->ind() + "--"s;
394 }
386 info->popScope(); 395 info->popScope();
387 auto line = "when "s + condition->to_string(ud); 396 auto line = "when "s + condition->to_string(ud);
388 if (line.find('\n') != std::string::npos) { 397 if (line.find('\n') != std::string::npos) {
@@ -405,6 +414,9 @@ std::string Switch_t::to_string(void* ud) const {
405 temp.emplace_back(info->ind() + "else"s); 414 temp.emplace_back(info->ind() + "else"s);
406 info->pushScope(); 415 info->pushScope();
407 temp.emplace_back(lastBranch->to_string(ud)); 416 temp.emplace_back(lastBranch->to_string(ud));
417 if (temp.back().empty()) {
418 temp.back() = info->ind() + "--"s;
419 }
408 info->popScope(); 420 info->popScope();
409 } 421 }
410 } 422 }
@@ -412,10 +424,18 @@ std::string Switch_t::to_string(void* ud) const {
412 return join(temp, "\n"sv); 424 return join(temp, "\n"sv);
413} 425}
414std::string Assignment_t::to_string(void* ud) const { 426std::string Assignment_t::to_string(void* ud) const {
415 return expList->to_string(ud) + ' ' + assign->to_string(ud); 427 if (expList) {
428 return ", "s + expList->to_string(ud) + " :"s + assign->to_string(ud);
429 } else {
430 return " :"s + assign->to_string(ud);
431 }
416} 432}
417std::string IfCond_t::to_string(void* ud) const { 433std::string IfCond_t::to_string(void* ud) const {
418 return condition->to_string(ud); 434 if (assignment) {
435 return condition->to_string(ud) + assignment->to_string(ud);
436 } else {
437 return condition->to_string(ud);
438 }
419} 439}
420std::string If_t::to_string(void* ud) const { 440std::string If_t::to_string(void* ud) const {
421 auto info = reinterpret_cast<YueFormat*>(ud); 441 auto info = reinterpret_cast<YueFormat*>(ud);
@@ -447,11 +467,17 @@ std::string If_t::to_string(void* ud) const {
447 if (condition) { 467 if (condition) {
448 info->pushScope(); 468 info->pushScope();
449 temp.emplace_back(node->to_string(ud)); 469 temp.emplace_back(node->to_string(ud));
470 if (temp.back().empty()) {
471 temp.back() = info->ind() + "--"s;
472 }
450 info->popScope(); 473 info->popScope();
451 } else { 474 } else {
452 temp.emplace_back(info->ind() + "else"s); 475 temp.emplace_back(info->ind() + "else"s);
453 info->pushScope(); 476 info->pushScope();
454 temp.emplace_back(node->to_string(ud)); 477 temp.emplace_back(node->to_string(ud));
478 if (temp.back().empty()) {
479 temp.back() = info->ind() + "--"s;
480 }
455 info->popScope(); 481 info->popScope();
456 } 482 }
457 condition = false; 483 condition = false;
@@ -473,6 +499,9 @@ std::string While_t::to_string(void* ud) const {
473 } 499 }
474 info->pushScope(); 500 info->pushScope();
475 temp.emplace_back(body->to_string(ud)); 501 temp.emplace_back(body->to_string(ud));
502 if (temp.back().empty()) {
503 temp.back() = info->ind() + "--"s;
504 }
476 info->popScope(); 505 info->popScope();
477 } 506 }
478 return join(temp, "\n"sv); 507 return join(temp, "\n"sv);
@@ -486,6 +515,9 @@ std::string Repeat_t::to_string(void* ud) const {
486 temp.emplace_back("repeat"s); 515 temp.emplace_back("repeat"s);
487 info->pushScope(); 516 info->pushScope();
488 temp.emplace_back(body->to_string(ud)); 517 temp.emplace_back(body->to_string(ud));
518 if (temp.back().empty()) {
519 temp.back() = info->ind() + "--"s;
520 }
489 info->popScope(); 521 info->popScope();
490 } 522 }
491 temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); 523 temp.emplace_back(info->ind() + "until "s + condition->to_string(ud));
@@ -508,6 +540,9 @@ std::string For_t::to_string(void* ud) const {
508 } 540 }
509 info->pushScope(); 541 info->pushScope();
510 auto block = body->to_string(ud); 542 auto block = body->to_string(ud);
543 if (block.empty()) {
544 block = info->ind() + "--"s;
545 }
511 info->popScope(); 546 info->popScope();
512 return line + '\n' + block; 547 return line + '\n' + block;
513 } 548 }
@@ -523,6 +558,9 @@ std::string ForEach_t::to_string(void* ud) const {
523 } 558 }
524 info->pushScope(); 559 info->pushScope();
525 auto block = body->to_string(ud); 560 auto block = body->to_string(ud);
561 if (block.empty()) {
562 block = info->ind() + "--"s;
563 }
526 info->popScope(); 564 info->popScope();
527 return line + '\n' + block; 565 return line + '\n' + block;
528 } 566 }
@@ -534,6 +572,9 @@ std::string Do_t::to_string(void* ud) const {
534 } else { 572 } else {
535 info->pushScope(); 573 info->pushScope();
536 auto block = body->to_string(ud); 574 auto block = body->to_string(ud);
575 if (block.empty()) {
576 block = info->ind() + "--"s;
577 }
537 info->popScope(); 578 info->popScope();
538 return "do\n"s + block; 579 return "do\n"s + block;
539 } 580 }
@@ -543,6 +584,9 @@ std::string CatchBlock_t::to_string(void* ud) const {
543 auto line = "catch "s + err->to_string(ud); 584 auto line = "catch "s + err->to_string(ud);
544 info->pushScope(); 585 info->pushScope();
545 auto block = body->to_string(ud); 586 auto block = body->to_string(ud);
587 if (block.empty()) {
588 block = info->ind() + "--"s;
589 }
546 info->popScope(); 590 info->popScope();
547 return line + '\n' + block; 591 return line + '\n' + block;
548} 592}
@@ -555,6 +599,9 @@ std::string Try_t::to_string(void* ud) const {
555 temp.emplace_back("try"s); 599 temp.emplace_back("try"s);
556 info->pushScope(); 600 info->pushScope();
557 temp.emplace_back(func->to_string(ud)); 601 temp.emplace_back(func->to_string(ud));
602 if (temp.back().empty()) {
603 temp.back() = info->ind() + "--"s;
604 }
558 info->popScope(); 605 info->popScope();
559 } 606 }
560 if (catchBlock) { 607 if (catchBlock) {
@@ -571,7 +618,11 @@ std::string Comprehension_t::to_string(void* ud) const {
571 temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s); 618 temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s);
572 } 619 }
573 if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) { 620 if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) {
574 return '[' + join(temp, ", "sv) + ']'; 621 if (items.size() == 1) {
622 return '[' + join(temp, ", "sv) + ",]"s;
623 } else {
624 return '[' + join(temp, ", "sv) + ']';
625 }
575 } else { 626 } else {
576 return '[' + join(temp, " "sv) + ']'; 627 return '[' + join(temp, " "sv) + ']';
577 } 628 }
@@ -613,7 +664,7 @@ std::string CompInner_t::to_string(void* ud) const {
613std::string Assign_t::to_string(void* ud) const { 664std::string Assign_t::to_string(void* ud) const {
614 str_list temp; 665 str_list temp;
615 if (values.size() == 1 && ast_is<TableBlock_t>(values.front())) { 666 if (values.size() == 1 && ast_is<TableBlock_t>(values.front())) {
616 return '=' + values.front()->to_string(ud); 667 return "=\n"s + values.front()->to_string(ud);
617 } 668 }
618 for (auto value : values.objects()) { 669 for (auto value : values.objects()) {
619 temp.emplace_back(value->to_string(ud)); 670 temp.emplace_back(value->to_string(ud));
@@ -790,7 +841,13 @@ static bool isInBlockExp(ast_node* node) {
790 TblComprehension_t, Comprehension_t>(simpleValue->value)) { 841 TblComprehension_t, Comprehension_t>(simpleValue->value)) {
791 return true; 842 return true;
792 } 843 }
844 } else if (auto chainValue = value->item.as<ChainValue_t>()) {
845 if (ast_is<InvokeArgs_t>(chainValue->items.back())) {
846 return true;
847 }
793 } 848 }
849 } else if (ast_is<TableBlock_t>(node)) {
850 return true;
794 } 851 }
795 return false; 852 return false;
796} 853}
@@ -863,7 +920,7 @@ std::string TableBlock_t::to_string(void* ud) const {
863 temp.emplace_back(info->ind() + "* "s + value->to_string(ud)); 920 temp.emplace_back(info->ind() + "* "s + value->to_string(ud));
864 break; 921 break;
865 case id<TableBlock_t>(): 922 case id<TableBlock_t>():
866 temp.emplace_back(info->ind() + "*"s + value->to_string(ud)); 923 temp.emplace_back(info->ind() + "*\n"s + value->to_string(ud));
867 break; 924 break;
868 default: 925 default:
869 temp.emplace_back(info->ind() + value->to_string(ud)); 926 temp.emplace_back(info->ind() + value->to_string(ud));
@@ -871,21 +928,25 @@ std::string TableBlock_t::to_string(void* ud) const {
871 } 928 }
872 } 929 }
873 info->popScope(); 930 info->popScope();
874 return '\n' + join(temp, "\n"sv); 931 return join(temp, "\n"sv);
875} 932}
876std::string TableBlockIndent_t::to_string(void* ud) const { 933std::string TableBlockIndent_t::to_string(void* ud) const {
877 auto info = reinterpret_cast<YueFormat*>(ud); 934 auto info = reinterpret_cast<YueFormat*>(ud);
878 str_list temp; 935 str_list temp;
879 info->pushScope(); 936 info->pushScope();
880 for (auto value : values.objects()) { 937 for (auto value : values.objects()) {
881 if (value == values.front()) { 938 if (ast_is<TableBlockIndent_t>(value)) {
882 temp.emplace_back("* "s + value->to_string(ud)); 939 temp.emplace_back("\n"s + value->to_string(ud));
883 } else { 940 } else {
884 temp.emplace_back(info->ind() + value->to_string(ud)); 941 if (value == values.front()) {
942 temp.emplace_back(" "s + value->to_string(ud));
943 } else {
944 temp.emplace_back(info->ind() + value->to_string(ud));
945 }
885 } 946 }
886 } 947 }
887 info->popScope(); 948 info->popScope();
888 return join(temp, "\n"sv); 949 return "*"s + join(temp, "\n"sv);
889} 950}
890std::string ClassMemberList_t::to_string(void* ud) const { 951std::string ClassMemberList_t::to_string(void* ud) const {
891 auto info = reinterpret_cast<YueFormat*>(ud); 952 auto info = reinterpret_cast<YueFormat*>(ud);
@@ -893,7 +954,7 @@ std::string ClassMemberList_t::to_string(void* ud) const {
893 for (auto value : values.objects()) { 954 for (auto value : values.objects()) {
894 temp.emplace_back(info->ind() + value->to_string(ud)); 955 temp.emplace_back(info->ind() + value->to_string(ud));
895 } 956 }
896 return join(temp, "\n"sv); 957 return join(temp, ", "sv);
897} 958}
898std::string ClassBlock_t::to_string(void* ud) const { 959std::string ClassBlock_t::to_string(void* ud) const {
899 auto info = reinterpret_cast<YueFormat*>(ud); 960 auto info = reinterpret_cast<YueFormat*>(ud);
@@ -929,7 +990,7 @@ std::string GlobalValues_t::to_string(void* ud) const {
929 auto line = nameList->to_string(ud); 990 auto line = nameList->to_string(ud);
930 if (valueList) { 991 if (valueList) {
931 if (valueList.is<TableBlock_t>()) { 992 if (valueList.is<TableBlock_t>()) {
932 line += " ="s + valueList->to_string(ud); 993 line += " =\n"s + valueList->to_string(ud);
933 } else { 994 } else {
934 line += " = "s + valueList->to_string(ud); 995 line += " = "s + valueList->to_string(ud);
935 } 996 }
@@ -949,8 +1010,12 @@ std::string Export_t::to_string(void* ud) const {
949 line += target->to_string(ud); 1010 line += target->to_string(ud);
950 break; 1011 break;
951 case id<Exp_t>(): { 1012 case id<Exp_t>(): {
952 auto valueStr = target->to_string(ud); 1013 if (def) {
953 line += '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ']'; 1014 line += target->to_string(ud);
1015 } else {
1016 auto valueStr = target->to_string(ud);
1017 line += '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ']';
1018 }
954 break; 1019 break;
955 } 1020 }
956 default: 1021 default:
@@ -973,7 +1038,7 @@ std::string NormalPair_t::to_string(void* ud) const {
973 } else { 1038 } else {
974 line = key->to_string(ud) + ":"s; 1039 line = key->to_string(ud) + ":"s;
975 } 1040 }
976 line += (value.is<TableBlock_t>() ? ""s : " "s) + value->to_string(ud); 1041 line += (value.is<TableBlock_t>() ? "\n"s : " "s) + value->to_string(ud);
977 return line; 1042 return line;
978} 1043}
979std::string MetaVariablePair_t::to_string(void* ud) const { 1044std::string MetaVariablePair_t::to_string(void* ud) const {
@@ -989,7 +1054,7 @@ std::string MetaNormalPair_t::to_string(void* ud) const {
989 } else { 1054 } else {
990 line = '<' + key->to_string(ud) + ">:"s; 1055 line = '<' + key->to_string(ud) + ">:"s;
991 } 1056 }
992 line += (value.is<TableBlock_t>() ? ""s : " "s) + value->to_string(ud); 1057 line += (value.is<TableBlock_t>() ? "\n"s : " "s) + value->to_string(ud);
993 return line; 1058 return line;
994} 1059}
995std::string VariablePairDef_t::to_string(void* ud) const { 1060std::string VariablePairDef_t::to_string(void* ud) const {
@@ -1033,23 +1098,38 @@ std::string FnArgDef_t::to_string(void* ud) const {
1033 line += op->to_string(ud); 1098 line += op->to_string(ud);
1034 } 1099 }
1035 if (defaultValue) { 1100 if (defaultValue) {
1036 if (isInBlockExp(defaultValue)) { 1101 line += " = "s + defaultValue->to_string(ud);
1037 line += " = ("s + defaultValue->to_string(ud) + ')';
1038 } else {
1039 line += " = "s + defaultValue->to_string(ud);
1040 }
1041 } 1102 }
1042 return line; 1103 return line;
1043} 1104}
1044std::string FnArgDefList_t::to_string(void* ud) const { 1105std::string FnArgDefList_t::to_string(void* ud) const {
1106 auto info = reinterpret_cast<YueFormat*>(ud);
1045 str_list temp; 1107 str_list temp;
1108 bool hasInBlockExp = false;
1046 for (auto def : definitions.objects()) { 1109 for (auto def : definitions.objects()) {
1047 temp.emplace_back(def->to_string(ud)); 1110 auto argDef = static_cast<FnArgDef_t*>(def);
1111 if (argDef->defaultValue && isInBlockExp(argDef->defaultValue)) {
1112 hasInBlockExp = true;
1113 break;
1114 }
1048 } 1115 }
1049 if (varArg) { 1116 if (hasInBlockExp) {
1050 temp.emplace_back(varArg->to_string(ud)); 1117 for (auto def : definitions.objects()) {
1118 temp.emplace_back(info->ind() + def->to_string(ud));
1119 }
1120 if (varArg) {
1121 temp.emplace_back(info->ind() + varArg->to_string(ud));
1122 }
1123 return join(temp, "\n"sv);
1124 } else {
1125 for (auto def : definitions.objects()) {
1126 temp.emplace_back(def->to_string(ud));
1127 }
1128 if (varArg) {
1129 temp.emplace_back(varArg->to_string(ud));
1130 }
1131 return join(temp, ", "sv);
1051 } 1132 }
1052 return join(temp, ", "sv);
1053} 1133}
1054std::string OuterVarShadow_t::to_string(void* ud) const { 1134std::string OuterVarShadow_t::to_string(void* ud) const {
1055 if (varList) { 1135 if (varList) {
@@ -1059,14 +1139,38 @@ std::string OuterVarShadow_t::to_string(void* ud) const {
1059 } 1139 }
1060} 1140}
1061std::string FnArgsDef_t::to_string(void* ud) const { 1141std::string FnArgsDef_t::to_string(void* ud) const {
1062 std::string line; 1142 auto info = reinterpret_cast<YueFormat*>(ud);
1143 bool hasInBlockExp = false;
1063 if (defList) { 1144 if (defList) {
1064 line += defList->to_string(ud); 1145 for (auto def : defList->definitions.objects()) {
1146 auto argDef = static_cast<FnArgDef_t*>(def);
1147 if (argDef->defaultValue && isInBlockExp(argDef->defaultValue)) {
1148 hasInBlockExp = true;
1149 break;
1150 }
1151 }
1065 } 1152 }
1066 if (shadowOption) { 1153 if (hasInBlockExp) {
1067 line += (line.empty() ? ""s : " "s) + shadowOption->to_string(ud); 1154 str_list temp;
1155 info->pushScope();
1156 if (defList) {
1157 temp.push_back(defList->to_string(ud));
1158 }
1159 if (shadowOption) {
1160 temp.push_back(info->ind() + shadowOption->to_string(ud));
1161 }
1162 info->popScope();
1163 return "(\n" + join(temp, "\n"sv) + '\n' + info->ind() + ')';
1164 } else {
1165 std::string line;
1166 if (defList) {
1167 line += defList->to_string(ud);
1168 }
1169 if (shadowOption) {
1170 line += (line.empty() ? ""s : " "s) + shadowOption->to_string(ud);
1171 }
1172 return line.empty() ? (defList ? "()"s : ""s) : '(' + line + ')';
1068 } 1173 }
1069 return line.empty() ? ""s : '(' + line + ')';
1070} 1174}
1071std::string FunLit_t::to_string(void* ud) const { 1175std::string FunLit_t::to_string(void* ud) const {
1072 auto info = reinterpret_cast<YueFormat*>(ud); 1176 auto info = reinterpret_cast<YueFormat*>(ud);
@@ -1080,7 +1184,11 @@ std::string FunLit_t::to_string(void* ud) const {
1080 line += ' ' + body->to_string(ud); 1184 line += ' ' + body->to_string(ud);
1081 } else { 1185 } else {
1082 info->pushScope(); 1186 info->pushScope();
1083 line += '\n' + body->to_string(ud); 1187 auto bodyStr = body->to_string(ud);
1188 if (bodyStr.empty()) {
1189 bodyStr = info->ind() + "--"s;
1190 }
1191 line += '\n' + bodyStr;
1084 info->popScope(); 1192 info->popScope();
1085 } 1193 }
1086 } 1194 }
@@ -1096,14 +1204,16 @@ std::string MacroLit_t::to_string(void* ud) const {
1096 line = '(' + argsDef->to_string(ud) + ')'; 1204 line = '(' + argsDef->to_string(ud) + ')';
1097 } 1205 }
1098 line += "->"s; 1206 line += "->"s;
1099 if (body) { 1207 if (body->content.is<Statement_t>()) {
1100 if (body->content.is<Statement_t>()) { 1208 line += ' ' + body->to_string(ud);
1101 line += ' ' + body->to_string(ud); 1209 } else {
1102 } else { 1210 info->pushScope();
1103 info->pushScope(); 1211 auto bodyStr = body->to_string(ud);
1104 line += '\n' + body->to_string(ud); 1212 if (bodyStr.empty()) {
1105 info->popScope(); 1213 bodyStr = info->ind() + "--"s;
1106 } 1214 }
1215 line += '\n' + bodyStr;
1216 info->popScope();
1107 } 1217 }
1108 return line; 1218 return line;
1109} 1219}
@@ -1113,14 +1223,16 @@ std::string Macro_t::to_string(void* ud) const {
1113std::string MacroInPlace_t::to_string(void* ud) const { 1223std::string MacroInPlace_t::to_string(void* ud) const {
1114 auto info = reinterpret_cast<YueFormat*>(ud); 1224 auto info = reinterpret_cast<YueFormat*>(ud);
1115 auto line = "$->"s; 1225 auto line = "$->"s;
1116 if (body) { 1226 if (body->content.is<Statement_t>()) {
1117 if (body->content.is<Statement_t>()) { 1227 line += ' ' + body->to_string(ud);
1118 line += ' ' + body->to_string(ud); 1228 } else {
1119 } else { 1229 info->pushScope();
1120 info->pushScope(); 1230 auto bodyStr = body->to_string(ud);
1121 line += '\n' + body->to_string(ud); 1231 if (bodyStr.empty()) {
1122 info->popScope(); 1232 bodyStr = info->ind() + "--"s;
1123 } 1233 }
1234 line += '\n' + bodyStr;
1235 info->popScope();
1124 } 1236 }
1125 return line; 1237 return line;
1126} 1238}
@@ -1135,15 +1247,32 @@ std::string AssignableNameList_t::to_string(void* ud) const {
1135 return join(temp, ", "sv); 1247 return join(temp, ", "sv);
1136} 1248}
1137std::string InvokeArgs_t::to_string(void* ud) const { 1249std::string InvokeArgs_t::to_string(void* ud) const {
1138 if (!args.empty() && ast_is<TableBlock_t>(args.back())) { 1250 auto info = reinterpret_cast<YueFormat*>(ud);
1251 bool hasInBlockExp = false;
1252 for (auto arg : args.objects()) {
1253 if (isInBlockExp(arg)) {
1254 hasInBlockExp = true;
1255 break;
1256 }
1257 }
1258 if (hasInBlockExp) {
1139 str_list temp; 1259 str_list temp;
1260 bool newLine = false;
1140 for (auto arg : args.objects()) { 1261 for (auto arg : args.objects()) {
1141 if (arg != args.back()) { 1262 if (arg == args.front()) {
1142 temp.emplace_back(arg->to_string(ud)); 1263 if (ast_is<TableBlock_t>(arg)) {
1264 newLine = true;
1265 }
1266 temp.push_back(arg->to_string(ud));
1267 info->pushScope();
1268 } else if (ast_is<TableBlock_t>(arg)) {
1269 temp.push_back(arg->to_string(ud));
1270 } else {
1271 temp.push_back(info->ind() + arg->to_string(ud));
1143 } 1272 }
1144 } 1273 }
1145 auto list = join(temp, ", "sv); 1274 info->popScope();
1146 return ' ' + list + (list.empty() ? ""s : ","s) + args.back()->to_string(ud); 1275 return (newLine ? '\n' : ' ') + join(temp, ",\n"sv);
1147 } else { 1276 } else {
1148 str_list temp; 1277 str_list temp;
1149 for (auto arg : args.objects()) { 1278 for (auto arg : args.objects()) {
@@ -1203,10 +1332,29 @@ std::string StatementAppendix_t::to_string(void* ud) const {
1203} 1332}
1204std::string Statement_t::to_string(void* ud) const { 1333std::string Statement_t::to_string(void* ud) const {
1205 std::string line; 1334 std::string line;
1206 if (appendix) { 1335 if (!comments.empty()) {
1207 return content->to_string(ud) + ' ' + appendix->to_string(ud); 1336 auto info = reinterpret_cast<YueFormat*>(ud);
1337 str_list temp;
1338 for (ast_node* comment : comments.objects()) {
1339 if (comment == comments.front()) {
1340 temp.push_back(comment->to_string(ud));
1341 } else {
1342 temp.push_back(info->ind() + comment->to_string(ud));
1343 }
1344 }
1345 if (appendix) {
1346 temp.push_back(info->ind() + content->to_string(ud) + ' ' + appendix->to_string(ud));
1347 return join(temp, "\n"sv);
1348 } else {
1349 temp.push_back(info->ind() + content->to_string(ud));
1350 return join(temp, "\n"sv);
1351 }
1208 } else { 1352 } else {
1209 return content->to_string(ud); 1353 if (appendix) {
1354 return content->to_string(ud) + ' ' + appendix->to_string(ud);
1355 } else {
1356 return content->to_string(ud);
1357 }
1210 } 1358 }
1211} 1359}
1212std::string StatementSep_t::to_string(void*) const { 1360std::string StatementSep_t::to_string(void*) const {
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 3e60556..59f6d4b 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.21.1"sv; 78const std::string_view version = "0.21.2"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 {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 4b865f5..89791d6 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -477,7 +477,7 @@ YueParser::YueParser() {
477 space 477 space
478 ); 478 );
479 479
480 list_lit_lines = space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); 480 list_lit_lines = +space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ',');
481 481
482 Comprehension = '[' >> not_('[') >> 482 Comprehension = '[' >> not_('[') >>
483 Seperator >> space >> ( 483 Seperator >> space >> (
@@ -489,7 +489,6 @@ YueParser::YueParser() {
489 white >> ']' >> not_(space >> '=') 489 white >> ']' >> not_(space >> '=')
490 ); 490 );
491 491
492 (space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']');
493 CompValue = ',' >> space >> Exp; 492 CompValue = ',' >> space >> Exp;
494 TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); 493 TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error);
495 494
@@ -829,17 +828,26 @@ YueParser::YueParser() {
829 '*' >> space >> (SpreadExp | Exp | TableBlock) 828 '*' >> space >> (SpreadExp | Exp | TableBlock)
830 ); 829 );
831 830
831 fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef);
832
833 fn_arg_def_lit_line = (
834 push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent)
835 ) | (
836 space
837 );
838
839 fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line);
840
832 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); 841 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp);
833 842
834 FnArgDefList = Seperator >> (( 843 FnArgDefList = Seperator >> (
835 FnArgDef >> 844 fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) |
836 *(space >> (',' | line_break) >> white >> FnArgDef) >> 845 white >> VarArg
837 -(space >> (',' | line_break) >> white >> VarArg) 846 );
838 ) | VarArg);
839 847
840 OuterVarShadow = key("using") >> space >> (NameList | key("nil")); 848 OuterVarShadow = key("using") >> space >> (NameList | key("nil"));
841 849
842 FnArgsDef = '(' >> white >> -FnArgDefList >> -(space >> OuterVarShadow) >> white >> ')'; 850 FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> ')';
843 FnArrow = expr("->") | "=>"; 851 FnArrow = expr("->") | "=>";
844 FunLit = -FnArgsDef >> space >> FnArrow >> -(space >> Body); 852 FunLit = -FnArgsDef >> space >> FnArrow >> -(space >> Body);
845 853
@@ -873,8 +881,8 @@ YueParser::YueParser() {
873 881
874 invoke_args_with_table = 882 invoke_args_with_table =
875 ',' >> ( 883 ',' >> (
876 TableBlock | 884 arg_table_block |
877 space_break >> advance_match >> arg_block >> -arg_table_block 885 space_break >> advance_match >> arg_block >> -(-(space >> ',') >> arg_table_block)
878 ) | arg_table_block; 886 ) | arg_table_block;
879 887
880 leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { 888 leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) {
@@ -954,11 +962,10 @@ YueParser::YueParser() {
954 962
955 Body = in_block | Statement; 963 Body = in_block | Statement;
956 964
957 empty_line_break = ( 965 empty_line_break =
958 check_indent >> (multi_line_comment >> space | comment) | 966 check_indent >> (multi_line_comment >> space | comment) >> and_(stop) |
959 advance >> ensure(multi_line_comment >> space | comment, pop_indent) | 967 advance >> ensure(multi_line_comment >> space | comment, pop_indent) >> and_(stop) |
960 plain_space 968 plain_space >> and_(line_break);
961 ) >> and_(stop);
962 969
963 indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { 970 indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) {
964 throw ParserError("unexpected indent"sv, item.begin); 971 throw ParserError("unexpected indent"sv, item.begin);
@@ -1084,6 +1091,11 @@ void trim(std::string& str) {
1084} // namespace Utils 1091} // namespace Utils
1085 1092
1086std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { 1093std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const {
1094 if (!codes) {
1095 std::ostringstream buf;
1096 buf << errLine + lineOffset << ": "sv << msg;
1097 return buf.str();
1098 }
1087 const int ASCII = 255; 1099 const int ASCII = 255;
1088 int length = errLine; 1100 int length = errLine;
1089 auto begin = codes->begin(); 1101 auto begin = codes->begin();
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index c3d5d7d..e183bf2 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -222,6 +222,9 @@ private:
222 NONE_AST_RULE(fn_args_lit_line); 222 NONE_AST_RULE(fn_args_lit_line);
223 NONE_AST_RULE(fn_args_lit_lines); 223 NONE_AST_RULE(fn_args_lit_lines);
224 NONE_AST_RULE(fn_args); 224 NONE_AST_RULE(fn_args);
225 NONE_AST_RULE(fn_arg_def_list);
226 NONE_AST_RULE(fn_arg_def_lit_line);
227 NONE_AST_RULE(fn_arg_def_lit_lines);
225 NONE_AST_RULE(destruct_def); 228 NONE_AST_RULE(destruct_def);
226 NONE_AST_RULE(macro_args_def); 229 NONE_AST_RULE(macro_args_def);
227 NONE_AST_RULE(chain_call); 230 NONE_AST_RULE(chain_call);
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp
index 856d8f3..dbaa287 100644
--- a/src/yuescript/yuescript.cpp
+++ b/src/yuescript/yuescript.cpp
@@ -172,6 +172,39 @@ static int yuetolua(lua_State* L) {
172 return 3; 172 return 3;
173} 173}
174 174
175static int yueformat(lua_State* L) {
176 size_t len = 0;
177 auto input = luaL_checklstring(L, 1, &len);
178 int tabSize = 0;
179 if (!lua_isnoneornil(L, 2)) {
180 tabSize = static_cast<int>(luaL_checkinteger(L, 2));
181 }
182 std::string_view codes(input, len);
183 auto info = yue::YueParser{}.parse<yue::File_t>(codes);
184 if (info.error) {
185 const auto& error = info.error.value();
186 if (!info.codes) {
187 lua_pushnil(L);
188 lua_pushlstring(L, error.msg.c_str(), error.msg.size());
189 return 2;
190 }
191 auto displayMessage = info.errorMessage(error.msg, error.line, error.col, 0);
192 lua_pushnil(L);
193 lua_pushlstring(L, displayMessage.c_str(), displayMessage.size());
194 return 2;
195 }
196 yue::YueFormat formatter{};
197 if (tabSize > 0) {
198 formatter.spaceOverTab = true;
199 formatter.tabSpaces = tabSize;
200 } else {
201 formatter.spaceOverTab = false;
202 }
203 auto result = formatter.toString(info.node.get());
204 lua_pushlstring(L, result.c_str(), result.size());
205 return 1;
206}
207
175static int yuecheck(lua_State* L) { 208static int yuecheck(lua_State* L) {
176 size_t len = 0; 209 size_t len = 0;
177 auto input = luaL_checklstring(L, 1, &len); 210 auto input = luaL_checklstring(L, 1, &len);
@@ -268,6 +301,7 @@ static int yuetoast(lua_State* L) {
268 stack.pop(); 301 stack.pop();
269 }; 302 };
270 do_call(info.node); 303 do_call(info.node);
304 yue::YueFormat formatter{};
271 while (!stack.empty()) { 305 while (!stack.empty()) {
272 auto& current = stack.top(); 306 auto& current = stack.top();
273 int continuation = current.continuation; 307 int continuation = current.continuation;
@@ -319,7 +353,8 @@ static int yuetoast(lua_State* L) {
319 lua_rawseti(L, -2, 2); 353 lua_rawseti(L, -2, 2);
320 lua_pushinteger(L, node->m_begin.m_col); 354 lua_pushinteger(L, node->m_begin.m_col);
321 lua_rawseti(L, -2, 3); 355 lua_rawseti(L, -2, 3);
322 auto str = parser.toString(node); 356 formatter.indent = 0;
357 auto str = node->to_string(&formatter);
323 yue::Utils::trim(str); 358 yue::Utils::trim(str);
324 lua_pushlstring(L, str.c_str(), str.length()); 359 lua_pushlstring(L, str.c_str(), str.length());
325 lua_rawseti(L, -2, 4); 360 lua_rawseti(L, -2, 4);
@@ -371,8 +406,9 @@ static int yuetoast(lua_State* L) {
371 return 1; 406 return 1;
372 } else { 407 } else {
373 lua_pushnil(L); 408 lua_pushnil(L);
374 const auto& msg = info.error.value().msg; 409 const auto& err = info.error.value();
375 lua_pushlstring(L, msg.c_str(), msg.length()); 410 auto displayMessage = info.errorMessage(err.msg, err.line, err.col);
411 lua_pushlstring(L, displayMessage.c_str(), displayMessage.length());
376 return 2; 412 return 2;
377 } 413 }
378} 414}
@@ -381,6 +417,7 @@ static const luaL_Reg yuelib[] = {
381 {"to_lua", yuetolua}, 417 {"to_lua", yuetolua},
382 {"to_ast", yuetoast}, 418 {"to_ast", yuetoast},
383 {"check", yuecheck}, 419 {"check", yuecheck},
420 {"format", yueformat},
384 {"version", nullptr}, 421 {"version", nullptr},
385 {"options", nullptr}, 422 {"options", nullptr},
386 {"load_stacktraceplus", nullptr}, 423 {"load_stacktraceplus", nullptr},