1 #include "semantic/Semantic.h"
6 #include "ast/AstNode.h"
7 #include "diagnostics/Location.h"
8 #include "parsetree/ParseTree.h"
15 : alloc{alloc}, diag{diag} {
32 return alloc.new_object<UnresolvedType>(alloc, loc);
36 return alloc.new_object<ArrayType>(alloc, elementType, loc);
41 return alloc.new_object<BuiltInType>(type, loc);
44 BuiltInType*
Semantic::BuildBuiltInType(parsetree::
Literal::Type type) {
45 return alloc.new_object<BuiltInType>(type);
48 BuiltInType*
Semantic::BuildBuiltInType(ast::BuiltInType::Kind type) {
61 ScopeID
const* scope,
Expr* init) {
62 auto decl = alloc.new_object<
VarDecl>(alloc, loc, type, name, init, scope);
63 if(!AddLexicalLocal(decl)) {
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";
74 Type* type, string_view name,
Expr* init,
76 if(!allowFinal && modifiers.isFinal()) {
78 <<
"field declaration cannot be final.";
80 if(modifiers.isAbstract()) {
82 <<
"field declaration cannot be abstract.";
84 if(modifiers.isNative()) {
86 <<
"field declaration cannot be native.";
88 if(modifiers.isPublic() && modifiers.isProtected()) {
90 <<
"field cannot be both public and protected.";
92 if(!modifiers.isPublic() && !modifiers.isProtected()) {
93 diag.ReportError(loc) <<
"field must have a visibility modifier.";
95 return alloc.new_object<FieldDecl>(
96 alloc, loc, modifiers, type, name, init, NextFieldScopeID());
103 LinkingUnit*
Semantic::BuildLinkingUnit(
104 array_ref<CompilationUnit*> compilationUnits) {
105 std::pmr::set<std::string_view> names;
107 for(
auto cu : compilationUnits) {
108 if(!cu->body())
continue;
109 std::string_view name = cu->bodyAsDecl()->getCanonicalName();
111 if(names.count(name) > 0) {
112 diag.ReportError(cu->location())
113 <<
"No two classes or interfaces can have the same canonical name";
123 std::pmr::vector<ImportDeclaration> imports;
124 compilationUnits.push_back(
125 BuildCompilationUnit(javaLangPackage, imports, SourceRange(),
nullptr));
127 return alloc.new_object<LinkingUnit>(alloc, compilationUnits);
130 CompilationUnit*
Semantic::BuildCompilationUnit(
131 ReferenceType* package, array_ref<ImportDeclaration> imports,
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());
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.";
146 fullImportNames.insert(fullName);
154 imports.push_back(javaLangImport);
157 return alloc.new_object<CompilationUnit>(alloc, package, imports, loc, body);
162 array_ref<ReferenceType*> interfaces,
163 array_ref<Decl*> classBodyDecls) {
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";
170 auto node = alloc.new_object<ClassDecl>(alloc,
179 if(node->constructors().size() == 0)
180 diag.ReportError(loc) <<
"class must have at least one constructor";
182 for(
auto constructor : node->constructors()) {
183 if(loc.isValid() && 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";
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";
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";
218 array_ref<ReferenceType*> extends,
219 array_ref<Decl*> interfaceBodyDecls) {
221 if(modifiers.isFinal())
223 <<
"interface cannot be final";
224 if(!modifiers.isPublic())
225 diag.ReportError(loc) <<
"interface must have a visibility modifier";
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";
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";
248 return alloc.new_object<InterfaceDecl>(
249 alloc, modifiers, loc, name, extends, objectType_, interfaceBodyDecls);
253 string_view name,
Type* returnType,
254 array_ref<VarDecl*> parameters,
255 bool isConstructor,
Stmt* body) {
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.";
261 if(modifiers.isAbstract() &&
262 (modifiers.isFinal() || modifiers.isStatic() || modifiers.isNative())) {
263 diag.ReportError(loc) <<
"an abstract method cannot be static, final, "
266 if(modifiers.isStatic() && modifiers.isFinal()) {
268 <<
"static method cannot be final.";
270 if(modifiers.isNative()) {
271 if(!modifiers.isStatic()) {
272 diag.ReportError(loc) <<
"native method must be static.";
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.";
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.";
289 if(modifiers.isPublic() && modifiers.isProtected()) {
291 <<
"method cannot be both public and protected.";
293 if(!modifiers.isPublic() && !modifiers.isProtected()) {
294 diag.ReportError(loc) <<
"method must have a visibility modifier.";
297 return alloc.new_object<MethodDecl>(
298 alloc, modifiers, loc, name, returnType, parameters, isConstructor, body);
305 BlockStatement*
Semantic::BuildBlockStatement(array_ref<Stmt*> stmts) {
306 return alloc.new_object<BlockStatement>(alloc, stmts);
310 return alloc.new_object<DeclStmt>(decl);
314 return alloc.new_object<ExprStmt>(expr);
318 return alloc.new_object<IfStmt>(condition, thenStmt, elseStmt);
322 return alloc.new_object<WhileStmt>(condition, body);
327 return alloc.new_object<ForStmt>(init, condition, update, body);
331 return alloc.new_object<ReturnStmt>(loc, expr);