ArkScript
A small, fast, functional and scripting language for video games
Optimizer.cpp
Go to the documentation of this file.
2 
3 namespace Ark::internal
4 {
5  Optimizer::Optimizer(uint16_t options) noexcept :
6  m_options(options)
7  {}
8 
9  void Optimizer::feed(const Node& ast)
10  {
11  m_ast = ast;
12 
14  remove_unused();
15  }
16 
17  const Node& Optimizer::ast() const noexcept
18  {
19  return m_ast;
20  }
21 
22  void Optimizer::throwOptimizerError(const std::string& message, const Node& node)
23  {
24  throw OptimizerError(makeNodeBasedErrorCtx(message, node));
25  }
26 
28  {
29  // do not handle non-list nodes
30  if (m_ast.nodeType() != NodeType::List)
31  return;
32 
33  runOnGlobalScopeVars(m_ast, [this](Node& node, Node& parent [[maybe_unused]], int idx [[maybe_unused]]) {
34  m_sym_appearances[node.constList()[1].string()] = 0;
35  });
37 
38  // logic: remove piece of code with only 1 reference, if they aren't function calls
39  runOnGlobalScopeVars(m_ast, [this](Node& node, Node& parent, int idx) {
40  std::string name = node.constList()[1].string();
41  // a variable was only declared and never used
42  if (m_sym_appearances.find(name) != m_sym_appearances.end() && m_sym_appearances[name] == 1 && parent.list()[idx].list()[2].nodeType() != NodeType::List)
43  parent.list().erase(parent.list().begin() + idx); // erase the node from the list
44  });
45  }
46 
47  void Optimizer::runOnGlobalScopeVars(Node& node, const std::function<void(Node&, Node&, int)>& func)
48  {
49  int i = static_cast<int>(node.constList().size());
50  // iterate only on the first level, using reverse iterators to avoid copy-delete-move to nowhere
51  for (auto it = node.list().rbegin(); it != node.list().rend(); ++it)
52  {
53  i--;
54 
55  if (it->constList().size() > 0 && it->constList()[0].nodeType() == NodeType::Keyword)
56  {
57  Keyword kw = it->constList()[0].keyword();
58 
59  // eliminate nested begin blocks
60  if (kw == Keyword::Begin)
61  {
62  runOnGlobalScopeVars(*it, func);
63  // skip let/ mut detection
64  continue;
65  }
66  // check if it's a let/mut declaration
67  else if (kw == Keyword::Let || kw == Keyword::Mut)
68  func(*it, node, i);
69  }
70  }
71  }
72 
74  {
75  if (node.nodeType() == NodeType::Symbol || node.nodeType() == NodeType::Capture)
76  {
77  std::string name = node.string();
78  // check if it's the name of something declared in global scope
79  if (m_sym_appearances.find(name) != m_sym_appearances.end())
80  m_sym_appearances[name]++;
81  }
82  else if (node.nodeType() == NodeType::List)
83  {
84  // iterate over children
85  for (std::size_t i = 0, end = node.constList().size(); i != end; ++i)
86  countOccurences(node.list()[i]);
87  }
88  }
89 }
Optimizes a given ArkScript AST.
OptimizerError thrown by the AST optimizer.
Definition: Exceptions.hpp:107
A node of an Abstract Syntax Tree for ArkScript.
Definition: Node.hpp:29
NodeType nodeType() const noexcept
Return the node type.
Definition: Node.cpp:126
const std::string & string() const noexcept
Return the string held by the value (if the node type allows it)
Definition: Node.cpp:92
const std::vector< Node > & constList() const noexcept
Return the list of sub-nodes held by the node.
Definition: Node.cpp:119
std::vector< Node > & list() noexcept
Return the list of sub-nodes held by the node.
Definition: Node.cpp:114
void feed(const Node &ast)
Send the AST to the optimizer, then run the different optimization strategies on it.
Definition: Optimizer.cpp:9
void throwOptimizerError(const std::string &message, const Node &node)
Generate a fancy error message.
Definition: Optimizer.cpp:22
void remove_unused()
Iterate over the AST and remove unused top level functions and constants.
Definition: Optimizer.cpp:27
const Node & ast() const noexcept
Returns the modified AST.
Definition: Optimizer.cpp:17
Optimizer(uint16_t options) noexcept
Construct a new Optimizer.
Definition: Optimizer.cpp:5
void countOccurences(Node &node)
Count the occurences of each symbol in the AST, recursively.
Definition: Optimizer.cpp:73
void runOnGlobalScopeVars(Node &node, const std::function< void(Node &, Node &, int)> &func)
Run a given functor on the global scope symbols.
Definition: Optimizer.cpp:47
std::unordered_map< std::string, unsigned > m_sym_appearances
Definition: Optimizer.hpp:57
std::string makeNodeBasedErrorCtx(const std::string &message, const Node &node)
Construct an error message based on a given node.
Keyword
The different keywords available.
Definition: Common.hpp:59
constexpr uint16_t FeatureRemoveUnusedVars
Definition: Constants.hpp:48