16 m_dry_run(dry_run), m_parser( 0,
ParserMode::
Raw), m_updated(false)
20 m_filename(
std::move(filename)), m_dry_run(dry_run), m_parser( 0,
ParserMode::
Raw), m_updated(false)
71 for (std::size_t i = 1, end = ast.
constList().size(); i < end; ++i)
91 const std::size_t before_count = std::ranges::count(original_code,
'#');
92 const std::size_t after_count = std::ranges::count(
m_output,
'#');
94 if (before_count != after_count)
97 "{}: one or more comments from the original source code seem to have been {} by mistake while formatting {}",
98 fmt::styled(
"Warning", fmt::fg(fmt::color::dark_orange)),
99 before_count > after_count ?
"removed" :
"duplicated",
101 fmt::println(
"Please fill an issue on GitHub: https://github.com/ArkScript-lang/Ark");
139 const std::string formatted =
format(node, 0,
false);
140 const std::string::size_type sz = formatted.find_first_of(
'\n');
158 const auto& child = list[at];
164 if (child.position().start.line - previous_line > 1 && child.comment().empty())
168 if (child.position().start.line - previous_line > 2 && !child.comment().empty())
179 after_newline =
true;
186 case NodeType::Symbol:
189 case NodeType::Capture:
190 result +=
"&" + node.
string();
192 case NodeType::Keyword:
193 result += std::string(
keywords[
static_cast<std::size_t
>(node.
keyword())]);
195 case NodeType::String:
196 result += fmt::format(
"\"{}\"", node.
string());
198 case NodeType::Number:
199 result += fmt::format(
"{}", node.
number());
202 result +=
formatBlock(node, indent, after_newline);
204 case NodeType::Spread:
205 result += fmt::format(
"...{}", node.
string());
207 case NodeType::Field:
210 for (std::size_t i = 1, end = node.
constList().size(); i < end; ++i)
215 case NodeType::Macro:
219 case NodeType::Namespace:
221 case NodeType::Unused:
233 std::string result =
prefix(indent);
234 for (std::size_t i = 0, end = comment.size(); i < end; ++i)
236 result += comment[i];
237 if (comment[i] ==
'\n' && i != end - 1)
250 if (first.
nodeType() == NodeType::Keyword)
268 case Keyword::Import:
284 std::string formatted_args;
286 if (!args_node.
comment().empty())
288 formatted_args +=
"\n";
290 formatted_args +=
prefix(indent + 1);
293 formatted_args +=
" ";
297 bool comment_in_args =
false;
301 for (std::size_t i = 0, end = args_node.
constList().size(); i < end; ++i)
305 comment_in_args =
true;
307 args +=
format(arg_i, indent + ((comment_in_args || split) ? 1 : 0), i > 0 && (comment_in_args || split));
309 args += (comment_in_args || split) ?
'\n' :
' ';
312 formatted_args += fmt::format(
"({}{})", (comment_in_args ?
"\n" :
""), args);
315 formatted_args +=
format(args_node, indent,
false);
318 return fmt::format(
"(fun{} {})", formatted_args,
format(body_node, indent + 1,
false));
319 return fmt::format(
"(fun{}\n{})", formatted_args,
format(body_node, indent + 1,
true));
324 const auto keyword = std::string(
keywords[
static_cast<std::size_t
>(node.
constList()[0].keyword())]);
327 const std::string formatted_bind =
format(node.
constList()[1], indent,
false);
331 return fmt::format(
"({} {} {})", keyword, formatted_bind,
format(body_node, indent,
false));
332 return fmt::format(
"({} {}\n{})", keyword, formatted_bind,
format(body_node, indent + 1,
true));
340 bool cond_on_newline =
false;
341 std::string formatted_cond =
format(cond_node, indent + 1,
false);
342 if (formatted_cond.find(
'\n') != std::string::npos)
343 cond_on_newline =
true;
345 std::string if_cond_formatted = fmt::format(
348 cond_on_newline ?
"\n" :
" ",
356 if (cond_on_newline || split_then_newline)
357 return fmt::format(
"{}\n{})", if_cond_formatted,
format(then_node, indent + 1,
true));
358 return fmt::format(
"{} {})", if_cond_formatted,
format(then_node, indent + 1,
false));
364 format(then_node, indent + 1,
true),
366 node.
constList()[3].commentAfter().empty() ?
"" : (
"\n" +
prefix(indent)));
374 bool cond_on_newline =
false;
375 std::string formatted_cond =
format(cond_node, indent + 1,
false);
376 if (formatted_cond.find(
'\n') != std::string::npos)
377 cond_on_newline =
true;
382 cond_on_newline ?
"\n" :
" ",
384 format(body_node, indent + 1,
true));
388 format(body_node, indent + 1,
false));
399 const std::size_t inner_indentation = indent + (after_newline ? 1 : 0) + (indent == 0 ? 1 : 0);
401 std::string result =
"{\n";
403 for (std::size_t i = 1, end = node.
constList().size(); i < end; ++i)
411 result +=
format(child, inner_indentation,
true);
418 result +=
"\n" +
prefix(indent) +
"}";
429 if (!package_node.
comment().empty())
430 package += "\n" + formatComment(package_node.comment(), indent + 1) + prefix(indent + 1);
434 for (std::size_t i = 0, end = package_node.
constList().size(); i < end; ++i)
436 package += format(package_node.constList()[i], indent + 1, false);
442 if (symbols.nodeType() == NodeType::Symbol && symbols.string() ==
"*")
446 if (const auto& sym_list = symbols.constList(); !sym_list.empty())
448 const bool comment_after_last = !sym_list.back().commentAfter().empty();
450 for (const auto& sym : sym_list)
452 if (sym.comment().empty())
454 if (comment_after_last)
455 package +=
"\n" + prefix(indent + 1) +
":" + sym.string();
457 package +=
" :" + sym.string();
460 package +=
"\n" + formatComment(sym.comment(), indent + 1) + prefix(indent + 1) +
":" + sym.string();
463 if (comment_after_last)
465 package +=
" " + formatComment(sym_list.back().commentAfter(), 0);
466 package +=
"\n" + prefix(indent + 1);
471 return fmt::format(
"(import{})", package);
476 std::string formatted_sym =
format(node.
constList()[1], indent + 1,
false);
477 if (formatted_sym.find(
'\n') != std::string::npos)
478 return fmt::format(
"(del\n{})", formatted_sym);
479 return fmt::format(
"(del {})", formatted_sym);
484 bool is_list =
false;
485 bool is_dict =
false;
486 bool is_multiline =
false;
488 if (!node.
constList().empty() && node.
constList().front().nodeType() == NodeType::Symbol)
490 if (node.
constList().front().string() ==
"list")
492 else if (node.
constList().front().string() ==
"dict")
496 std::vector<std::string> formatted_args;
497 for (std::size_t i = 1, end = node.
constList().size(); i < end; ++i)
501 if (formatted_args.back().find(
'\n') != std::string::npos || !node.
constList()[i].commentAfter().empty())
505 std::string result = is_list ?
"[" : (
"(" +
format(node.
constList()[0], indent,
false));
506 for (std::size_t i = 0, end = formatted_args.size(); i < end; ++i)
508 const std::string& formatted_node = formatted_args[i];
511 if (i % 2 == 0 && formatted_args.size() > 2)
514 result +=
" " + formatted_node;
516 else if (is_multiline)
518 else if (is_list && i == 0)
519 result += formatted_node;
521 result +=
" " + formatted_node;
523 if (!node.
constList().back().commentAfter().empty())
524 result +=
"\n" +
prefix(indent);
526 result += is_list ?
"]" :
")";
535 std::string result =
"(macro ";
536 bool after_newline =
false;
538 for (std::size_t i = 0, end = node.
constList().size(); i < end; ++i)
541 after_newline =
false;
543 if (!node.
constList()[i].commentAfter().empty())
546 after_newline =
true;
548 else if (i != end - 1)
Common code for the compiler.
Constants used by ArkScript.
Tools to report code errors nicely to the user.
ArkScript homemade exceptions.
Lots of utilities about the filesystem.
A node of an Abstract Syntax Tree for ArkScript.
NodeType nodeType() const noexcept
Return the node type.
bool isListLike() const noexcept
Check if the node is a list like node.
const std::string & string() const noexcept
Return the string held by the value (if the node type allows it)
const std::vector< Node > & constList() const noexcept
Return the list of sub-nodes held by the node.
Keyword keyword() const noexcept
Return the keyword held by the value (if the node type allows it)
const std::string & comment() const noexcept
Return the comment attached to this node, if any.
FileSpan position() const noexcept
Get the span of the node (start and end)
const std::string & commentAfter() const noexcept
Return the comment attached after this node, if any.
double number() const noexcept
Return the number held by the value (if the node type allows it)
void process(const std::string &filename, const std::string &code)
Parse the given code.
const Node & ast() const noexcept
ARK_API void generate(const CodeError &e, std::ostream &os=std::cout, bool colorize=true)
Generate a diagnostic from an error and print it to the standard output.
std::string readFile(const std::string &name)
Helper to read a file.
@ Raw
Keep all text as is without modifying it (useful for the code formatter)
Keyword
The different keywords available.
constexpr std::array< std::string_view, 9 > keywords
List of available keywords in ArkScript.
CodeError thrown by the compiler (parser, macro processor, optimizer, and compiler itself)
std::size_t line
0-indexed line number