ArkScript
A small, lisp-inspired, functional scripting language
Processor.hpp
Go to the documentation of this file.
1/**
2 * @file Processor.hpp
3 * @author Lexy Plateau (lexplt.dev@gmail.com)
4 * @brief Handles the macros and their expansion in ArkScript source code
5 * @date 2021-02-18
6 *
7 * @copyright Copyright (c) 2021-2026
8 *
9 */
10
11#ifndef COMPILER_MACROS_PROCESSOR_HPP
12#define COMPILER_MACROS_PROCESSOR_HPP
13
17#include <Ark/Compiler/Pass.hpp>
18
19#include <unordered_map>
20#include <optional>
21#include <string>
22
23namespace Ark::internal
24{
25 class MacroExecutor;
26
27 /**
28 * @brief The class handling the macros definitions and calls, given an AST
29 *
30 */
31 class ARK_API MacroProcessor final : public Pass
32 {
33 public:
34 /**
35 * @brief Construct a new Macro Processor object
36 *
37 * @param debug the debug level
38 */
39 explicit MacroProcessor(unsigned debug) noexcept;
40
41 /**
42 * @brief Send the complete AST and work on it
43 *
44 * @param ast
45 */
46 void process(const Node& ast);
47
48 /**
49 * @brief Return the modified AST
50 *
51 * @return Node&
52 */
53 [[nodiscard]] const Node& ast() const noexcept;
54
55 friend class MacroExecutor;
56
57 private:
58 Node m_ast; ///< The modified AST
59 std::vector<MacroScope> m_macros; ///< Handling macros in a scope fashion
60 std::vector<Node> m_macros_being_applied; ///< Stack of macros being applied. The last one is the current one we are working on
61 std::shared_ptr<MacroExecutor> m_conditional_executor;
62 std::vector<std::shared_ptr<MacroExecutor>> m_executors;
63 std::unordered_map<std::string, Node> m_defined_functions;
64 std::size_t m_genned_sym;
65
66 /**
67 * @brief Return std::nullopt if the function isn't registered, otherwise return its node
68 *
69 * @param name function name
70 * @return std::optional<Node>
71 */
72 [[nodiscard]] std::optional<Node> lookupDefinedFunction(const std::string& name) const;
73
74 /**
75 * @brief Find the nearest macro matching a given name
76 *
77 * @param name
78 * @return const Node* nullptr if no macro was found
79 */
80 [[nodiscard]] const Node* findNearestMacro(const std::string& name) const;
81
82 /**
83 * @brief Find the nearest macro matching a given name and delete it
84 *
85 * @param name
86 */
87 void deleteNearestMacro(const std::string& name);
88
89 /**
90 * @brief Check if a given node is a list node, and starts with a Begin
91 *
92 * @param node
93 * @return true if it starts with a Begin
94 * @return false
95 */
96 static bool isBeginNode(const Node& node);
97
98 /**
99 * @brief Remove a begin block added by a macro
100 *
101 * @param node
102 * @param i
103 */
104 static void removeBegin(Node& node, std::size_t i);
105
106 /**
107 * @brief Registers macros based on their type, expand conditional macros
108 * @details Validate macros and register them by their name
109 *
110 * @param node A node of type Macro
111 * @param depth
112 */
113 void handleMacroNode(Node& node, unsigned depth);
114
115 /**
116 * @brief Registers a function definition node
117 *
118 * @param node
119 */
120 void registerFuncDef(const Node& node);
121
122 /**
123 * @brief Register macros in scopes and apply them as needed
124 *
125 * @param node node on which to operate
126 * @param depth
127 * @param is_processing_namespace
128 */
129 void processNode(Node& node, unsigned depth, bool is_processing_namespace = false);
130
131 /**
132 * @brief Apply a macro on a given node
133 *
134 * @param node
135 * @param depth
136 * @return true if a macro was applied
137 * @return false
138 */
139 bool applyMacro(Node& node, unsigned depth);
140
141 /**
142 * @brief Check if the given node has exactly the provided argument count, otherwise throws an error
143 *
144 * @param node a list node with a macro application, eg (= a b)
145 * @param expected expected argument count, not counting the macro
146 * @param name the name of the macro being applied
147 * @param is_expansion if the error message should switch from "Interpreting ..." to "When expanding ..."
148 * @param kind the macro kind, empty by default (eg "operator", "condition")
149 */
150 void checkMacroArgCountEq(const Node& node, std::size_t expected, const std::string& name, bool is_expansion = false, const std::string& kind = "") const;
151
152 /**
153 * @brief Check if the given node has at least the provided argument count, otherwise throws an error
154 *
155 * @param node a list node with a macro application, eg (= a b)
156 * @param expected expected argument count, not counting the macro
157 * @param name the name of the macro being applied
158 * @param kind the macro kind, empty by default (eg "operator", "condition")
159 */
160 void checkMacroArgCountGe(const Node& node, std::size_t expected, const std::string& name, const std::string& kind = "") const;
161
162 /**
163 * @brief Evaluate only the macros
164 *
165 * @param node
166 * @param depth
167 * @param is_not_body true if the method is run on a non-body code (eg a condition of an if-macro)
168 * @return Node
169 */
170 Node evaluate(Node& node, unsigned depth, bool is_not_body = false);
171
172 /**
173 * @brief Check if a node can be evaluated to true
174 *
175 * @param node
176 * @return true
177 * @return false
178 */
179 [[nodiscard]] bool isTruthy(const Node& node) const;
180
181 /**
182 * @brief Throw a macro processing error
183 *
184 * @param message the error
185 * @param node the node in which there is an error
186 */
187 [[noreturn]] void throwMacroProcessingError(const std::string& message, const Node& node) const;
188
189 void checkMacroTypeError(const std::string& macro, const std::string& arg, NodeType expected, const Node& actual) const;
190 };
191}
192
193#endif
Defines tools to handle macro definitions.
#define ARK_API
Definition Module.hpp:22
AST node used by the parser, optimizer and compiler.
Interface for a compiler pass.
ArkScript configuration macros.
A class that applies macros in a Node.
Definition Executor.hpp:28
The class handling the macros definitions and calls, given an AST.
Definition Processor.hpp:32
std::shared_ptr< MacroExecutor > m_conditional_executor
Definition Processor.hpp:61
std::vector< Node > m_macros_being_applied
Stack of macros being applied. The last one is the current one we are working on.
Definition Processor.hpp:60
Node m_ast
The modified AST.
Definition Processor.hpp:58
std::unordered_map< std::string, Node > m_defined_functions
Definition Processor.hpp:63
std::vector< std::shared_ptr< MacroExecutor > > m_executors
Definition Processor.hpp:62
std::vector< MacroScope > m_macros
Handling macros in a scope fashion.
Definition Processor.hpp:59
A node of an Abstract Syntax Tree for ArkScript.
Definition Node.hpp:32
An interface to describe compiler passes.
Definition Pass.hpp:24
NodeType
The different node types available.
Definition Common.hpp:44