1 #include "semantic/NameResolver.h"
3 #include <utils/Assert.h>
6 #include <memory_resource>
9 #include <unordered_map>
13 #include "ast/AstNode.h"
14 #include "ast/DeclContext.h"
16 #include "diagnostics/Location.h"
17 #include "semantic/Semantic.h"
18 #include "utils/BumpAllocator.h"
21 using ast::UnresolvedType;
22 using std::string_view;
23 using std::pmr::string;
24 using std::pmr::unordered_map;
25 using std::pmr::vector;
29 static const std::pmr::string UNNAMED_PACKAGE{
""};
31 void NameResolver::buildSymbolTable() {
32 rootPkg_ = alloc.new_object<
Pkg>(alloc);
34 rootPkg_->children[UNNAMED_PACKAGE] = alloc.new_object<
Pkg>(alloc);
36 for(
auto cu : lu_->compliationUnits()) {
39 auto pkg = cast<UnresolvedType>(cu->package());
42 Pkg* subPkg = rootPkg_;
43 for(
auto const& id : pkg->parts()) {
46 if(subPkg->children.find(id) == subPkg->children.end()) {
47 auto newpkg = alloc.new_object<Pkg>(alloc, string_view{id});
48 subPkg->children[id] = newpkg;
55 Pkg::Child
const& child = subPkg->children[id];
56 if(std::holds_alternative<Decl*>(child)) {
57 auto decl = std::get<Decl*>(child);
58 assert(decl &&
"Package node holds empty decl");
59 diag.ReportError(cu->location())
60 <<
"subpackage name cannot be the same as a declaration: " << id;
64 subPkg = std::get<Pkg*>(child);
66 if(cu->isDefaultPackage()) {
67 subPkg = std::get<Pkg*>(rootPkg_->children[UNNAMED_PACKAGE]);
70 if(!cu->body())
continue;
72 if(subPkg->children.find(cu->bodyAsDecl()->name().data()) !=
73 subPkg->children.end()) {
74 diag.ReportError(cu->bodyAsDecl()->location())
75 <<
"declaration name is not unique in the subpackage.";
78 subPkg->children[cu->bodyAsDecl()->name().data()] = cu->mut_bodyAsDecl();
82 diag.ReportDebug(2) <<
"Symbol table built!";
83 rootPkg_->print(diag.ReportDebug(2).get(), 0);
87 void NameResolver::populateJavaLangCache() {
89 auto javaPkg = std::get<Pkg*>(rootPkg_->children[
"java"]);
90 auto langPkg = std::get<Pkg*>(javaPkg->children[
"lang"]);
91 auto ioPkg = std::get<Pkg*>(javaPkg->children[
"io"]);
95 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Boolean"]));
97 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Byte"]));
98 java_lang_.Character =
99 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Character"]));
101 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Class"]));
102 java_lang_.Cloneable = cast<ast::InterfaceDecl*>(
103 std::get<Decl*>(langPkg->children[
"Cloneable"]));
105 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Integer"]));
107 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Number"]));
109 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Object"]));
111 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"Short"]));
113 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"String"]));
115 cast<ast::ClassDecl>(std::get<Decl*>(langPkg->children[
"System"]));
116 java_lang_.Serializable = cast<ast::InterfaceDecl>(
117 std::get<Decl*>(ioPkg->children[
"Serializable"]));
119 assert(java_lang_.Boolean &&
"java.lang.Boolean not valid (expected class)");
120 assert(java_lang_.Byte &&
"java.lang.Byte not valid (expected class)");
121 assert(java_lang_.Character &&
122 "java.lang.Character not valid (expected class)");
123 assert(java_lang_.Class &&
"java.lang.Class not valid (expected class)");
124 assert(java_lang_.Cloneable &&
125 "java.lang.Cloneable not valid (expected interface)");
126 assert(java_lang_.Integer &&
"java.lang.Integer not valid (expected class)");
127 assert(java_lang_.Number &&
"java.lang.Number not valid (expected class)");
128 assert(java_lang_.Object &&
"java.lang.Object not valid (expected class)");
129 assert(java_lang_.Short &&
"java.lang.Short not valid (expected class)");
130 assert(java_lang_.String &&
"java.lang.String not valid (expected class)");
131 assert(java_lang_.System &&
"java.lang.System not valid (expected class)");
136 std::pmr::vector<ReferenceType*> interfaces{alloc};
137 std::pmr::vector<Decl*> body{alloc};
138 std::pmr::vector<VarDecl*> emptyParams{alloc};
139 std::pmr::vector<ImportDeclaration> emptyImports{alloc};
149 auto length = sema_->BuildFieldDecl(lengthMod,
SourceRange{}, intTy,
"length",
nullptr,
true);
150 auto ctor = sema_->BuildMethodDecl(pubMod,
152 "[__builtin_array_proto",
156 sema_->BuildNullStmt());
157 body.push_back(length);
158 body.push_back(ctor);
160 arrayPrototype_ = sema_->BuildClassDecl(pubMod,
162 "[__builtin_array_proto",
166 (
void) sema_->BuildCompilationUnit(
nullptr, emptyImports, SourceRange{}, arrayPrototype_);
175 auto& importsMap = importsMap_[cu];
178 auto curPkg = cast<UnresolvedType>(cu->package());
193 for(
auto const& imp : cu->imports()) {
194 if(!imp.isOnDemand)
continue;
196 auto subPkg = resolveImport(
static_cast<UnresolvedType
const*>(imp.type));
198 if(!subPkg)
continue;
199 if(!std::holds_alternative<Pkg*>(subPkg.value())) {
200 diag.ReportError(imp.location())
201 <<
"failed to resolve import-on-demand as subpackage is a "
203 << imp.simpleName() <<
"\"";
207 auto pkg = std::get<Pkg*>(subPkg.value());
214 for(
auto& kv : pkg->children) {
215 if(!std::holds_alternative<Decl*>(kv.second))
continue;
216 auto decl = std::get<Decl*>(kv.second);
217 if(importsMap.find(kv.first) != importsMap.end()) {
218 auto imported = importsMap[kv.first];
219 if(std::holds_alternative<Decl*>(imported) &&
220 std::get<Decl*>(imported) == decl)
224 importsMap[kv.first] =
static_cast<Decl*>(
nullptr);
227 importsMap[kv.first] = Pkg::Child{decl};
232 for(
auto& kv : rootPkg_->children) {
233 if(!std::holds_alternative<Pkg*>(kv.second))
235 if(importsMap.find(kv.first) != importsMap.end())
237 importsMap[kv.first] = Pkg::Child{std::get<Pkg*>(kv.second)};
242 auto curTree = resolveImport(curPkg);
243 assert(curTree &&
"Current package should exist!");
244 assert(std::holds_alternative<Pkg*>(curTree.value()));
245 for(
auto& kv : std::get<Pkg*>(curTree.value())->children)
246 if(std::holds_alternative<Decl*>(kv.second))
247 importsMap[kv.first] = Pkg::Child{std::get<Decl*>(kv.second)};
250 for(
auto const& imp : cu->imports()) {
251 if(imp.isOnDemand)
continue;
253 auto subPkg = resolveImport(
static_cast<UnresolvedType
const*>(imp.type));
254 if(!subPkg)
continue;
255 if(!std::holds_alternative<Decl*>(subPkg.value())) {
256 diag.ReportError(imp.location())
257 <<
"failed to resolve single-type-import as a declaration: \""
258 << imp.simpleName() <<
"\"";
262 auto decl = std::get<Decl*>(subPkg.value());
263 auto cuDecl = cu->bodyAsDecl();
266 if((decl->name() == cuDecl->name()) && (decl != cuDecl)) {
267 diag.ReportError(cu->location()) <<
"single-type-import is the same "
268 "as the class/interface name: "
272 std::pmr::string name{imp.simpleName().data(), alloc};
273 importsMap[name] = decl;
277 importsMap[cu->bodyAsDecl()->name().data()] = cu->mut_bodyAsDecl();
280 NameResolver::ChildOpt NameResolver::resolveImport(UnresolvedType
const* t)
const {
281 assert(t &&
"Type should not be null");
282 assert(!t->isResolved() &&
"Type should not be resolved");
283 if(t->parts().empty()) {
284 return rootPkg_->children[UNNAMED_PACKAGE];
286 Pkg::Child subPkg = rootPkg_;
287 for(
auto const& id : t->parts()) {
289 if(std::holds_alternative<Decl*>(subPkg)) {
290 diag.ReportError(t->location())
291 <<
"failed to resolve import as subpackage is a declaration: \""
296 auto pkg = std::get<Pkg*>(subPkg);
298 if(pkg->children.find(id) == pkg->children.end()) {
299 diag.ReportError(t->location())
300 <<
"failed to resolve import as subpackage does not exist: \"" << id
305 subPkg = pkg->children[id];
312 assert(ty &&
"Type should not be null");
313 assert(!ty->isResolved() &&
"Type should not be resolved");
314 if(ty->parts().empty())
return;
316 auto it = ty->parts().begin();
318 auto& importsMap = importsMap_[currentCU_];
319 if(
auto it2 = importsMap.find(*it); it2 != importsMap.end()) {
322 diag.ReportError(ty->location())
323 <<
"failed to resolve type as subpackage does not exist: \"" << *it
329 for(; it != ty->parts().end(); it++) {
331 if(std::holds_alternative<Decl*>(subTy)) {
332 diag.ReportError(ty->location())
333 <<
"failed to resolve type as subpackage is a declaration: \""
338 auto pkg = std::get<Pkg*>(subTy);
340 if(pkg->children.find(*it) == pkg->children.end()) {
341 diag.ReportError(ty->location())
342 <<
"failed to resolve type as subpackage does not exist: \"" << *it
347 subTy = pkg->children[*it];
350 if(!std::holds_alternative<Decl*>(subTy)) {
351 diag.ReportError(ty->location())
352 <<
"failed to resolve type, is not a declaration: \"" << ty
->toString()
358 if(!std::get<Decl*>(subTy)) {
360 diag.ReportError(ty->location())
361 <<
"failed to resolve type, ambiguous import-on-demand: \""
368 assert(ty->isResolved() &&
"Type should be resolved");
371 std::ostream& NameResolver::
Pkg::print(std::ostream& os,
int indent)
const {
372 for(
auto const& [name, child] : children) {
373 for(
int i = 0; i < indent; i++) os <<
" ";
374 if(std::holds_alternative<Decl*>(child)) {
375 os << name << std::endl;
377 if(name != UNNAMED_PACKAGE)
380 os <<
"(default package)";
381 os <<
" ->" << std::endl;
382 std::get<
Pkg*>(child)->print(os, indent + 1);
388 void NameResolver::
Pkg::dump()
const { print(std::cout, 0); }
390 void NameResolver::
dump()
const {
391 std::cout <<
"Symbol table:" << std::endl;
393 std::cout <<
"Import table:" << std::endl;
398 for(
auto const* cu : lu_->compliationUnits()) dumpImports(cu);
401 void NameResolver::
dumpImports(ast::CompilationUnit
const* cu)
const {
402 if(cu && cu->bodyAsDecl() && cu->bodyAsDecl()->hasCanonicalName()) {
403 std::cout <<
"Current CU: " << cu->bodyAsDecl()->getCanonicalName()
409 auto it = importsMap_.find(cu);
410 assert(it != importsMap_.end() &&
"Compilation unit not found in import map");
411 auto const& importsMap = it->second;
413 if(importsMap.empty()) {
414 std::cout <<
"No imports" << std::endl;
418 for(
auto const& [name, child] : importsMap) {
419 if(name == UNNAMED_PACKAGE)
420 std::cout <<
"(default package) -> ";
422 std::cout << name <<
" -> ";
423 if(std::holds_alternative<Decl*>(child)) {
424 auto* decl = std::get<Decl*>(child);
425 std::cout <<
"(Decl) ";
427 std::cout << decl->name();
429 std::cout <<
"<null>";
431 std::cout <<
"(subpackage)";
433 std::cout << std::endl;
438 ast::CompilationUnit
const* cu, std::string_view name,
439 std::pmr::memory_resource* r)
const {
441 auto it = importsMap_.find(cu);
442 assert(it != importsMap_.end() &&
"Compilation unit not found in import map");
443 auto const& importsMap = it->second;
446 BumpAllocator alloc1{r};
447 std::pmr::string str{name, alloc1};
448 auto it2 = importsMap.find(str);
451 if(it2 == importsMap.end())
return std::nullopt;
454 if(std::holds_alternative<Decl*>(it2->second)) {
455 return static_cast<Decl
const*>(std::get<Decl*>(it2->second));
457 return static_cast<Pkg
const*>(std::get<Pkg*>(it2->second));