2023-04-17 12:09:02 +03:00
|
|
|
// for clangd
|
|
|
|
|
#include "../include/link_symbols_visitor.hpp"
|
2023-04-17 18:56:58 +03:00
|
|
|
#include "../include/error_handling.hpp"
|
2023-05-02 16:16:55 +03:00
|
|
|
#include <optional>
|
2023-04-17 12:09:02 +03:00
|
|
|
|
|
|
|
|
namespace interpreter {
|
|
|
|
|
|
|
|
|
|
// Namespaces, partitions -----------------
|
|
|
|
|
|
|
|
|
|
void LinkSymbolsVisitor::Visit(Namespace* node) {
|
2023-05-02 15:18:08 +03:00
|
|
|
// Visitor::Visit(&node->type); // not needed
|
2023-04-17 12:09:02 +03:00
|
|
|
|
2023-05-02 16:16:55 +03:00
|
|
|
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindLocalType(node->type);
|
|
|
|
|
|
|
|
|
|
std::optional<utils::IdType> maybe_typeclass;
|
|
|
|
|
if (namespace_visitor_.GetCurrentPath().size() == 0) {
|
|
|
|
|
maybe_typeclass = namespace_visitor_.FindTypeclass(node->type);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 15:18:08 +03:00
|
|
|
if (maybe_type.has_value() && maybe_typeclass.has_value()) {
|
2023-05-05 11:59:02 +03:00
|
|
|
error_handling::HandleTypecheckError("Ambigious namespace name (typeclass or type)", node->base);
|
2023-04-17 12:09:02 +03:00
|
|
|
}
|
2023-05-05 11:59:02 +03:00
|
|
|
|
2023-05-02 15:18:08 +03:00
|
|
|
if (maybe_type.has_value()) {
|
|
|
|
|
node->link_type_id_ = maybe_type.value();
|
2023-04-17 12:09:02 +03:00
|
|
|
}
|
2023-05-02 15:18:08 +03:00
|
|
|
if (maybe_typeclass.has_value()) {
|
|
|
|
|
node->link_typeclass_id_ = maybe_typeclass.value();
|
2023-04-17 12:09:02 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-02 15:18:08 +03:00
|
|
|
namespace_visitor_.EnterNamespace(node->type);
|
2023-04-17 12:09:02 +03:00
|
|
|
|
2023-05-02 15:18:08 +03:00
|
|
|
Visitor::Visit(&node->scope);
|
2023-04-17 12:09:02 +03:00
|
|
|
|
2023-05-02 15:18:08 +03:00
|
|
|
namespace_visitor_.ExitNamespace();
|
2023-04-17 12:09:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type, typeclass, etc. -----------------
|
|
|
|
|
|
|
|
|
|
// Type
|
|
|
|
|
|
2023-05-02 15:18:08 +03:00
|
|
|
void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
|
2023-04-17 18:56:58 +03:00
|
|
|
std::vector<std::string> path;
|
2023-05-02 15:18:08 +03:00
|
|
|
path.reserve(node->path.size());
|
2023-04-17 18:56:58 +03:00
|
|
|
|
2023-05-02 15:18:08 +03:00
|
|
|
for (auto& path_type : node->path) {
|
2023-05-03 15:03:57 +03:00
|
|
|
path.push_back(path_type.type);
|
2023-04-17 18:56:58 +03:00
|
|
|
}
|
|
|
|
|
|
2023-05-03 15:03:57 +03:00
|
|
|
node->type_id_ = namespace_visitor_.FindType(path, node->type.type);
|
|
|
|
|
node->constructor_id_ = namespace_visitor_.FindConstructor(path, node->type.type);
|
2023-05-02 15:18:08 +03:00
|
|
|
|
2023-05-07 19:52:35 +03:00
|
|
|
if (path.size() == 0 && namespace_visitor_.FindAbstractType(node->type.type).has_value()) { // TODO
|
|
|
|
|
// abstract / basic / TODO: local abstract type
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) { // TODO: check, that not bastract types
|
|
|
|
|
error_handling::HandleTypecheckError("Type or constructor not found", node->base);
|
|
|
|
|
}
|
2023-05-02 16:51:47 +03:00
|
|
|
|
2023-05-04 16:11:25 +03:00
|
|
|
if (node->constructor_id_.has_value()) {
|
|
|
|
|
utils::IdType constructor_type_id = namespace_visitor_.GetGlobalInfo()->GetConstructorInfo(node->constructor_id_.value()).type_id;
|
|
|
|
|
|
|
|
|
|
if (node->type_id_.has_value() && node->type_id_.value() != constructor_type_id) {
|
2023-05-05 11:59:02 +03:00
|
|
|
error_handling::HandleTypecheckError("Contructor and type with same name have different types", node->base);
|
2023-05-04 16:11:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node->type_id_ = constructor_type_id;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 15:03:57 +03:00
|
|
|
if (node->type_id_.has_value()) {
|
|
|
|
|
node->type.type_id_ = node->type_id_.value();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 16:51:47 +03:00
|
|
|
std::optional<info::definition::Namespace*> maybe_type_namespace = namespace_visitor_.FindNamespace(path);
|
|
|
|
|
if (maybe_type_namespace.has_value()) {
|
|
|
|
|
info::definition::Namespace* type_namespace = maybe_type_namespace.value();
|
|
|
|
|
|
|
|
|
|
for (ssize_t i = (ssize_t)node->path.size(); i >= 0; --i) {
|
|
|
|
|
info::definition::Namespace* parent_namespace = type_namespace->parent_namespace;
|
|
|
|
|
|
2023-05-03 15:03:57 +03:00
|
|
|
auto type_iter = parent_namespace->types.find(type_namespace->type_name);
|
|
|
|
|
if (type_iter != parent_namespace->types.end()) {
|
|
|
|
|
node->path[i].type_id_ = type_iter->second;
|
2023-05-02 16:51:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parent_namespace == nullptr) {
|
|
|
|
|
error_handling::HandleInternalError("Parent namespace is null in type expression", "LinkSymbolsVisitor");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type_namespace = parent_namespace;
|
|
|
|
|
}
|
2023-04-17 12:09:02 +03:00
|
|
|
}
|
2023-04-17 18:56:58 +03:00
|
|
|
}
|
|
|
|
|
|
2023-04-17 12:09:02 +03:00
|
|
|
// Typeclass
|
|
|
|
|
|
2023-05-03 15:03:57 +03:00
|
|
|
void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) { // TODO: check
|
|
|
|
|
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclass(node->typeclass);
|
2023-05-02 15:18:08 +03:00
|
|
|
|
|
|
|
|
if (maybe_typeclass.has_value()) {
|
|
|
|
|
node->typeclass_id_ = maybe_typeclass.value();
|
2023-04-17 18:56:58 +03:00
|
|
|
} else {
|
2023-05-05 11:59:02 +03:00
|
|
|
error_handling::HandleTypecheckError("Type not found", node->base);
|
2023-04-17 18:56:58 +03:00
|
|
|
}
|
2023-04-17 12:09:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace interpreter
|