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 (lexplt.dev@gmail.com)
4  * @brief Handles the macros and their expansion in ArkScript source code
5  * @version 0.6
6  * @date 2021-02-18
7  *
8  * @copyright Copyright (c) 2021
9  *
10  */
11 
12 #ifndef COMPILER_MACROS_PROCESSOR_HPP
13 #define COMPILER_MACROS_PROCESSOR_HPP
14 
18 
19 #include <unordered_map>
20 #include <string>
21 #include <cinttypes>
22 
23 namespace Ark::internal
24 {
25  /**
26  * @brief The class handling the macros definitions and calls, given an AST
27  *
28  */
30  {
31  public:
32  /**
33  * @brief Construct a new Macro Processor object
34  *
35  * @param debug the debug level
36  * @param options the options flags
37  */
38  MacroProcessor(unsigned debug, uint16_t options) noexcept;
39 
40  /**
41  * @brief Send the complete AST (after the inclusions and stuff), and work on it
42  *
43  * @param ast
44  */
45  void feed(const Node& ast);
46 
47  /**
48  * @brief Return the modified AST
49  *
50  * @return Node&
51  */
52  const Node& ast() const noexcept;
53 
54  friend class MacroExecutor;
55 
56  private:
57  unsigned m_debug; ///< The debug level
58  uint16_t m_options;
59  Node m_ast; ///< The modified AST
60  std::vector<std::unordered_map<std::string, Node>> m_macros; ///< Handling macros in a scope fashion
62  std::vector<std::string> m_predefined_macros; ///< Already existing macros, non-keywords, non-builtins
63  std::unordered_map<std::string, Node> m_defined_functions;
64 
65  /**
66  * @brief Find the nearest macro matching a given name
67  *
68  * @param name
69  * @return Node* nullptr if no macro was found
70  */
71  Node* findNearestMacro(const std::string& name);
72 
73  /**
74  * @brief Find the nearest macro matching a given name and delete it
75  *
76  * @param name
77  */
78  void deleteNearestMacro(const std::string& name);
79 
80  /**
81  * @brief Check if a given symbol is a predefined macro or not
82  *
83  * @param symbol
84  * @return true
85  * @return false
86  */
87  bool isPredefined(const std::string& symbol);
88 
89  /**
90  * @brief Recursively apply macros on a given node
91  *
92  * @param node
93  */
94  void recurApply(Node& node);
95 
96  /**
97  * @brief Check if a given node is a list node, and starts with a Begin
98  *
99  * @param node
100  * @return true if it starts with a Begin
101  * @return false
102  */
103  bool hadBegin(const Node& node);
104 
105  /**
106  * @brief Remove a begin block added by a macro
107  *
108  * @param node
109  * @param i
110  */
111  void removeBegin(Node& node, std::size_t& i);
112 
113  /**
114  * @brief Check if a node can be evaluated at compile time
115  *
116  * @param node
117  * @return true
118  * @return false
119  */
120  bool isConstEval(const Node& node) const;
121 
122  /**
123  * @brief Registers macros based on their type
124  * @details Validate macros and register them by their name
125  *
126  * @param node A node of type Macro
127  */
128  void registerMacro(Node& node);
129 
130  /**
131  * @brief Registers a function definition node
132  *
133  * @param node
134  */
135  void registerFuncDef(Node& node);
136 
137  /**
138  * @brief Register macros in scopes and apply them as needed
139  *
140  * @param node node on which to operate
141  * @param depth
142  */
143  void process(Node& node, unsigned depth);
144 
145  /**
146  * @brief Apply a macro on a given node
147  *
148  * @param node
149  * @return true if a macro was applied
150  * @return false
151  */
152  bool applyMacro(Node& node);
153 
154  /**
155  * @brief Unify a target node with a given map symbol => replacement node, recursively
156  *
157  * @param map
158  * @param target
159  * @param parent
160  * @param index position of target inside parent->list()
161  */
162  void unify(const std::unordered_map<std::string, Node>& map, Node& target, Node* parent, std::size_t index = 0);
163 
164  /**
165  * @brief Evaluate only the macros
166  *
167  * @param node
168  * @param is_not_body true if the method is run on a non-body code (eg a condition of an if-macro)
169  * @return Node
170  */
171  Node evaluate(Node& node, bool is_not_body = false);
172 
173  /**
174  * @brief Check if a node can be evaluated to true
175  *
176  * @param node
177  * @return true
178  * @return false
179  */
180  bool isTruthy(const Node& node);
181 
182  /**
183  * @brief Throw a macro processing error
184  *
185  * @param message the error
186  * @param node the node in which there is an error
187  */
188  [[noreturn]] void throwMacroProcessingError(const std::string& message, const Node& node);
189  };
190 }
191 
192 #endif
The base class for all MacroExecutors.
AST node used by the parser, optimizer and compiler.
The Chain of Responsibility class for running nodes through MacroExecutors.
The class that initializes the MacroExecutors.
Definition: Pipeline.hpp:29
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:30
void removeBegin(Node &node, std::size_t &i)
Remove a begin block added by a macro.
Definition: Processor.cpp:563
MacroProcessor(unsigned debug, uint16_t options) noexcept
Construct a new Macro Processor object.
Definition: Processor.cpp:15
void process(Node &node, unsigned depth)
Register macros in scopes and apply them as needed.
Definition: Processor.cpp:132
void unify(const std::unordered_map< std::string, Node > &map, Node &target, Node *parent, std::size_t index=0)
Unify a target node with a given map symbol => replacement node, recursively.
Definition: Processor.cpp:218
const Node & ast() const noexcept
Return the modified AST.
Definition: Processor.cpp:46
MacroExecutorPipeline m_executor_pipeline
Definition: Processor.hpp:61
void recurApply(Node &node)
Recursively apply macros on a given node.
Definition: Processor.cpp:544
std::vector< std::string > m_predefined_macros
Already existing macros, non-keywords, non-builtins.
Definition: Processor.hpp:62
void registerMacro(Node &node)
Registers macros based on their type.
Definition: Processor.cpp:51
std::vector< std::unordered_map< std::string, Node > > m_macros
Handling macros in a scope fashion.
Definition: Processor.hpp:60
Node evaluate(Node &node, bool is_not_body=false)
Evaluate only the macros.
Definition: Processor.cpp:245
Node m_ast
The modified AST.
Definition: Processor.hpp:59
bool isTruthy(const Node &node)
Check if a node can be evaluated to true.
Definition: Processor.cpp:481
bool hadBegin(const Node &node)
Check if a given node is a list node, and starts with a Begin.
Definition: Processor.cpp:555
void throwMacroProcessingError(const std::string &message, const Node &node)
Throw a macro processing error.
Definition: Processor.cpp:624
std::unordered_map< std::string, Node > m_defined_functions
Definition: Processor.hpp:63
bool isConstEval(const Node &node) const
Check if a node can be evaluated at compile time.
Definition: Processor.cpp:583
bool isPredefined(const std::string &symbol)
Check if a given symbol is a predefined macro or not.
Definition: Processor.cpp:534
bool applyMacro(Node &node)
Apply a macro on a given node.
Definition: Processor.cpp:213
void feed(const Node &ast)
Send the complete AST (after the inclusions and stuff), and work on it.
Definition: Processor.cpp:30
Node * findNearestMacro(const std::string &name)
Find the nearest macro matching a given name.
Definition: Processor.cpp:499
void registerFuncDef(Node &node)
Registers a function definition node.
Definition: Processor.cpp:115
unsigned m_debug
The debug level.
Definition: Processor.hpp:57
void deleteNearestMacro(const std::string &name)
Find the nearest macro matching a given name and delete it.
Definition: Processor.cpp:515
A node of an Abstract Syntax Tree for ArkScript.
Definition: Node.hpp:29