ArkScript
A small, fast, functional and scripting language for video games
Processor.hpp
Go to the documentation of this file.
1/**
2 * @file Processor.hpp
3 * @author Alexandre Plateau ([email protected])
4 * @brief Handles the macros and their expansion in ArkScript source code
5 * @date 2021-02-18
6 *
7 * @copyright Copyright (c) 2021-2025
8 *
9 */
10
11#ifndef COMPILER_MACROS_PROCESSOR_HPP
12#define COMPILER_MACROS_PROCESSOR_HPP
13
14#include <Ark/Platform.hpp>
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) override;
47
48 /**
49 * @brief Return the modified AST
50 *
51 * @return Node&
52 */
53 [[nodiscard]] const Node& ast() const noexcept override;
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
65 /**
66 * @brief Return std::nullopt if the function isn't registered, otherwise return its node
67 *
68 * @param name function name
69 * @return std::optional<Node>
70 */
71 [[nodiscard]] std::optional<Node> lookupDefinedFunction(const std::string& name) const;
72
73 /**
74 * @brief Find the nearest macro matching a given name
75 *
76 * @param name
77 * @return const Node* nullptr if no macro was found
78 */
79 [[nodiscard]] const Node* findNearestMacro(const std::string& name) const;
80
81 /**
82 * @brief Find the nearest macro matching a given name and delete it
83 *
84 * @param name
85 */
86 void deleteNearestMacro(const std::string& name);
87
88 /**
89 * @brief Check if a given node is a list node, and starts with a Begin
90 *
91 * @param node
92 * @return true if it starts with a Begin
93 * @return false
94 */
95 static bool isBeginNode(const Node& node);
96
97 /**
98 * @brief Remove a begin block added by a macro
99 *
100 * @param node
101 * @param i
102 */
103 static void removeBegin(Node& node, std::size_t i);
104
105 /**
106 * @brief Check if a node can be evaluated at compile time
107 *
108 * @param node
109 * @return true
110 * @return false
111 */
112 [[nodiscard]] bool isConstEval(const Node& node) const;
113
114 /**
115 * @brief Registers macros based on their type, expand conditional macros
116 * @details Validate macros and register them by their name
117 *
118 * @param node A node of type Macro
119 */
120 void handleMacroNode(Node& node);
121
122 /**
123 * @brief Registers a function definition node
124 *
125 * @param node
126 */
127 void registerFuncDef(const Node& node);
128
129 /**
130 * @brief Register macros in scopes and apply them as needed
131 *
132 * @param node node on which to operate
133 * @param depth
134 * @param is_processing_namespace
135 */
136 void processNode(Node& node, unsigned depth, bool is_processing_namespace = false);
137
138 /**
139 * @brief Apply a macro on a given node
140 *
141 * @param node
142 * @param depth
143 * @return true if a macro was applied
144 * @return false
145 */
146 bool applyMacro(Node& node, unsigned depth);
147
148 /**
149 * @brief Check if the given node has exactly the provided argument count, otherwise throws an error
150 *
151 * @param node a list node with a macro application, eg (= a b)
152 * @param expected expected argument count, not counting the macro
153 * @param name the name of the macro being applied
154 * @param kind the macro kind, empty by default (eg "operator", "condition")
155 */
156 void checkMacroArgCountEq(const Node& node, std::size_t expected, const std::string& name, const std::string& kind = "");
157
158 /**
159 * @brief Check if the given node has at least the provided argument count, otherwise throws an error
160 *
161 * @param node a list node with a macro application, eg (= a b)
162 * @param expected expected argument count, not counting the macro
163 * @param name the name of the macro being applied
164 * @param kind the macro kind, empty by default (eg "operator", "condition")
165 */
166 void checkMacroArgCountGe(const Node& node, std::size_t expected, const std::string& name, const std::string& kind = "");
167
168 /**
169 * @brief Evaluate only the macros
170 *
171 * @param node
172 * @param depth
173 * @param is_not_body true if the method is run on a non-body code (eg a condition of an if-macro)
174 * @return Node
175 */
176 Node evaluate(Node& node, unsigned depth, bool is_not_body = false);
177
178 /**
179 * @brief Check if a node can be evaluated to true
180 *
181 * @param node
182 * @return true
183 * @return false
184 */
185 bool isTruthy(const Node& node);
186
187 /**
188 * @brief Throw a macro processing error
189 *
190 * @param message the error
191 * @param node the node in which there is an error
192 */
193 [[noreturn]] void throwMacroProcessingError(const std::string& message, const Node& node) const;
194 };
195}
196
197#endif
Defines tools to handle macro definitions.
#define ARK_API
Definition Module.hpp:28
AST node used by the parser, optimizer and compiler.
Interface for a compiler pass (take in an AST, output an AST)
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:30
An interface to describe compiler passes.
Definition Pass.hpp:23