tan  0.0.1
analysis_action.h
1 #ifndef __TAN_ANALYSIS_ANALYSIS_ACTION_H__
2 #define __TAN_ANALYSIS_ANALYSIS_ACTION_H__
3 
4 #include "ast/ast_node_type.h"
5 #include "common/compiler_action.h"
6 #include "ast/decl.h"
7 #include "ast/context.h"
8 
9 namespace tanlang {
10 
11 template <typename Derived, typename Input, typename Output>
12 class SemanticAnalysisAction : public CompilerAction<Derived, Input, Output> {
13 protected:
14  [[noreturn]] void error(ErrorType type, ASTBase *p, const str &message) {
15  auto *src = p->src();
16  Error(type, src->get_token(p->start()), src->get_token(p->end()), message).raise();
17  }
18 
19  void push_scope(ASTBase *scope) { _scopes.push_back(scope); }
20 
21  void pop_scope() {
22  TAN_ASSERT(!_scopes.empty());
23  _scopes.pop_back();
24  }
25 
26  Context *ctx() {
27  TAN_ASSERT(!_scopes.empty());
28  return _scopes.back()->ctx();
29  }
30 
31  Context *top_ctx() {
32  TAN_ASSERT(!_scopes.empty());
33  return _scopes.front()->ctx();
34  }
35 
36  Decl *search_decl_in_scopes(const str &name) {
37  int n = (int)_scopes.size();
38  TAN_ASSERT(n);
39  Decl *ret = nullptr;
40  for (int i = n - 1; i >= 0; --i) {
41  Context *c = _scopes[(size_t)i]->ctx();
42  ret = c->get_decl(name);
43  if (ret)
44  return ret;
45  }
46 
47  return ret;
48  }
49 
50  template <typename T, ASTNodeType node_type> T *search_node_in_parent_scopes() {
51  int n = (int)_scopes.size();
52  TAN_ASSERT(n);
53  for (int i = n - 1; i >= 0; --i) {
54  auto *node = _scopes[(size_t)i];
55  if (node->get_node_type() == node_type) {
56  return pcast<T>(node);
57  }
58  }
59 
60  return nullptr;
61  }
62 
63 private:
64  friend Derived;
65  SemanticAnalysisAction() = default;
66 
67 private:
68  vector<ASTBase *> _scopes{};
69 };
70 
71 } // namespace tanlang
72 
73 #endif //__TAN_ANALYSIS_ANALYSIS_ACTION_H__
Decl * get_decl(const str &name) const
Search for a declaration by name.
Definition: context.cpp:15