adding types to typeclass tree, part 1

This commit is contained in:
ProgramSnail 2023-05-19 11:55:46 +03:00
parent 17328b842c
commit d841e2754b
7 changed files with 260 additions and 167 deletions

View file

@ -350,19 +350,19 @@ public:
return &typeclass_graph_; return &typeclass_graph_;
} }
std::unordered_set<utils::IdType> // std::unordered_set<utils::IdType>
GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node); // GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node);
//
std::vector<utils::IdType> // std::vector<utils::IdType>
GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node); // GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node);
//
std::unordered_map<std::string, TypeclassGraph::FunctionInfo> // std::unordered_map<std::string, TypeclassGraph::FunctionInfo>
GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node, // GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node,
const interpreter::tokens::BaseNode& base_node); // const interpreter::tokens::BaseNode& base_node);
//
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo>> // std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo>>
GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node, // GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node,
const interpreter::tokens::BaseNode& base_node); // const interpreter::tokens::BaseNode& base_node);
std::unordered_map<std::string, utils::IdType>* ChooseNamespaces( std::unordered_map<std::string, utils::IdType>* ChooseNamespaces(
utils::ClassInternalsModifier modifier, utils::ClassInternalsModifier modifier,
@ -370,6 +370,9 @@ public:
std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass); std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass);
// function declarations & definitions should be added latter
std::optional<utils::IdType> AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node);
private: private:
void CollectFunctionInfo( void CollectFunctionInfo(
utils::IdType current_namespace, utils::IdType current_namespace,

View file

@ -17,9 +17,7 @@ public:
void VisitSourceFile(SourceFile* source_file) override { void VisitSourceFile(SourceFile* source_file) override {
Visitor::Visit(source_file); Visitor::Visit(source_file);
if (!namespace_visitor_.GetTypeclassGraph()->CalculateGraph()) { namespace_visitor_.GetTypeclassGraph()->CalculateGraph();
error_handling::HandleInternalError("Can't calculate typeclass graph", "LinkSymbolsVisitor.VisitSourceFile");
}
} }
private: private:
@ -39,7 +37,7 @@ private:
// // void Visit(VariableDefinitionStatement* node) override; // // void Visit(VariableDefinitionStatement* node) override;
// // void Visit(FunctionDeclaration* node) override; // // void Visit(FunctionDeclaration* node) override;
// // void Visit(FunctionDefinitionStatement* node) override; // // void Visit(FunctionDefinitionStatement* node) override;
// // void Visit(TypeDefinitionStatement* node) override; void Visit(TypeDefinitionStatement* node) override;
// // void Visit(AbstractTypeDefinitionStatement* node) override; // // void Visit(AbstractTypeDefinitionStatement* node) override;
void Visit(TypeclassDefinitionStatement* node) override; void Visit(TypeclassDefinitionStatement* node) override;
// // void Visit(PartitionStatement* node) override; // // void Visit(PartitionStatement* node) override;

View file

@ -12,57 +12,77 @@
namespace info { namespace info {
// move constructor parameters ??
class TypeclassGraph { class TypeclassGraph {
public: public:
enum class Modifier {
Typeclass = 0,
Type = 1,
};
struct FunctionInfo { struct FunctionInfo {
utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static;
interpreter::tokens::FunctionDeclaration* declaration = nullptr; interpreter::tokens::FunctionDeclaration* declaration = nullptr;
std::optional<interpreter::tokens::FunctionDefinitionStatement*> definition; std::optional<interpreter::tokens::FunctionDefinitionStatement*> definition;
bool is_defined_in_owner = false;
}; };
struct TypeclassVertex { struct Vertex { // make constructor ??
std::string name; std::string name;
interpreter::tokens::TypeclassDefinitionStatement* definition = nullptr;
std::unordered_map<std::string, FunctionInfo> functions; std::unordered_map<std::string, FunctionInfo> functions;
std::unordered_set<std::string> dependencies; // TODO: parameters std::unordered_set<std::string> dependencies; // TODO: parameters
interpreter::tokens::BaseNode* base_node; // for error handling
Modifier modifier;
}; };
std::optional<utils::IdType> AddTypeclass( // move parameters ?? utils::IdType AddVertex(
const std::string& name, const std::string& name,
interpreter::tokens::TypeclassDefinitionStatement* definition, const std::vector<std::string>& dependencies,
const std::vector<std::string>& dependencies, // TODO: parameters
const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations, const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions); const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions,
interpreter::tokens::BaseNode* base_node,
Modifier modifier);
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name); std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name);
bool IsFunctionInTypeclass(const std::string& name, utils::IdType typeclass_id) { bool IsFunctionInVertex(const std::string& name, utils::IdType vertex_id) {
return typeclasses_[typeclass_id].functions.count(name) != 0; return verticles_[vertex_id].functions.count(name) != 0;
} }
// if vertex_id == std::nullopt, info can be not complete
std::optional<FunctionInfo*> GetFunctionInfo(const std::string& name, std::optional<FunctionInfo*> GetFunctionInfo(const std::string& name,
std::optional<utils::IdType> typeclass_id); std::optional<utils::IdType> vertex_id);
const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ?? const Vertex& GetVertex(utils::IdType id) {
return typeclasses_.at(typeclass_id); return verticles_.at(id);
}
std::optional<Vertex*> GetTypeVertex(utils::IdType id) {
if (verticles_.at(id).modifier == Modifier::Type) {
return &verticles_[id];
}
return std::nullopt;
} }
// cache ?? // cache ??
std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id); std::unordered_set<utils::IdType> GetDependenciesSet(utils::IdType id);
std::vector<utils::IdType> GetDependenciesVector(utils::IdType id);
// cache ?? const std::unordered_map<std::string, FunctionInfo>& GetVertexFunctions(utils::IdType id) {
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> GetTypeclassFunctions(utils::IdType id); return verticles_.at(id).functions;
}
bool IsCalculated() { bool IsCalculated() {
return is_calculated_; return is_calculated_;
} }
bool CalculateGraph(); // can exit by typecheck error
void CalculateGraph();
private: private:
std::unordered_map<std::string, utils::IdType> method_to_typeclass_; std::unordered_map<std::string, utils::IdType> method_to_vertex_;
std::unordered_map<std::string, utils::IdType> name_to_typeclass_; std::unordered_map<std::string, utils::IdType> name_to_typeclass_;
std::vector<TypeclassVertex> typeclasses_; std::vector<Vertex> verticles_;
bool is_calculated_ = true; bool is_calculated_ = true;
}; };

View file

@ -49,6 +49,8 @@ void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) {
info.type = std::move(alias_info); info.type = std::move(alias_info);
node->type_id_ = namespace_visitor_.AddType(node->type, std::move(info), node->base); node->type_id_ = namespace_visitor_.AddType(node->type, std::move(info), node->base);
Visitor::Visit(node->value.get()); // to visit all tree
} }
void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
@ -69,6 +71,8 @@ void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
info.node = node; info.node = node;
node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name, std::move(info), node->base); node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name, std::move(info), node->base);
Visitor::Visit(node->type.get()); // to visit all tree
} }
void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) { void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) {
@ -84,6 +88,9 @@ void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) {
info.node = node; info.node = node;
node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info), node->base); node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info), node->base);
Visitor::Visit(definition); // to visit all tree
Visitor::Visit(node->value); // to visit all tree
} }
void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
@ -113,6 +120,9 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
info.type = std::move(any_type_info); info.type = std::move(any_type_info);
node->type_id_ = namespace_visitor_.AddType(type, std::move(info), node->base); node->type_id_ = namespace_visitor_.AddType(type, std::move(info), node->base);
// definition visited earlier
Visitor::Visit(node->value); // to visit all tree
} }
void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) { void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
@ -153,10 +163,14 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId(); info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId();
node->typeclass_id_ = namespace_visitor_.AddTypeclass(typeclass_name, std::move(info), node->base); node->typeclass_id_ = namespace_visitor_.AddTypeclass(typeclass_name, std::move(info), node->base);
// no need to visit definition->type, because it is typeclass
} }
void FindSymbolsVisitor::Visit(PartitionStatement* node) { void FindSymbolsVisitor::Visit(PartitionStatement* node) {
node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node, node->base); node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node, node->base);
Visitor::Visit(node->value); // to visit all tree
} }
// Definition parts // Definition parts
@ -171,8 +185,19 @@ void FindSymbolsVisitor::Visit(AnyAnnotatedType* node) {
info.typeclass_nodes[i] = node->typeclasses[i].get(); info.typeclass_nodes[i] = node->typeclasses[i].get();
} }
for (auto& typeclass : node->typeclasses) {
Visitor::Visit(typeclass.get()); // to visit all tree
}
info.node = node; info.node = node;
auto maybe_graph_id = namespace_visitor_.GetGlobalInfo()->AddAnnotatedTypeToGraph(node); // definitions and declarations should be added latter
if (!maybe_graph_id.has_value()) {
error_handling::HandleInternalError("Can't add annotated type to typeclass graph",
"FindSymbolsVisitor.AnyAnnotatedType");
}
current_info_ = std::move(info); current_info_ = std::move(info);
} }

View file

@ -460,79 +460,79 @@ std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindNamespaceIn(
// //
// cache ?? // // cache ??
std::unordered_set<utils::IdType> // std::unordered_set<utils::IdType>
GlobalInfo::GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node) { // GlobalInfo::GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node) {
//
std::unordered_set<utils::IdType> typeclasses; // std::unordered_set<utils::IdType> typeclasses;
//
for (auto& typeclass : node->typeclasses) { // for (auto& typeclass : node->typeclasses) {
utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_; // utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_;
//
std::vector<utils::IdType> dependencies = typeclass_graph_.GetTypeclassDependencies(graph_id); // std::vector<utils::IdType> dependencies = typeclass_graph_.GetTypeclassDependencies(graph_id);
for (auto& dependency : dependencies) { // for (auto& dependency : dependencies) {
typeclasses.insert(dependency); // typeclasses.insert(dependency);
} // }
//
typeclasses.insert(graph_id); // typeclasses.insert(graph_id);
} // }
return typeclasses; // return typeclasses;
} // }
//
std::vector<utils::IdType> // std::vector<utils::IdType>
GlobalInfo::GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node) { // GlobalInfo::GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node) {
//
std::unordered_set<utils::IdType> typeclasses_set = GetAnnotatedTypeTypeclassesSet(node); // std::unordered_set<utils::IdType> typeclasses_set = GetAnnotatedTypeTypeclassesSet(node);
//
std::vector<utils::IdType> typeclasses_vector; // std::vector<utils::IdType> typeclasses_vector;
typeclasses_vector.reserve(typeclasses_vector.size()); // typeclasses_vector.reserve(typeclasses_vector.size());
for (auto& typeclass : typeclasses_set) { // for (auto& typeclass : typeclasses_set) {
typeclasses_vector.push_back(typeclass); // typeclasses_vector.push_back(typeclass);
} // }
return typeclasses_vector; // return typeclasses_vector;
} // }
//
std::unordered_map<std::string, TypeclassGraph::FunctionInfo> // TODO: optimize, cache // std::unordered_map<std::string, TypeclassGraph::FunctionInfo> // TODO: optimize, cache
GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node, // GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node,
const interpreter::tokens::BaseNode& base_node) { // const interpreter::tokens::BaseNode& base_node) {
//
std::unordered_map<std::string, TypeclassGraph::FunctionInfo> functions; // std::unordered_map<std::string, TypeclassGraph::FunctionInfo> functions;
//
for (auto& typeclass : node->typeclasses) { // for (auto& typeclass : node->typeclasses) {
utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_; // utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_;
//
auto requirements = typeclass_graph_.GetTypeclassFunctions(graph_id); // auto requirements = typeclass_graph_.GetTypeclassFunctions(graph_id);
for (auto& requirement : requirements) { // for (auto& requirement : requirements) {
auto requirement_iter = functions.find(requirement.first); // auto requirement_iter = functions.find(requirement.first);
if (requirement_iter == functions.end()) { // if (requirement_iter == functions.end()) {
functions[requirement.first] = *requirement.second; // functions[requirement.first] = *requirement.second;
} else { // } else {
if (requirement_iter->second.definition.has_value()) { // if (requirement_iter->second.definition.has_value()) {
if (requirement.second->definition.has_value()) { // if (requirement.second->definition.has_value()) {
error_handling::HandleTypecheckError("Function defined more then in one type requirement", base_node); // error_handling::HandleTypecheckError("Function defined more then in one type requirement", base_node);
} // }
} else { // } else {
requirement_iter->second.definition = requirement.second->definition; // requirement_iter->second.definition = requirement.second->definition;
} // }
} // }
} // }
} // }
return functions; // return functions;
} // }
//
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo>> // TODO: optimize, cache // std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo>> // TODO: optimize, cache
GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node, // GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node,
const interpreter::tokens::BaseNode& base_node) { // const interpreter::tokens::BaseNode& base_node) {
//
auto functions_set = GetAnnotatedTypeFunctionsMap(node, base_node); // auto functions_set = GetAnnotatedTypeFunctionsMap(node, base_node);
//
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo>> functions_vector; // std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo>> functions_vector;
functions_vector.reserve(functions_vector.size()); // functions_vector.reserve(functions_vector.size());
for (auto& typeclass : functions_set) { // for (auto& typeclass : functions_set) {
functions_vector.push_back(typeclass); // functions_vector.push_back(typeclass);
} // }
return functions_vector; // return functions_vector;
} // }
std::unordered_map<std::string, utils::IdType>* std::unordered_map<std::string, utils::IdType>*
GlobalInfo::ChooseNamespaces(utils::ClassInternalsModifier modifier, GlobalInfo::ChooseNamespaces(utils::ClassInternalsModifier modifier,
@ -558,6 +558,7 @@ std::optional<utils::IdType> GlobalInfo::AddTypeclassToGraph(utils::IdType typec
definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace); definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace);
std::string name = typeclass_info->node->definition->type->type; std::string name = typeclass_info->node->definition->type->type;
interpreter::tokens::BaseNode* base_node = &typeclass_info->node->base;
std::vector<std::string> dependencies; std::vector<std::string> dependencies;
std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>> function_declarations; std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>> function_declarations;
std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>> function_definitions; std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>> function_definitions;
@ -566,7 +567,7 @@ std::optional<utils::IdType> GlobalInfo::AddTypeclassToGraph(utils::IdType typec
std::string dependency = dependency_node->typeclass; std::string dependency = dependency_node->typeclass;
if (dependency_node->parameters.size() > 0) { if (dependency_node->parameters.size() > 0) {
error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet",
"TypeclassGraph.AddTypeclassByNode"); "GlobalInfo.AddTypeclassToGraph");
} }
dependencies.push_back(dependency); dependencies.push_back(dependency);
} }
@ -595,11 +596,34 @@ std::optional<utils::IdType> GlobalInfo::AddTypeclassToGraph(utils::IdType typec
function_definitions); function_definitions);
} }
return typeclass_graph_.AddTypeclass(name, return typeclass_graph_.AddVertex(name,
typeclass_info->node,
dependencies, dependencies,
function_declarations, function_declarations,
function_definitions); function_definitions,
base_node,
TypeclassGraph::Modifier::Typeclass);
}
std::optional<utils::IdType> GlobalInfo::AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node) {
std::string name = node->type;
interpreter::tokens::BaseNode* base_node = &node->base;
std::vector<std::string> dependencies;
for (auto& dependency_node : node->typeclasses) {
std::string dependency = dependency_node->typeclass;
if (dependency_node->parameters.size() > 0) {
error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet",
"GlobalInfo.AddAnnotatedTypeToGraph");
}
dependencies.push_back(dependency);
}
return typeclass_graph_.AddVertex(name,
dependencies,
{},
{},
base_node,
TypeclassGraph::Modifier::Type);
} }
void GlobalInfo::CollectFunctionInfo( void GlobalInfo::CollectFunctionInfo(

View file

@ -47,6 +47,13 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
// Definitions ----------------- // Definitions -----------------
void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
Visitor::Visit(node->definition.get());
Visitor::Visit(node->value);
// TODO: add type declarations / definitions
}
void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
Visitor::Visit(node->definition.get()); Visitor::Visit(node->definition.get());
for (auto& function_requirement : node->requirements) { for (auto& function_requirement : node->requirements) {

View file

@ -1,31 +1,41 @@
// for clangd // for clangd
#include "../include/typeclass_graph.hpp" #include "../include/typeclass_graph.hpp"
#include "../include/error_handling.hpp"
namespace info { namespace info {
std::optional<utils::IdType> TypeclassGraph::AddTypeclass( utils::IdType TypeclassGraph::AddVertex(
const std::string& name, const std::string& name,
interpreter::tokens::TypeclassDefinitionStatement* definition,
const std::vector<std::string>& dependencies, // TODO: parameters const std::vector<std::string>& dependencies, // TODO: parameters
const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations, const std::vector<std::pair<std::string, std::pair<utils::ClassInternalsModifier, interpreter::tokens::FunctionDeclaration*>>>& function_declarations,
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions) { const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions,
interpreter::tokens::BaseNode* base_node,
Modifier modifier) {
if (name_to_typeclass_.count(name) != 0) {
error_handling::HandleTypecheckError("Typeclass \"" + name + "\" already defined (other type / typeclass can't have this name)", *base_node);
}
if (modifier == Modifier::Typeclass) {
for (auto& method : function_declarations) { for (auto& method : function_declarations) {
if (method_to_typeclass_.count(method.first) != 0) { if (method_to_vertex_.count(method.first) != 0) {
return std::nullopt; error_handling::HandleTypecheckError("Typeclass \"" + name + "\" method \"" + method.first + "\" already declaret in another typeclass", *base_node);
}
} }
} }
is_calculated_ = false; is_calculated_ = false;
utils::IdType id = typeclasses_.size(); utils::IdType id = verticles_.size();
typeclasses_.emplace_back(); verticles_.emplace_back();
TypeclassVertex& typeclass = typeclasses_.back(); Vertex& vertex = verticles_.back();
typeclass.name = name; vertex.name = name;
typeclass.definition = definition; vertex.base_node = base_node;
vertex.modifier = modifier;
for (auto& dependency : dependencies) { for (auto& dependency : dependencies) {
typeclass.dependencies.insert(dependency); vertex.dependencies.insert(dependency);
} }
for (auto& method : function_declarations) { for (auto& method : function_declarations) {
@ -33,31 +43,37 @@ std::optional<utils::IdType> TypeclassGraph::AddTypeclass(
function_info.modifier = method.second.first; function_info.modifier = method.second.first;
function_info.declaration = method.second.second; function_info.declaration = method.second.second;
typeclass.functions[method.first] = function_info; vertex.functions[method.first] = function_info;
method_to_typeclass_[method.first] = id; if (modifier == Modifier::Typeclass) {
method_to_vertex_[method.first] = id;
} }
}
if (modifier == Modifier::Typeclass) {
name_to_typeclass_[name] = id; name_to_typeclass_[name] = id;
}
for (auto& method : function_definitions) { for (auto& method : function_definitions) {
typeclass.functions[method.first].definition = method.second; FunctionInfo& function_info = vertex.functions[method.first];
function_info.definition = method.second;
function_info.is_defined_in_owner = true;
} }
return id; return id;
} }
std::optional<utils::IdType> TypeclassGraph::FindFunctionTypeclass(const std::string& name) { std::optional<utils::IdType> TypeclassGraph::FindFunctionTypeclass(const std::string& name) {
auto function_iter = method_to_typeclass_.find(name); auto function_iter = method_to_vertex_.find(name);
if (function_iter == method_to_typeclass_.end()) { if (function_iter == method_to_vertex_.end()) {
return std::nullopt; return std::nullopt;
} }
return function_iter->second; return function_iter->second;
} }
std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::GetFunctionInfo(const std::string& name, std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::GetFunctionInfo(const std::string& name,
std::optional<utils::IdType> typeclass_id) { std::optional<utils::IdType> vertex_id) {
if (typeclass_id.has_value()) { if (vertex_id.has_value()) {
return &typeclasses_[typeclass_id.value()].functions[name]; return &verticles_[vertex_id.value()].functions[name];
} }
auto maybe_function_typeclass_id = FindFunctionTypeclass(name); auto maybe_function_typeclass_id = FindFunctionTypeclass(name);
@ -66,47 +82,45 @@ std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::GetFunctionInfo(con
return std::nullopt; return std::nullopt;
} }
return &typeclasses_[maybe_function_typeclass_id.value()].functions[name]; return &verticles_[maybe_function_typeclass_id.value()].functions[name];
} }
// cache ?? std::unordered_set<utils::IdType> TypeclassGraph::GetDependenciesSet(utils::IdType id) {
std::vector<utils::IdType> TypeclassGraph::GetTypeclassDependencies(utils::IdType id) { std::unordered_set<utils::IdType> dependencies;
dependencies.reserve(verticles_.at(id).dependencies.size());
for (auto& dependency : verticles_[id].dependencies) {
dependencies.insert(name_to_typeclass_[dependency]);
}
return dependencies;
}
std::vector<utils::IdType> TypeclassGraph::GetDependenciesVector(utils::IdType id) {
std::vector<utils::IdType> dependencies; std::vector<utils::IdType> dependencies;
dependencies.reserve(typeclasses_.at(id).dependencies.size()); dependencies.reserve(verticles_.at(id).dependencies.size());
for (auto& dependency : typeclasses_[id].dependencies) { for (auto& dependency : verticles_[id].dependencies) {
dependencies.push_back(name_to_typeclass_[dependency]); dependencies.push_back(name_to_typeclass_[dependency]);
} }
return dependencies; return dependencies;
} }
// cache ?? void TypeclassGraph::CalculateGraph() {
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> TypeclassGraph::GetTypeclassFunctions(utils::IdType id) {
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> functions;
functions.reserve(typeclasses_.at(id).functions.size());
for (auto& function : typeclasses_[id].functions) {
functions.push_back({function.first, &function.second});
}
return functions;
}
bool TypeclassGraph::CalculateGraph() {
if (is_calculated_) { if (is_calculated_) {
return true; return;
} }
std::vector<std::vector<size_t>> edges(typeclasses_.size()); std::vector<std::vector<size_t>> edges(verticles_.size());
for (size_t i = 0; i < typeclasses_.size(); ++i) { for (size_t i = 0; i < verticles_.size(); ++i) {
edges[i].reserve(typeclasses_[i].dependencies.size()); edges[i].reserve(verticles_[i].dependencies.size());
for (auto& dependency :typeclasses_[i].dependencies) { for (auto& dependency : verticles_[i].dependencies) {
auto dependency_iter = name_to_typeclass_.find(dependency); auto dependency_iter = name_to_typeclass_.find(dependency);
if (dependency_iter == name_to_typeclass_.end()) { if (dependency_iter == name_to_typeclass_.end()) {
return false; error_handling::HandleTypecheckError("Dependency typeclass \"" + dependency + "\" not found", *verticles_[i].base_node);
} }
edges[i].push_back(dependency_iter->second); edges[i].push_back(dependency_iter->second);
@ -117,26 +131,28 @@ bool TypeclassGraph::CalculateGraph() {
std::reverse(sorted_verticles.begin(), sorted_verticles.end()); std::reverse(sorted_verticles.begin(), sorted_verticles.end());
for (auto& id : sorted_verticles) { for (auto& id : sorted_verticles) {
for (auto& dependency : typeclasses_[id].dependencies) { for (auto& dependency : verticles_[id].dependencies) {
for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) { for (auto& method : verticles_[name_to_typeclass_[dependency]].functions) {
auto function_iter = typeclasses_[id].functions.find(method.first); auto function_iter = verticles_[id].functions.find(method.first);
if (function_iter == typeclasses_[id].functions.end()) { if (function_iter == verticles_[id].functions.end()) {
typeclasses_[id].functions[method.first] = method.second; verticles_[id].functions[method.first] = method.second;
} else { } else {
if (!function_iter->second.definition.has_value()) { if (!function_iter->second.definition.has_value()) {
function_iter->second.definition = method.second.definition; function_iter->second.definition = method.second.definition;
} else {
if (!function_iter->second.is_defined_in_owner) {
error_handling::HandleTypecheckError("Method \"" + method.first + "\" defined in more then one dependency of type / typeclass \"" + verticles_[id].name + "\"", *verticles_[id].base_node);
} }
} }
} }
for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) { }
typeclasses_[id].dependencies.insert(inherited_dependency); for (auto& inherited_dependency : verticles_[method_to_vertex_[dependency]].dependencies) {
verticles_[id].dependencies.insert(inherited_dependency);
} }
} }
} }
is_calculated_ = true; is_calculated_ = true;
return true;
} }
} // namespace info } // namespace info