Skip to content

Commit

Permalink
feat(formatter): adding a first version of an ArkScript code formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperFola committed Mar 31, 2024
1 parent a5dd4ad commit 2f188a7
Show file tree
Hide file tree
Showing 36 changed files with 846 additions and 13 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ if (ARK_TESTS)
add_executable(unittests ${UT_SOURCES})

add_subdirectory(${ark_SOURCE_DIR}/lib/ut)
target_include_directories(unittests PUBLIC ${ark_SOURCE_DIR}/include)
target_link_libraries(unittests PUBLIC ArkReactor termcolor ut)

add_compile_definitions(BOOST_UT_DISABLE_MODULE)
Expand Down
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,20 +186,35 @@ SYNOPSIS
arkscript --dev-info
arkscript -e <expression>
arkscript -c <file> [-d]
arkscript <file> [-d] [-L <lib_dir>]
arkscript -f <file> [--dry-run]
arkscript --ast <file> [-d] [-L <lib_dir>]
arkscript -bcr <file> -on
arkscript -bcr <file> -a [-s <start> <end>]
arkscript -bcr <file> -st [-s <start> <end>]
arkscript -bcr <file> -vt [-s <start> <end>]
arkscript -bcr <file> [-cs] [-p <page>] [-s <start> <end>]
arkscript <file> [-d] [-L <lib_dir>]

OPTIONS
-h, --help Display this message
-v, --version Display ArkScript version and exit
--dev-info Display development information and exit
-e, --eval Evaluate ArkScript expression

-c, --compile Compile the given program to bytecode, but do not run
-d, --debug... Increase debug level (default: 0)

-L, --lib Set the location of the ArkScript standard library. Paths can be
delimited by ';'

-f, --format Format the given source file in place
--dry-run Do not modify the file, only print out the changes

--ast Compile the given program and output its AST as JSON to stdout
-d, --debug... Increase debug level (default: 0)
-L, --lib Set the location of the ArkScript standard library. Paths can be
delimited by ';'

-bcr, --bytecode-reader Launch the bytecode reader
-on, --only-names Display only the bytecode segments names and sizes
-a, --all Display all the bytecode segments (default)
Expand All @@ -208,8 +223,9 @@ OPTIONS
-cs, --code Display only the code segments
-p, --page Set the bytecode reader code segment to display
-s, --slice Select a slice of instructions in the bytecode
-L, --lib Set the location of the ArkScript standard library. Paths can be
delimited by ';'

VERSION
4.0.0-86587c14

LICENSE
Mozilla Public License 2.0
Expand Down
79 changes: 79 additions & 0 deletions include/CLI/Formatter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#ifndef ARK_FORMATTER_HPP
#define ARK_FORMATTER_HPP

#include <string>

#include <Ark/Compiler/AST/Parser.hpp>

constexpr struct FormatterConfig
{
static constexpr std::size_t SpacePerIndent = 2; ///< Indentation level of each node
static constexpr std::size_t LongLineLength = 32; ///< Max number of characters per line segment to consider splitting
} FormatterConfig;

class Formatter final
{
public:
Formatter(std::string filename, bool dry_run);

void run();

[[nodiscard]] const std::string& output() const;

private:
const std::string m_filename;
bool m_dry_run; ///< If true, only prints the formatted file instead of saving it to disk
Ark::internal::Parser m_parser;
std::string m_output;

bool isListStartingWithKeyword(const Ark::internal::Node& node, Ark::internal::Keyword keyword);
bool isBeginBlock(const Ark::internal::Node& node);
bool isFuncDef(const Ark::internal::Node& node);
bool isFuncCall(const Ark::internal::Node& node);

/**
* @param node
* @return true if the node is a String|Number|Symbol|Field
* @return false
*/
bool isPlainValue(const Ark::internal::Node& node);

/**
* @brief Compute the line on which the deepest right most node of node is at
* @param node
* @return
*/
std::size_t lineOfLastNodeIn(const Ark::internal::Node& node);

bool should_split_on_newline(const Ark::internal::Node& node);

inline constexpr std::string prefix(std::size_t indent) const
{
return std::string(indent * FormatterConfig.SpacePerIndent, ' ');
}

/**
* @brief Handles all node formatting
* @param node
* @param indent indentation level, starting at 0, increment by 1
* @param after_newline when false, do not add prefix
* @return
*/
std::string format(const Ark::internal::Node& node, std::size_t indent, bool after_newline);

std::string formatComment(const std::string& comment, std::size_t indent);

std::string formatBlock(const Ark::internal::Node& node, std::size_t indent, bool after_newline);

std::string formatFunction(const Ark::internal::Node& node, std::size_t indent);
std::string formatVariable(const Ark::internal::Node& node, std::size_t indent);
std::string formatCondition(const Ark::internal::Node& node, std::size_t indent, bool is_macro = false);
std::string formatLoop(const Ark::internal::Node& node, std::size_t indent);
std::string formatBegin(const Ark::internal::Node& node, std::size_t indent, bool after_newline);
std::string formatImport(const Ark::internal::Node& node, std::size_t indent);
std::string formatDel(const Ark::internal::Node& node, std::size_t indent);
std::string formatCall(const Ark::internal::Node& node, std::size_t indent);
std::string formatMacro(const Ark::internal::Node& node, std::size_t indent);
};

#endif // ARK_FORMATTER_HPP
Loading

0 comments on commit 2f188a7

Please sign in to comment.