mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-05 22:48:42 +00:00
226 lines
8.2 KiB
C++
226 lines
8.2 KiB
C++
#include <bits/types/error_t.h>
|
|
#include <optional>
|
|
|
|
// for clangd
|
|
#include "../include/link_symbols_visitor.hpp"
|
|
#include "../include/error_handling.hpp"
|
|
#include "../include/types.hpp"
|
|
|
|
namespace interpreter {
|
|
|
|
// Namespaces, partitions -----------------
|
|
|
|
void LinkSymbolsVisitor::Visit(Namespace* node) {
|
|
// Visitor::Visit(&node->type); // not needed
|
|
|
|
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindLocalTypeId(node->type);
|
|
|
|
std::optional<utils::IdType> maybe_typeclass;
|
|
if (namespace_visitor_.IsInGlobalNamespace()) {
|
|
maybe_typeclass = namespace_visitor_.FindTypeclassId(node->type);
|
|
}
|
|
|
|
if (!node->is_type_namespace && (maybe_type.has_value() || maybe_typeclass.has_value())) {
|
|
error_handling::HandleNamesError("Not type / typeclass namespace has associated type / typeclass", node->base);
|
|
}
|
|
|
|
if (node->is_type_namespace && !maybe_type.has_value() && !maybe_typeclass.has_value()) {
|
|
error_handling::HandleNamesError("Type / typeclass namespace has no associated type / typeclass", node->base);
|
|
}
|
|
|
|
if (maybe_type.has_value() && maybe_typeclass.has_value()) {
|
|
error_handling::HandleNamesError("Ambigious namespace name (typeclass or type)", node->base);
|
|
}
|
|
|
|
if (maybe_type.has_value()) {
|
|
node->link_type_id_ = maybe_type.value();
|
|
}
|
|
|
|
if (maybe_typeclass.has_value()) {
|
|
node->link_typeclass_id_ = maybe_typeclass.value();
|
|
if (!namespace_visitor_.IsInGlobalNamespace()) {
|
|
// other type of error??
|
|
error_handling::HandleParsingError("Can't use typeclass namespace in other namespace",
|
|
node->base.start_position,
|
|
node->base.end_position);
|
|
}
|
|
}
|
|
|
|
namespace_visitor_.EnterNamespace(node->type, node->modifier);
|
|
|
|
Visitor::Visit(&node->scope);
|
|
|
|
namespace_visitor_.ExitNamespace();
|
|
}
|
|
|
|
// Definitions -----------------
|
|
|
|
void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
|
|
Visitor::Visit(node->definition.get());
|
|
Visitor::Visit(node->value);
|
|
|
|
utils::IdType graph_id = node->definition->type->graph_id_;
|
|
|
|
AddTypeFunctionsToTypeclassGraph(node->type_id_,
|
|
graph_id,
|
|
utils::ClassInternalsModifier::Static,
|
|
node->base);
|
|
|
|
AddTypeFunctionsToTypeclassGraph(node->type_id_,
|
|
graph_id,
|
|
utils::ClassInternalsModifier::Const,
|
|
node->base);
|
|
|
|
AddTypeFunctionsToTypeclassGraph(node->type_id_,
|
|
graph_id,
|
|
utils::ClassInternalsModifier::Var,
|
|
node->base);
|
|
}
|
|
|
|
void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
|
|
Visitor::Visit(node->definition.get());
|
|
for (auto& function_requirement : node->requirements) {
|
|
namespace_visitor_.EnterNamespace(node->definition->type->type, function_requirement.first);
|
|
Visitor::Visit(function_requirement.second.get());
|
|
namespace_visitor_.ExitNamespace();
|
|
}
|
|
|
|
auto maybe_graph_id = global_info_.AddTypeclassToGraph(node->typeclass_id_);
|
|
if (!maybe_graph_id.has_value()) {
|
|
error_handling::HandleNamesError("Can't add typeclass to graph", node->base);
|
|
}
|
|
global_info_.GetTypeclassInfo(node->typeclass_id_).graph_id_ = maybe_graph_id.value();
|
|
}
|
|
|
|
// Type, typeclass, etc. -----------------
|
|
|
|
// Type
|
|
|
|
void LinkSymbolsVisitor::Visit(TypeExpression* node) {
|
|
std::vector<std::string> path;
|
|
path.reserve(node->path.size());
|
|
|
|
for (auto& path_type : node->path) {
|
|
path.push_back(path_type.type);
|
|
}
|
|
|
|
node->type_id_ = namespace_visitor_.FindTypeId(path, node->type.type);
|
|
node->constructor_id_ = namespace_visitor_.FindConstructorId(path, node->type.type);
|
|
|
|
// internal type
|
|
if (info::type::ToInternalType(node->type.type).has_value()) {
|
|
if (!node->path.empty()) {
|
|
error_handling::HandleNamesError("Internal type is not in namespace", node->base);
|
|
}
|
|
|
|
if (!node->type.parameters.empty()) {
|
|
error_handling::HandleNamesError("Can't parametrize internal type", node->base);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) {
|
|
// check made in typecheck visitor
|
|
return;
|
|
}
|
|
|
|
if (node->constructor_id_.has_value()) {
|
|
utils::IdType constructor_type_id = global_info_.GetConstructorInfo(node->constructor_id_.value()).type_id;
|
|
|
|
if (node->type_id_.has_value() && node->type_id_.value() != constructor_type_id) {
|
|
error_handling::HandleNamesError("Contructor and type with same name have different types", node->base);
|
|
}
|
|
|
|
node->type_id_ = constructor_type_id;
|
|
}
|
|
|
|
if (node->type_id_.has_value()) {
|
|
node->type.type_id_ = node->type_id_.value();
|
|
}
|
|
|
|
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() - 1; i >= 0; --i) {
|
|
info::definition::Namespace* parent_namespace = &global_info_.GetNamespaceInfo(type_namespace->parent_namespace);
|
|
|
|
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;
|
|
}
|
|
|
|
type_namespace = parent_namespace;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Typeclass
|
|
|
|
void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) {
|
|
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclassId(node->typeclass);
|
|
|
|
if (maybe_typeclass.has_value()) {
|
|
node->typeclass_id_ = maybe_typeclass.value();
|
|
} else {
|
|
error_handling::HandleNamesError("Typeclass not found", node->base);
|
|
}
|
|
|
|
if (node->parameters.size() > 0) {
|
|
error_handling::HandleNamesError("Parametrized typeclasses not implemented yet", node->base);
|
|
}
|
|
}
|
|
|
|
//
|
|
|
|
void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id,
|
|
utils::IdType graph_id,
|
|
utils::ClassInternalsModifier namespace_modifier,
|
|
const BaseNode& base_node) {
|
|
auto maybe_type_graph_info = typeclass_graph_.GetTypeVertex(graph_id);
|
|
if (!maybe_type_graph_info.has_value()) {
|
|
error_handling::HandleInternalError("Type in typeclass graph is not marked as type",
|
|
"LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph",
|
|
&base_node);
|
|
}
|
|
auto type_graph_info = maybe_type_graph_info.value();
|
|
|
|
auto maybe_namespace =
|
|
global_info_.GetTypeNamespace(type_id, namespace_modifier);
|
|
|
|
if (maybe_namespace.has_value()) {
|
|
for (auto& function : maybe_namespace.value()->functions) {
|
|
auto function_info = global_info_.GetFunctionInfo(function.second);
|
|
|
|
auto function_graph_iter = type_graph_info->functions.find(function.first);
|
|
if (function_graph_iter == type_graph_info->functions.end()) {
|
|
info::TypeclassGraph::FunctionInfo function_graph_info;
|
|
|
|
// can be found after graph calculation
|
|
if (function_info.declaration.has_value()) {
|
|
function_graph_info.declaration = function_info.declaration.value().node;
|
|
}
|
|
|
|
// can be found after graph calculation
|
|
if (function_info.definition.has_value()) {
|
|
function_graph_info.definition = function_info.definition.value().node;
|
|
function_graph_info.is_defined_in_owner = true;
|
|
}
|
|
|
|
function_graph_info.modifier = namespace_modifier;
|
|
|
|
type_graph_info->functions[function.first] = function_graph_info;
|
|
} else {
|
|
if (namespace_modifier != function_graph_iter->second.modifier) {
|
|
error_handling::HandleTypecheckError("Type function \"" + function.first + "\" has definitions / declarations with different modifiers (static / const /var)", base_node);
|
|
}
|
|
|
|
error_handling::HandleInternalError("This code should be unreachable",
|
|
"LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph",
|
|
&base_node);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace interpreter
|