Joos1W Compiler Framework
All Classes Functions Typedefs Pages
Semantic.cc
1 #include "semantic/Semantic.h"
2 
3 #include <set>
4 #include <string>
5 
6 #include "ast/AstNode.h"
7 #include "diagnostics/Location.h"
8 #include "parsetree/ParseTree.h"
9 
10 namespace ast {
11 
12 using std::string;
13 
14 Semantic::Semantic(BumpAllocator& alloc, diagnostics::DiagnosticEngine& diag)
15  : alloc{alloc}, diag{diag} {
16  // Preallocate java.lang.Object type
17  {
18  auto ty = BuildUnresolvedType(SourceRange{});
19  ty->addIdentifier("java");
20  ty->addIdentifier("lang");
21  ty->addIdentifier("Object");
22  ty->lock();
23  objectType_ = ty;
24  }
25 }
26 
27 /* ===--------------------------------------------------------------------=== */
28 // ast/Type.h
29 /* ===--------------------------------------------------------------------=== */
30 
31 UnresolvedType* Semantic::BuildUnresolvedType(SourceRange loc) {
32  return alloc.new_object<UnresolvedType>(alloc, loc);
33 }
34 
35 ArrayType* Semantic::BuildArrayType(Type* elementType, SourceRange loc) {
36  return alloc.new_object<ArrayType>(alloc, elementType, loc);
37 }
38 
39 BuiltInType* Semantic::BuildBuiltInType(parsetree::BasicType::Type type,
40  SourceRange loc) {
41  return alloc.new_object<BuiltInType>(type, loc);
42 }
43 
44 BuiltInType* Semantic::BuildBuiltInType(parsetree::Literal::Type type) {
45  return alloc.new_object<BuiltInType>(type);
46 }
47 
48 BuiltInType* Semantic::BuildBuiltInType(ast::BuiltInType::Kind type) {
49  return alloc.new_object<BuiltInType>(type, SourceRange{});
50 }
51 
52 ReferenceType* Semantic::BuildReferenceType(Decl const* decl) {
53  return alloc.new_object<ReferenceType>(decl, SourceRange{});
54 }
55 
56 /* ===--------------------------------------------------------------------=== */
57 // ast/Decl.h
58 /* ===--------------------------------------------------------------------=== */
59 
60 VarDecl* Semantic::BuildVarDecl(Type* type, SourceRange loc, string_view name,
61  ScopeID const* scope, Expr* init) {
62  auto decl = alloc.new_object<VarDecl>(alloc, loc, type, name, init, scope);
63  if(!AddLexicalLocal(decl)) {
64  diag.ReportError(loc)
65  << "local variable \"" << name << "\" already declared in this scope"
66  << loc << "local declared here"
67  << lexicalLocalScope[std::string{name.data()}]->location()
68  << "previous declaration here";
69  }
70  return decl;
71 }
72 
73 FieldDecl* Semantic::BuildFieldDecl(Modifiers modifiers, SourceRange loc,
74  Type* type, string_view name, Expr* init,
75  bool allowFinal) {
76  if(!allowFinal && modifiers.isFinal()) {
77  diag.ReportError(modifiers.getLocation(Modifiers::Type::Final))
78  << "field declaration cannot be final.";
79  }
80  if(modifiers.isAbstract()) {
81  diag.ReportError(modifiers.getLocation(Modifiers::Type::Abstract))
82  << "field declaration cannot be abstract.";
83  }
84  if(modifiers.isNative()) {
85  diag.ReportError(modifiers.getLocation(Modifiers::Type::Native))
86  << "field declaration cannot be native.";
87  }
88  if(modifiers.isPublic() && modifiers.isProtected()) {
89  diag.ReportError(modifiers.getLocation(Modifiers::Type::Public))
90  << "field cannot be both public and protected.";
91  }
92  if(!modifiers.isPublic() && !modifiers.isProtected()) {
93  diag.ReportError(loc) << "field must have a visibility modifier.";
94  }
95  return alloc.new_object<FieldDecl>(
96  alloc, loc, modifiers, type, name, init, NextFieldScopeID());
97 }
98 
99 /* ===--------------------------------------------------------------------=== */
100 // ast/DeclContext.h
101 /* ===--------------------------------------------------------------------=== */
102 
103 LinkingUnit* Semantic::BuildLinkingUnit(
104  array_ref<CompilationUnit*> compilationUnits) {
105  std::pmr::set<std::string_view> names;
106 
107  for(auto cu : compilationUnits) {
108  if(!cu->body()) continue;
109  std::string_view name = cu->bodyAsDecl()->getCanonicalName();
110 
111  if(names.count(name) > 0) {
112  diag.ReportError(cu->location())
113  << "No two classes or interfaces can have the same canonical name";
114  }
115 
116  names.insert(name);
117  }
118 
119  // Build the java.lang package
120  auto javaLangPackage = BuildUnresolvedType(SourceRange{});
121  javaLangPackage->addIdentifier("java");
122  javaLangPackage->addIdentifier("lang");
123  std::pmr::vector<ImportDeclaration> imports;
124  compilationUnits.push_back(
125  BuildCompilationUnit(javaLangPackage, imports, SourceRange(), nullptr));
126 
127  return alloc.new_object<LinkingUnit>(alloc, compilationUnits);
128 }
129 
130 CompilationUnit* Semantic::BuildCompilationUnit(
131  ReferenceType* package, array_ref<ImportDeclaration> imports,
132  SourceRange loc, DeclContext* body) {
133  std::pmr::set<std::pmr::string> names;
134  std::pmr::set<std::pmr::string> fullImportNames;
135  for(auto import : imports) {
136  if(import.isOnDemand) continue;
137  std::pmr::string name(import.simpleName());
138  std::pmr::string fullName(import.type->toString());
139  // Check that no two single-type-import declarations clash with each other
140  // We allow duplicate if they refer to the same type
141  if(names.count(name) > 0 && fullImportNames.count(fullName) == 0) {
142  diag.ReportError(loc)
143  << "No two single-type-import declarations clash with each other.";
144  }
145  names.insert(name);
146  fullImportNames.insert(fullName);
147  }
148 
149  // cf. JLS 7.5.2, we must import java.lang.*
150  auto javaLang = BuildUnresolvedType(SourceRange{});
151  javaLang->addIdentifier("java");
152  javaLang->addIdentifier("lang");
153  ImportDeclaration javaLangImport{javaLang, true};
154  imports.push_back(javaLangImport);
155 
156  // Create the AST node
157  return alloc.new_object<CompilationUnit>(alloc, package, imports, loc, body);
158 }
159 
160 ClassDecl* Semantic::BuildClassDecl(Modifiers modifiers, SourceRange loc,
161  string_view name, ReferenceType* superClass,
162  array_ref<ReferenceType*> interfaces,
163  array_ref<Decl*> classBodyDecls) {
164  // Check that the modifiers are valid for a class
165  if(modifiers.isAbstract() && modifiers.isFinal())
166  diag.ReportError(loc) << "class cannot be both abstract and final";
167  if(!modifiers.isPublic())
168  diag.ReportError(loc) << "class must have a visibility modifier";
169  // Create the AST node
170  auto node = alloc.new_object<ClassDecl>(alloc,
171  modifiers,
172  loc,
173  name,
174  superClass,
175  objectType_,
176  interfaces,
177  classBodyDecls);
178  // Check if the class has at least one constructor
179  if(node->constructors().size() == 0)
180  diag.ReportError(loc) << "class must have at least one constructor";
181  // Check if the construct name is the same as the class name
182  for(auto constructor : node->constructors()) {
183  if(loc.isValid() /* is decl synthetic? */ && constructor->name() != name) {
184  diag.ReportError(constructor->location())
185  << "constructor name must be the same as the class name"
186  << constructor->location() << "constructor here" << loc
187  << "must match class declared here";
188  }
189  }
190  // Check if multiple fields have the same name
191  for(auto field : node->fields()) {
192  for(auto other : node->fields()) {
193  if(field != other && field->name() == other->name()) {
194  diag.ReportError(field->location())
195  << "field \"" << field->name() << "\" is already declared"
196  << field->location() << "field here" << other->location()
197  << "previous declaration here";
198  }
199  }
200  }
201  // Check that interfaces cannot be repeated in implements clause
202  for(auto interface : node->interfaces()) {
203  for(auto other : node->interfaces()) {
204  if(interface != other && interface->toString() == other->toString()) {
205  diag.ReportError(loc)
206  << "interface \"" << interface->toString()
207  << "\" is already implemented" << interface->location()
208  << "interface here" << other->location()
209  << "previous implementation here";
210  }
211  }
212  }
213  return node;
214 }
215 
216 InterfaceDecl* Semantic::BuildInterfaceDecl(Modifiers modifiers, SourceRange loc,
217  string_view name,
218  array_ref<ReferenceType*> extends,
219  array_ref<Decl*> interfaceBodyDecls) {
220  // Check that the modifiers are valid for an interface
221  if(modifiers.isFinal())
222  diag.ReportError(modifiers.getLocation(Modifiers::Type::Final))
223  << "interface cannot be final";
224  if(!modifiers.isPublic())
225  diag.ReportError(loc) << "interface must have a visibility modifier";
226  // Verify the methods are abstract
227  for(auto decl : interfaceBodyDecls) {
228  if(auto methodDecl = dyn_cast<MethodDecl*>(decl)) {
229  if(!methodDecl->modifiers().isAbstract()) {
230  diag.ReportError(methodDecl->location())
231  << "interface method must be abstract";
232  }
233  }
234  }
235  // Check that interfaces cannot be repeated in extends clause
236  for(auto interface : extends) {
237  for(auto other : extends) {
238  if(interface != other && interface->toString() == other->toString()) {
239  diag.ReportError(loc)
240  << "interface \"" << interface->toString()
241  << "\" is already implemented" << interface->location()
242  << "interface here" << other->location()
243  << "previous implementation here";
244  }
245  }
246  }
247  // Create the AST node
248  return alloc.new_object<InterfaceDecl>(
249  alloc, modifiers, loc, name, extends, objectType_, interfaceBodyDecls);
250 }
251 
252 MethodDecl* Semantic::BuildMethodDecl(Modifiers modifiers, SourceRange loc,
253  string_view name, Type* returnType,
254  array_ref<VarDecl*> parameters,
255  bool isConstructor, Stmt* body) {
256  // Check modifiers
257  if((body == nullptr) != (modifiers.isAbstract() || modifiers.isNative())) {
258  diag.ReportError(loc) << "method has a body if and only if it is "
259  "neither abstract nor native.";
260  }
261  if(modifiers.isAbstract() &&
262  (modifiers.isFinal() || modifiers.isStatic() || modifiers.isNative())) {
263  diag.ReportError(loc) << "an abstract method cannot be static, final, "
264  "or native.";
265  }
266  if(modifiers.isStatic() && modifiers.isFinal()) {
267  diag.ReportError(modifiers.getLocation(Modifiers::Type::Final))
268  << "static method cannot be final.";
269  }
270  if(modifiers.isNative()) {
271  if(!modifiers.isStatic()) {
272  diag.ReportError(loc) << "native method must be static.";
273  }
274  if(auto ty = dyn_cast<BuiltInType*>(returnType)) {
275  if(ty->getKind() != BuiltInType::Kind::Int) {
276  diag.ReportError(loc) << "native method must have return type int.";
277  }
278  }
279  if(parameters.size() != 1) {
280  diag.ReportError(loc) << "native method must have exactly one "
281  "parameter of type int.";
282  } else if(auto ty = dyn_cast<BuiltInType*>(parameters[0]->type())) {
283  if(ty->getKind() != BuiltInType::Kind::Int) {
284  diag.ReportError(loc) << "native method must have exactly one "
285  "parameter of type int.";
286  }
287  }
288  }
289  if(modifiers.isPublic() && modifiers.isProtected()) {
290  diag.ReportError(modifiers.getLocation(Modifiers::Type::Public))
291  << "method cannot be both public and protected.";
292  }
293  if(!modifiers.isPublic() && !modifiers.isProtected()) {
294  diag.ReportError(loc) << "method must have a visibility modifier.";
295  }
296  // Create the AST node
297  return alloc.new_object<MethodDecl>(
298  alloc, modifiers, loc, name, returnType, parameters, isConstructor, body);
299 }
300 
301 /* ===-----------------------------------------------------------------=== */
302 // ast/Stmt.h
303 /* ===-----------------------------------------------------------------=== */
304 
305 BlockStatement* Semantic::BuildBlockStatement(array_ref<Stmt*> stmts) {
306  return alloc.new_object<BlockStatement>(alloc, stmts);
307 }
308 
309 DeclStmt* Semantic::BuildDeclStmt(VarDecl* decl) {
310  return alloc.new_object<DeclStmt>(decl);
311 }
312 
313 ExprStmt* Semantic::BuildExprStmt(Expr* expr) {
314  return alloc.new_object<ExprStmt>(expr);
315 }
316 
317 IfStmt* Semantic::BuildIfStmt(Expr* condition, Stmt* thenStmt, Stmt* elseStmt) {
318  return alloc.new_object<IfStmt>(condition, thenStmt, elseStmt);
319 }
320 
321 WhileStmt* Semantic::BuildWhileStmt(Expr* condition, Stmt* body) {
322  return alloc.new_object<WhileStmt>(condition, body);
323 }
324 
325 ForStmt* Semantic::BuildForStmt(Stmt* init, Expr* condition, Stmt* update,
326  Stmt* body) {
327  return alloc.new_object<ForStmt>(init, condition, update, body);
328 }
329 
330 ReturnStmt* Semantic::BuildReturnStmt(SourceRange loc, Expr* expr) {
331  return alloc.new_object<ReturnStmt>(loc, expr);
332 }
333 
334 } // namespace ast