15 m_dry_run(dry_run), m_parser( 0, false), m_updated(false)
19 m_filename(std::move(filename)), m_dry_run(dry_run), m_parser( 0, false), m_updated(false)
70 for (std::size_t i = 1, end = ast.
constList().size(); i < end; ++i)
90 if (std::ranges::count(original_code,
'#') != std::ranges::count(
m_output,
'#'))
93 "{}: one or more comments from the original source code seem to have been removed by mistake while formatting {}",
94 fmt::styled(
"Warning", fmt::fg(fmt::color::dark_orange)),
96 fmt::println(
"Please fill an issue on GitHub: https://github.com/ArkScript-lang/Ark");
125 if (child_line < node.
line())
134 const std::string formatted =
format(node, 0,
false);
135 const std::string::size_type sz = formatted.find_first_of(
'\n');
153 const auto& child = list[at];
159 if (child.line() - previous_line > 1 && child.comment().empty())
163 if (child.line() - previous_line > 2 && !child.comment().empty())
174 after_newline =
true;
181 case NodeType::Symbol:
184 case NodeType::Capture:
187 case NodeType::Keyword:
190 case NodeType::String:
193 case NodeType::Number:
199 case NodeType::Spread:
202 case NodeType::Field:
205 for (std::size_t i = 1, end = node.
constList().size(); i < end; ++i)
210 case NodeType::Macro:
214 case NodeType::Namespace:
216 case NodeType::Unused:
229 for (std::size_t i = 0, end = comment.size(); i < end; ++i)
232 if (comment[i] ==
'\n' && i != end - 1)
245 if (first.
nodeType() == NodeType::Keyword)
263 case Keyword::Import:
279 std::string formatted_args;
281 if (!args_node.
comment().empty())
283 formatted_args +=
"\n";
285 formatted_args +=
prefix(indent + 1);
288 formatted_args +=
" ";
292 bool comment_in_args =
false;
294 for (std::size_t i = 0, end = args_node.
constList().size(); i < end; ++i)
298 comment_in_args =
true;
300 args +=
format(arg_i, indent + (comment_in_args ? 1 : 0), comment_in_args);
302 args += comment_in_args ?
'\n' :
' ';
305 formatted_args += fmt::format(
"({}{})", (comment_in_args ?
"\n" :
""), args);
308 formatted_args +=
format(args_node, indent,
false);
311 return fmt::format(
"(fun{} {})", formatted_args,
format(body_node, indent + 1,
false));
312 return fmt::format(
"(fun{}\n{})", formatted_args,
format(body_node, indent + 1,
true));
317 std::string keyword = std::string(
keywords[
static_cast<std::size_t
>(node.
constList()[0].keyword())]);
320 const std::string formatted_bind =
format(node.
constList()[1], indent,
false);
324 return fmt::format(
"({} {} {})", keyword, formatted_bind,
format(body_node, indent,
false));
326 return fmt::format(
"({} {} {})", keyword, formatted_bind,
format(body_node, indent + 1,
false));
327 return fmt::format(
"({} {}\n{})", keyword, formatted_bind,
format(body_node, indent + 1,
true));
335 bool cond_on_newline =
false;
336 std::string formatted_cond =
format(cond_node, indent + 1,
false);
337 if (formatted_cond.find(
'\n') != std::string::npos)
338 cond_on_newline =
true;
340 std::string if_cond_formatted = fmt::format(
343 cond_on_newline ?
"\n" :
" ",
351 if (cond_on_newline || split_then_newline)
352 return fmt::format(
"{}\n{})", if_cond_formatted,
format(then_node, indent + 1,
true));
353 return fmt::format(
"{} {})", if_cond_formatted,
format(then_node, indent + 1,
false));
359 format(then_node, indent + 1,
true),
361 node.
constList()[3].commentAfter().empty() ?
"" : (
"\n" +
prefix(indent)));
369 bool cond_on_newline =
false;
370 std::string formatted_cond =
format(cond_node, indent + 1,
false);
371 if (formatted_cond.find(
'\n') != std::string::npos)
372 cond_on_newline =
true;
377 cond_on_newline ?
"\n" :
" ",
379 format(body_node, indent + 1,
true));
383 format(body_node, indent + 1,
false));
394 const std::size_t inner_indentation = indent + (after_newline ? 1 : 0) + (indent == 0 ? 1 : 0);
396 std::string
output =
"{\n";
398 for (std::size_t i = 1, end = node.
constList().size(); i < end; ++i)
424 if (!package_node.
comment().empty())
425 package += "\n" + formatComment(package_node.comment(), indent + 1) + prefix(indent + 1);
429 for (std::size_t i = 0, end = package_node.
constList().size(); i < end; ++i)
431 package += format(package_node.constList()[i], indent + 1, false);
437 if (symbols.nodeType() == NodeType::Symbol && symbols.string() ==
"*")
441 if (const auto& sym_list = symbols.constList(); !sym_list.empty())
443 const bool comment_after_last = !sym_list.back().commentAfter().empty();
445 for (const auto& sym : sym_list)
447 if (sym.comment().empty())
449 if (comment_after_last)
450 package +=
"\n" + prefix(indent + 1) +
":" + sym.string();
452 package +=
" :" + sym.string();
455 package +=
"\n" + formatComment(sym.comment(), indent + 1) + prefix(indent + 1) +
":" + sym.string();
458 if (comment_after_last)
460 package +=
" " + formatComment(sym_list.back().commentAfter(), 0);
461 package +=
"\n" + prefix(indent + 1);
466 return fmt::format(
"(import{})", package);
471 std::string formatted_sym =
format(node.
constList()[1], indent + 1,
false);
472 if (formatted_sym.find(
'\n') != std::string::npos)
473 return fmt::format(
"(del\n{})", formatted_sym);
474 return fmt::format(
"(del {})", formatted_sym);
479 bool is_list =
false;
480 if (!node.
constList().empty() && node.
constList().front().nodeType() == NodeType::Symbol &&
481 node.
constList().front().string() ==
"list")
484 bool is_multiline =
false;
486 std::vector<std::string> formatted_args;
487 for (std::size_t i = 1, end = node.
constList().size(); i < end; ++i)
491 if (formatted_args.back().find(
'\n') != std::string::npos || !node.
constList()[i].commentAfter().empty())
496 for (std::size_t i = 0, end = formatted_args.size(); i < end; ++i)
498 const std::string formatted_node = formatted_args[i];
502 output += (is_list && i == 0 ?
"" :
" ") + formatted_node;
504 if (!node.
constList().back().commentAfter().empty())
506 output += is_list ?
"]" :
")";
515 std::string
output =
"($ ";
516 bool after_newline =
false;
518 for (std::size_t i = 0, end = node.
constList().size(); i < end; ++i)
521 after_newline =
false;
523 if (!node.
constList()[i].commentAfter().empty())
526 after_newline =
true;
528 else if (i != end - 1)
Common code for the compiler.
Constants used by ArkScript.
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.
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)
std::size_t line() const noexcept
Get the line at which this node was created.
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.
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)