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 * @version 3.0
6 * @date 2021-02-18
7 *
8 * @copyright Copyright (c) 2021-2024
9 *
10 */
11
12#ifndef COMPILER_MACROS_PROCESSOR_HPP
13#define COMPILER_MACROS_PROCESSOR_HPP
14
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 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::shared_ptr<MacroExecutor> m_conditional_executor;
61 std::vector<std::shared_ptr<MacroExecutor>> m_executors;
62 std::unordered_map<std::string, Node> m_defined_functions;
63
64 /**
65 * @brief Return std::nullopt if the function isn't registered, otherwise return its node
66 *
67 * @param name function name
68 * @return std::optional<Node>
69 */
70 [[nodiscard]] std::optional<Node> lookupDefinedFunction(const std::string& name) const;
71
72 /**
73 * @brief Find the nearest macro matching a given name
74 *
75 * @param name
76 * @return const Node* nullptr if no macro was found
77 */
78 [[nodiscard]] const Node* findNearestMacro(const std::string& name) const;
79
80 /**
81 * @brief Find the nearest macro matching a given name and delete it
82 *
83 * @param name
84 */
85 void deleteNearestMacro(const std::string& name);
86
87 /**
88 * @brief Check if a given node is a list node, and starts with a Begin
89 *
90 * @param node
91 * @return true if it starts with a Begin
92 * @return false
93 */
94 static bool isBeginNode(const Node& node);
95
96 /**
97 * @brief Remove a begin block added by a macro
98 *
99 * @param node
100 * @param i
101 */
102 static void removeBegin(Node& node, std::size_t i);
103
104 /**
105 * @brief Check if a node can be evaluated at compile time
106 *
107 * @param node
108 * @return true
109 * @return false
110 */
111 [[nodiscard]] bool isConstEval(const Node& node) const;
112
113 /**
114 * @brief Registers macros based on their type, expand conditional macros
115 * @details Validate macros and register them by their name
116 *
117 * @param node A node of type Macro
118 */
119 void handleMacroNode(Node& node);
120
121 /**
122 * @brief Registers a function definition node
123 *
124 * @param node
125 */
126 void registerFuncDef(const Node& node);
127
128 /**
129 * @brief Register macros in scopes and apply them as needed
130 *
131 * @param node node on which to operate
132 * @param depth
133 * @param is_processing_namespace
134 */
135 void processNode(Node& node, unsigned depth, bool is_processing_namespace = false);
136
137 /**
138 * @brief Apply a macro on a given node
139 *
140 * @param node
141 * @param depth
142 * @return true if a macro was applied
143 * @return false
144 */
145 bool applyMacro(Node& node, unsigned depth);
146
147 /**
148 * @brief Check if the given node has exactly the provided argument count, otherwise throws an error
149 *
150 * @param node a list node with a macro application, eg (= a b)
151 * @param expected expected argument count, not counting the macro
152 * @param name the name of the macro being applied
153 * @param kind the macro kind, empty by default (eg "operator", "condition")
154 */
155 static void checkMacroArgCountEq(const Node& node, std::size_t expected, const std::string& name, const std::string& kind = "");
156
157 /**
158 * @brief Check if the given node has at least the provided argument count, otherwise throws an error
159 *
160 * @param node a list node with a macro application, eg (= a b)
161 * @param expected expected argument count, not counting the macro
162 * @param name the name of the macro being applied
163 * @param kind the macro kind, empty by default (eg "operator", "condition")
164 */
165 static void checkMacroArgCountGe(const Node& node, std::size_t expected, const std::string& name, const std::string& kind = "");
166
167 /**
168 * @brief Evaluate only the macros
169 *
170 * @param node
171 * @param depth
172 * @param is_not_body true if the method is run on a non-body code (eg a condition of an if-macro)
173 * @return Node
174 */
175 Node evaluate(Node& node, unsigned depth, bool is_not_body = false);
176
177 /**
178 * @brief Check if a node can be evaluated to true
179 *
180 * @param node
181 * @return true
182 * @return false
183 */
184 static bool isTruthy(const Node& node);
185
186 /**
187 * @brief Throw a macro processing error
188 *
189 * @param message the error
190 * @param node the node in which there is an error
191 */
192 [[noreturn]] static void throwMacroProcessingError(const std::string& message, const Node& node);
193 };
194}
195
196#endif
Defines tools to handle macro definitions.
AST node used by the parser, optimizer and compiler.
Interface for a compiler pass (take in an AST, output an AST)
A class that applies macros in a Node.
Definition Executor.hpp:29
The class handling the macros definitions and calls, given an AST.
Definition Processor.hpp:32
Node evaluate(Node &node, unsigned depth, bool is_not_body=false)
Evaluate only the macros.
void registerFuncDef(const Node &node)
Registers a function definition node.
Definition Processor.cpp:78
const Node & ast() const noexcept override
Return the modified AST.
Definition Processor.cpp:45
std::shared_ptr< MacroExecutor > m_conditional_executor
Definition Processor.hpp:60
bool applyMacro(Node &node, unsigned depth)
Apply a macro on a given node.
static bool isBeginNode(const Node &node)
Check if a given node is a list node, and starts with a Begin.
static void removeBegin(Node &node, std::size_t i)
Remove a begin block added by a macro.
std::optional< Node > lookupDefinedFunction(const std::string &name) const
Return std::nullopt if the function isn't registered, otherwise return its node.
const Node * findNearestMacro(const std::string &name) const
Find the nearest macro matching a given name.
Node m_ast
The modified AST.
Definition Processor.hpp:58
static bool isTruthy(const Node &node)
Check if a node can be evaluated to true.
static void throwMacroProcessingError(const std::string &message, const Node &node)
Throw a macro processing error.
std::unordered_map< std::string, Node > m_defined_functions
Definition Processor.hpp:62
bool isConstEval(const Node &node) const
Check if a node can be evaluated at compile time.
std::vector< std::shared_ptr< MacroExecutor > > m_executors
Definition Processor.hpp:61
void process(const Node &ast) override
Send the complete AST and work on it.
Definition Processor.cpp:30
MacroProcessor(unsigned debug) noexcept
Construct a new Macro Processor object.
Definition Processor.cpp:20
void processNode(Node &node, unsigned depth, bool is_processing_namespace=false)
Register macros in scopes and apply them as needed.
std::vector< MacroScope > m_macros
Handling macros in a scope fashion.
Definition Processor.hpp:59
static void checkMacroArgCountGe(const Node &node, std::size_t expected, const std::string &name, const std::string &kind="")
Check if the given node has at least the provided argument count, otherwise throws an error.
static void checkMacroArgCountEq(const Node &node, std::size_t expected, const std::string &name, const std::string &kind="")
Check if the given node has exactly the provided argument count, otherwise throws an error.
void handleMacroNode(Node &node)
Registers macros based on their type, expand conditional macros.
Definition Processor.cpp:50
void deleteNearestMacro(const std::string &name)
Find the nearest macro matching a given name and delete it.
A node of an Abstract Syntax Tree for ArkScript.
Definition Node.hpp:31
An interface to describe compiler passes.
Definition Pass.hpp:23