Joos1W Compiler Framework
All Classes Functions Typedefs Pages
VisitClassInterface.cc
1 #include <utility>
2 #include "ast/AST.h"
3 #include "parsetree/ParseTree.h"
4 #include "parsetree/ParseTreeVisitor.h"
5 
6 namespace parsetree {
7 
8 using pty = Node::Type;
9 using ptv = ParseTreeVisitor;
10 
11 // pty::ClassDeclaration ///////////////////////////////////////////////////////
12 
13 ast::ClassDecl* ptv::visitClassDeclaration(Node* node) {
14  sem.ResetFieldScope();
15  check_node_type(node, pty::ClassDeclaration);
16  check_num_children(node, 5, 5);
17  // $1: Visit the modifiers
18  ast::Modifiers modifiers = visitModifierList(node->child(0), ast::Modifiers{});
19  // $3: Visit identifier
20  auto nameNode = node->child(1);
21  auto name = visitIdentifier(node->child(1));
22  // $4: Visit SuperOpt
23  auto super = visitSuperOpt(node->child(2));
24  // $5: Visit InterfaceTypeList
25  ast::pmr_vector<ast::ReferenceType*> interfaces;
26  visitListPattern<pty::InterfaceTypeList, ast::ReferenceType*, true>(
27  node->child(3), interfaces);
28  // $6: Visit ClassBody
29  ast::pmr_vector<ast::Decl*> classBodyDeclarations;
30  visitListPattern<pty::ClassBodyDeclarationList, ast::Decl*, true>(
31  node->child(4), classBodyDeclarations);
32  // Return the constructed AST node
33  return sem.BuildClassDecl(modifiers,
34  nameNode->location(),
35  name,
36  super,
37  interfaces,
38  classBodyDeclarations);
39 }
40 
41 ast::ReferenceType* ptv::visitSuperOpt(Node* node) {
42  if(node == nullptr) return nullptr;
43  check_node_type(node, pty::SuperOpt);
44  check_num_children(node, 1, 1);
45  return visitReferenceType(node->child(0));
46 }
47 
48 template <>
49 ast::ReferenceType* ptv::visit<pty::InterfaceTypeList>(Node* node) {
50  return visitReferenceType(node);
51 }
52 
53 template <>
54 ast::Decl* ptv::visit<pty::ClassBodyDeclarationList>(Node* node) {
55  auto nodety = node->get_node_type();
56  switch(nodety) {
57  case pty::FieldDeclaration:
58  return visitFieldDeclaration(node);
59  case pty::MethodDeclaration:
60  return visitMethodDeclaration(node);
61  case pty::ConstructorDeclaration:
62  return visitConstructorDeclaration(node);
63  default:
64  std::unreachable();
65  }
66 }
67 
68 // pty::FieldDeclaration ///////////////////////////////////////////////////////
69 
70 ast::FieldDecl* ptv::visitFieldDeclaration(Node* node) {
71  check_node_type(node, pty::FieldDeclaration);
72  check_num_children(node, 3, 3);
73  // $1: Visit the modifiers
74  auto modifiers = visitModifierList(node->child(0));
75  // $2, $3: Visit the type and declarator
76  auto decl = visitVariableDeclarator(node->child(1), node->child(2));
77  // Replace the scope with the field scope
78  if(decl.init) decl.init->setScope(sem.CurrentFieldScopeID());
79  return sem.BuildFieldDecl(modifiers, decl.loc, decl.type, decl.name, decl.init);
80 }
81 
82 // pty::MethodDeclaration //////////////////////////////////////////////////////
83 
84 ast::MethodDecl* ptv::visitMethodDeclaration(Node* node) {
85  check_node_type(node, pty::MethodDeclaration);
86  check_num_children(node, 2, 2);
87 
88  // Reset the lexical local scope
90 
91  // $1: Visit the header
92  auto pt_header = node->child(0);
93  check_node_type(pt_header, pty::MethodHeader);
94  check_num_children(pt_header, 3, 4);
95  ast::Modifiers modifiers;
96  ast::Type* type = nullptr;
97  std::string name;
98  ast::pmr_vector<ast::VarDecl*> params;
99  Node* nameNode = nullptr;
100  if(pt_header->num_children() == 3) {
101  // $1: Visit the modifiers
102  modifiers = visitModifierList(pt_header->child(0));
103  // The type is void
104  type = nullptr;
105  // $2: Visit the identifier
106  name = visitIdentifier(pt_header->child(1));
107  nameNode = pt_header->child(1);
108  // $3: Visit the formal parameters
109  visitListPattern<pty::FormalParameterList, ast::VarDecl*, true>(
110  pt_header->child(2), params);
111  } else if(pt_header->num_children() == 4) {
112  // $1: Visit the modifiers
113  modifiers = visitModifierList(pt_header->child(0));
114  // $2: Visit the type
115  type = visitType(pt_header->child(1));
116  // $3: Visit the identifier
117  name = visitIdentifier(pt_header->child(2));
118  nameNode = pt_header->child(2);
119  // $4: Visit the formal parameters
120  visitListPattern<pty::FormalParameterList, ast::VarDecl*, true>(
121  pt_header->child(3), params);
122  }
123 
124  // $2: Visit the body
125  auto pt_body = node->child(1);
126  ast::Stmt* body = nullptr;
127  if(pt_body != nullptr) {
128  body = visitBlock(pt_body);
129  }
130 
131  // Return the constructed AST node
132  auto ast = sem.BuildMethodDecl(
133  modifiers, nameNode->location(), name, type, params, false, body);
134  ast->addDecls(sem.getAllLexicalDecls());
135  return ast;
136 }
137 
138 ast::MethodDecl* ptv::visitConstructorDeclaration(Node* node) {
139  check_node_type(node, pty::ConstructorDeclaration);
140  check_num_children(node, 4, 4);
141 
142  // Reset the lexical local scope
144 
145  // $1: Visit the modifiers
146  auto modifiers = visitModifierList(node->child(0));
147  // $2: Visit the identifier
148  auto nameNode = node->child(1);
149  auto name = visitIdentifier(nameNode);
150  // $3: Visit the formal parameters
151  ast::pmr_vector<ast::VarDecl*> params;
152  visitListPattern<pty::FormalParameterList, ast::VarDecl*, true>(node->child(2),
153  params);
154  // $4: Visit the body
155  ast::Stmt* body = nullptr;
156  if(node->child(3) != nullptr) {
157  body = visitBlock(node->child(3));
158  }
159  // Create the AST and attach the lexical local declarations
160  auto ast = sem.BuildMethodDecl(
161  modifiers, nameNode->location(), name, nullptr, params, true, body);
162  ast->addDecls(sem.getAllLexicalDecls());
163  return ast;
164 }
165 
166 template <>
167 ast::VarDecl* ptv::visit<pty::FormalParameterList>(Node* node) {
168  check_node_type(node, pty::FormalParameter);
169  check_num_children(node, 2, 2);
170  // $1: Visit the type
171  auto type = visitType(node->child(0));
172  // $2: Visit the identifier
173  auto nameNode = node->child(1);
174  auto name = visitIdentifier(nameNode);
175  // Return the constructed AST node
176  return sem.BuildVarDecl(type, nameNode->location(), name, sem.NextScopeID());
177 }
178 
179 // pty::InterfaceDeclaration ///////////////////////////////////////////////////
180 
181 ast::InterfaceDecl* ptv::visitInterfaceDeclaration(Node* node) {
182  sem.ResetFieldScope();
183  check_node_type(node, pty::InterfaceDeclaration);
184  check_num_children(node, 4, 4);
185  // $1: Visit the modifiers
186  ast::Modifiers modifiers = visitModifierList(node->child(0), ast::Modifiers{});
187  // $2: Visit identifier
188  auto nameNode = node->child(1);
189  auto name = visitIdentifier(node->child(1));
190  // $3: Visit ExtendsInterfacesOpt
191  ast::pmr_vector<ast::ReferenceType*> extends;
192  visitListPattern<pty::InterfaceTypeList, ast::ReferenceType*, true>(
193  node->child(2), extends);
194  // $4: Visit InterfaceBody
195  ast::pmr_vector<ast::Decl*> interfaceBodyDeclarations;
196  visitListPattern<pty::InterfaceMemberDeclarationList, ast::Decl*, true>(
197  node->child(3), interfaceBodyDeclarations);
198  // Return the constructed AST node
199  return sem.BuildInterfaceDecl(modifiers,
200  nameNode->location(),
201  name,
202  extends,
203  interfaceBodyDeclarations);
204 }
205 
206 template <>
207 ast::Decl* ptv::visit<pty::InterfaceMemberDeclarationList>(Node* node) {
208  return visitAbstractMethodDeclaration(node);
209 }
210 
211 // pty::AbstractMethodDeclaration //////////////////////////////////////////////
212 
213 ast::MethodDecl* ptv::visitAbstractMethodDeclaration(Node* node) {
214  check_node_type(node, pty::AbstractMethodDeclaration);
215  check_num_children(node, 3, 4);
216 
217  // Reset the lexical local scope
219 
220  ast::Modifiers modifiers;
221  ast::Type* type = nullptr;
222  std::string name;
223  ast::pmr_vector<ast::VarDecl*> params;
224  Node* nameNode = nullptr;
225  if(node->num_children() == 3) {
226  // $1: Visit the modifiers
227  modifiers = visitModifierList(node->child(0));
228  // The type is void
229  type = nullptr;
230  // $2: Visit the identifier
231  nameNode = node->child(1);
232  name = visitIdentifier(node->child(1));
233  // $3: Visit the formal parameters
234  visitListPattern<pty::FormalParameterList, ast::VarDecl*, true>(
235  node->child(2), params);
236  } else if(node->num_children() == 4) {
237  // $1: Visit the modifiers
238  modifiers = visitModifierList(node->child(0));
239  // $2: Visit the type
240  type = visitType(node->child(1));
241  // $3: Visit the identifier
242  nameNode = node->child(2);
243  name = visitIdentifier(node->child(2));
244  // $4: Visit the formal parameters
245  visitListPattern<pty::FormalParameterList, ast::VarDecl*, true>(
246  node->child(3), params);
247  }
248  // Set as abstract
249  modifiers.set(ast::Modifiers::Type::Abstract);
250  // Return the constructed AST node
251  auto ast = sem.BuildMethodDecl(
252  modifiers, nameNode->location(), name, type, params, false, nullptr);
253  ast->addDecls(sem.getAllLexicalDecls());
254  return ast;
255 }
256 
257 } // namespace parsetree