tan  0.0.1
register_declarations.cpp
1 #include "analysis/register_declarations.h"
2 #include "ast/intrinsic.h"
3 #include "ast/stmt.h"
4 #include "ast/type.h"
5 #include "ast/package.h"
6 #include <iostream>
7 
8 namespace tanlang {
9 
10 void RegisterDeclarations::run_impl(Program *p) { visit(p); }
11 
12 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, Program) {
13  push_scope(p);
14 
15  for (const auto &c : p->get_children()) {
16  visit(c);
17  }
18 
19  pop_scope();
20 }
21 
22 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, Intrinsic) {
23  // check children if this is @test_comp_error
24  if (p->get_intrinsic_type() == IntrinsicType::TEST_COMP_ERROR) {
25  _within_test_comp_error = true;
26 
27  auto *tce = pcast<TestCompError>(p->get_sub());
28  if (tce->_caught)
29  return;
30 
31  push_scope(p);
32 
33  try {
34  for (auto *c : tce->get_children())
35  visit(c);
36  } catch (const CompileException &e) {
37  std::cerr << fmt::format("Caught expected compile error: {}\nContinue compilation...\n", e.what());
38  tce->_caught = true;
39  }
40 
41  pop_scope();
42  _within_test_comp_error = false;
43  }
44 }
45 
46 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, Parenthesis) { visit(p->get_sub()); }
47 
48 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, If) {
49  size_t n = p->get_num_branches();
50  for (size_t i = 0; i < n; ++i) {
51  auto *cond = p->get_predicate(i);
52  if (cond) { /// can be nullptr, meaning an "else" branch
53  visit(cond);
54  }
55 
56  visit(p->get_branch(i));
57  }
58 }
59 
60 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, VarDecl) {
61  str name = p->get_name();
62  if (ctx()->get_decl(name)) {
63  error(ErrorType::SEMANTIC_ERROR, p, fmt::format("Cannot redeclare variable named {}", name));
64  }
65 
66  ctx()->set_decl(name, p);
67 }
68 
69 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, ArgDecl) {
70  str name = p->get_name();
71  if (ctx()->get_decl(name)) {
72  error(ErrorType::SEMANTIC_ERROR, p, fmt::format("Cannot redeclare argument named {}", name));
73  }
74 
75  ctx()->set_decl(name, p);
76 }
77 
78 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, CompoundStmt) {
79  push_scope(p);
80  for (const auto &c : p->get_children()) {
81  visit(c);
82  }
83  pop_scope();
84 }
85 
86 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, BinaryOrUnary) { visit(p->get_expr_ptr()); }
87 
88 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, BinaryOperator) {
89  visit(p->get_lhs());
90  visit(p->get_rhs());
91 }
92 
93 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, UnaryOperator) { visit(p->get_rhs()); }
94 
95 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, Assignment) {
96  visit(p->get_rhs());
97  visit(p->get_lhs());
98 }
99 
100 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, FunctionDecl) {
101  register_public_func_decl(p);
102 
103  push_scope(p);
104 
105  size_t n = p->get_n_args();
106  const auto &arg_decls = p->get_arg_decls();
107  for (size_t i = 0; i < n; ++i) {
108  visit(arg_decls[i]);
109  }
110 
111  if (!p->is_external()) {
112  visit(p->get_body());
113  }
114 
115  pop_scope();
116 }
117 
118 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, StructDecl) {
119  // check if struct name is in conflicts of variable/function names
120  str struct_name = p->get_name();
121  auto *root_ctx = top_ctx();
122  auto *prev_decl = root_ctx->get_decl(struct_name);
123  if (prev_decl && prev_decl != p) {
124  error(ErrorType::SEMANTIC_ERROR, p, "Cannot redeclare a struct");
125  }
126 
127  register_public_type_decl(struct_name, p);
128 
129  // Create the type first and it will be modified later. Doing this allows recursive type reference
130  p->set_type(Type::GetStructType(p));
131 }
132 
133 DEFINE_AST_VISITOR_IMPL(RegisterDeclarations, Loop) {
134  push_scope(p);
135 
136  if (p->_loop_type == ASTLoopType::FOR) {
137  visit(p->_initialization);
138  }
139  // visit(p->_predicate);
140  // visit(p->_iteration);
141  visit(p->_body);
142 
143  pop_scope();
144 }
145 
146 void RegisterDeclarations::register_public_type_decl(const str &name, TypeDecl *decl) {
147  if (!_within_test_comp_error) {
148  top_ctx()->set_decl(name, decl);
149  }
150 }
151 
152 void RegisterDeclarations::register_public_func_decl(FunctionDecl *decl) {
153  if (!_within_test_comp_error) {
154  top_ctx()->set_function_decl(decl);
155  }
156 }
157 
158 } // namespace tanlang
void set_decl(const str &name, Decl *decl)
Register a type declaration.
Definition: context.cpp:10
void set_function_decl(FunctionDecl *func)
Register a function declaration.
Definition: context.cpp:41