fixes, build_visitor TupleType and VariantType fix

This commit is contained in:
ProgramSnail 2023-05-17 17:57:56 +03:00
parent 692f7ea3ec
commit b723fd6a65
12 changed files with 321 additions and 241 deletions

View file

@ -20,7 +20,7 @@ add_executable(lang_interpreter src/main.cpp
src/types.cpp
src/values.cpp
src/global_info.cpp
include/definitions.hpp
src/typeclass_graph.cpp
src/visitor.cpp
src/build_visitor.cpp
src/print_visitor.cpp

View file

@ -132,7 +132,7 @@ private:
return true;
}
if (variables_.count(name) > 0) {
if (variables_.count(name) != 0) {
return false;
}
variables_[name] = value_id;
@ -140,7 +140,7 @@ private:
}
bool DefineLocalType(const std::string& name, utils::IdType type_id) {
if (local_types_.count(name) > 0) {
if (local_types_.count(name) != 0) {
return false;
}
local_types_[name] = type_id;

View file

@ -48,7 +48,7 @@ struct AnyType {
interpreter::tokens::AnyType* value;
utils::ClassModifier modifier;
utils::IdType parent_namespace;
utils::IdType parent_namespace = 0;
};
struct Type {
@ -57,8 +57,8 @@ struct Type {
struct Constructor {
std::string name;
size_t order;
utils::IdType type_id;
std::optional<size_t> order; // no order for tuple types
utils::IdType type_id = 0;
std::optional<interpreter::tokens::TupleType*> constructor_tuple_node;
};
@ -83,9 +83,9 @@ struct Typeclass {
std::vector<Parameter> parameters;
interpreter::tokens::TypeclassDefinitionStatement* node;
utils::IdType parent_namespace;
utils::IdType parent_namespace = 0;
utils::IdType graph_id_; // TODO: make safe??
utils::IdType graph_id_ = 0; // TODO: make safe??
};
struct Import {
@ -101,7 +101,7 @@ struct Namespace {
std::unordered_map<std::string, utils::IdType> var_namespaces;
std::unordered_map<std::string, utils::IdType> const_namespaces;
utils::IdType parent_namespace;
utils::IdType parent_namespace = 0;
utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static;
std::string type_name;

View file

@ -32,146 +32,32 @@ public:
interpreter::tokens::TypeclassDefinitionStatement* definition,
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, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions) {
for (auto& method : function_declarations) {
if (method_to_typeclass_.count(method.first) != 0) {
return std::nullopt;
}
}
const std::vector<std::pair<std::string, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions);
is_calculated_ = false;
typeclasses_.emplace_back();
TypeclassVertex& typeclass = typeclasses_.back();
typeclass.name = name;
typeclass.definition = definition;
for (auto& dependency : dependencies) {
typeclass.dependencies.insert(dependency);
}
for (auto& method : function_declarations) {
FunctionInfo function_info;
function_info.modifier = method.second.first;
function_info.declaration = method.second.second;
typeclass.functions[method.first] = function_info;
method_to_typeclass_[method.first] = typeclasses_.size();
}
name_to_typeclass_[name] = typeclasses_.size() - 1;
for (auto& method : function_definitions) {
typeclass.functions[method.first].definition = method.second;
}
return typeclasses_.size() - 1;
}
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name) {
auto function_iter = method_to_typeclass_.find(name);
if (function_iter == method_to_typeclass_.end()) {
return std::nullopt;
}
return function_iter->second;
}
std::optional<utils::IdType> FindFunctionTypeclass(const std::string& name);
bool IsFunctionInTypeclass(const std::string& name, utils::IdType typeclass_id) {
return typeclasses_[typeclass_id].functions.count(name) != 0;
}
std::optional<FunctionInfo*> GetFunctionInfo(const std::string& name,
std::optional<utils::IdType> typeclass_id) {
if (typeclass_id.has_value()) {
return &typeclasses_[typeclass_id.value()].functions[name];
}
auto maybe_function_typeclass_id = FindFunctionTypeclass(name);
if (!maybe_function_typeclass_id.has_value()) {
return std::nullopt;
}
return &typeclasses_[maybe_function_typeclass_id.value()].functions[name];
}
std::optional<utils::IdType> typeclass_id);
const TypeclassVertex& GetTypeclass(utils::IdType typeclass_id) { // check, if calculated ??
return typeclasses_.at(typeclass_id);
}
// cache ??
std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id) {
std::vector<utils::IdType> dependencies;
dependencies.reserve(typeclasses_.at(id).dependencies.size());
for (auto& dependency : typeclasses_[id].dependencies) {
dependencies.push_back(name_to_typeclass_[dependency]);
}
return dependencies;
}
std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id);
// cache ??
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> 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;
}
std::vector<std::pair<std::string, TypeclassGraph::FunctionInfo*>> GetTypeclassFunctions(utils::IdType id);
bool IsCalculated() {
return is_calculated_;
}
bool CalculateGraph() {
if (is_calculated_) {
return true;
}
std::vector<std::vector<size_t>> edges(typeclasses_.size());
for (size_t i = 0; i < typeclasses_.size(); ++i) {
edges[i].reserve(typeclasses_[i].dependencies.size());
for (auto& dependency :typeclasses_[i].dependencies) {
auto dependency_iter = name_to_typeclass_.find(dependency);
if (dependency_iter == name_to_typeclass_.end()) {
return false;
}
edges[i].push_back(dependency_iter->second);
}
}
std::vector<size_t> sorted_verticles = utils::BackTopSort(edges);
std::reverse(sorted_verticles.begin(), sorted_verticles.end());
for (auto& id : sorted_verticles) {
for (auto& dependency : typeclasses_[id].dependencies) {
for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) {
auto function_iter = typeclasses_[id].functions.find(method.first);
if (function_iter == typeclasses_[id].functions.end()) {
typeclasses_[id].functions[method.first] = method.second;
} else {
if (!function_iter->second.definition.has_value()) {
function_iter->second.definition = method.second.definition;
}
}
}
for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) {
typeclasses_[id].dependencies.insert(inherited_dependency);
}
}
}
is_calculated_ = true;
return true;
}
bool CalculateGraph();
private:
std::unordered_map<std::string, utils::IdType> method_to_typeclass_;

View file

@ -8,6 +8,7 @@
#include <unordered_map>
// for clangd
#include "error_handling.hpp"
#include "utils.hpp"
namespace info::type {
@ -24,8 +25,8 @@ public:
const std::vector<utils::IdType>& requirement_graph_ids)
: modifier_(modifier),
name_(name) {
for (auto& typeclass : requirement_graph_ids) {
requirement_graph_ids_.insert(typeclass);
for (auto& requirement_graph_id : requirement_graph_ids) {
requirement_graph_ids_.insert(requirement_graph_id);
}
}

View file

@ -228,7 +228,8 @@ private:
std::vector<size_t> ranks_;
};
static void BackVisitDfs(size_t id,
// move to .cpp ??
inline void BackVisitDfs(size_t id,
std::vector<size_t>& verticles,
std::vector<size_t>& marks,
const std::vector<std::vector<size_t>>& edges,
@ -245,7 +246,8 @@ static void BackVisitDfs(size_t id,
}
}
static std::vector<size_t> BackTopSort(const std::vector<std::vector<size_t>>& edges_) {
// move to .cpp ??
inline std::vector<size_t> BackTopSort(const std::vector<std::vector<size_t>>& edges_) {
std::vector<size_t> sorted_verticles;
std::vector<size_t> marks(edges_.size(), 0);

View file

@ -1292,32 +1292,32 @@ void BuildVisitor::Visit(TupleType* node) {
auto parse_node = current_node_;
size_t current_node_n = 0;
size_t current_child = 0;
current_node_ = parse_node.NthNamedChild(current_node_n);
current_node_ = parse_node.NthNamedChild(current_child);
if (current_node_.GetType() == parser::tokens::Constructor) {
if (parse_node.NthChild(0).GetValue() != "&") {
node->type = current_node_.GetValue();
++current_node_n;
current_node_ = parse_node.NthNamedChild(current_node_n);
++current_child;
current_node_ = parse_node.NthNamedChild(current_child);
}
while (current_node_n < parse_node.NamedChildCount()) {
while (current_child < parse_node.NamedChildCount()) {
node->entities.emplace_back();
if (current_node_.GetType() == parser::tokens::NameIdentifier) {
node->entities.back().first = current_node_.GetValue();
++current_node_n;
current_node_ = parse_node.NthNamedChild(current_node_n);
++current_child;
current_node_ = parse_node.NthNamedChild(current_child);
}
node->entities.back().second = std::make_unique<ExtendedScopedAnyType>();
Visit(node->entities.back().second.get());
++current_node_n;
current_node_ = parse_node.NthNamedChild(current_node_n);
++current_child;
current_node_ = parse_node.NthNamedChild(current_child);
}
current_node_ = parse_node;
@ -1328,33 +1328,31 @@ void BuildVisitor::Visit(VariantType* node) {
auto parse_node = current_node_;
size_t current_node_n = 0;
size_t excluded_child_count = 0;
current_node_ = parse_node.NthNamedChild(current_node_n);
size_t child_count = parse_node.NamedChildCount();
if (current_node_.GetType() == parser::tokens::Constructor) {
node->type = current_node_.GetValue();
if (parse_node.NthChild(0).GetValue() != "|") {
node->type = parse_node.NthNamedChild(0).GetValue();
++current_node_n;
current_node_ = parse_node.NthNamedChild(current_node_n);
++excluded_child_count;
}
while (current_node_n < parse_node.NamedChildCount()) {
node->constructors.resize(child_count - excluded_child_count);
for (size_t i = 0; i < node->constructors.size(); ++i) {
current_node_ = parse_node.NthNamedChild(i + excluded_child_count);
std::string current_node_type = current_node_.GetType();
node->constructors.emplace_back();
if (current_node_type == parser::tokens::Constructor) {
node->constructors.back() = current_node_.GetValue();
node->constructors[i] = current_node_.GetValue();
} else if (current_node_type == parser::tokens::TupleType) {
node->constructors.back() = std::make_unique<TupleType>();
Visit(std::get<std::unique_ptr<TupleType>>(node->constructors.back()).get());
node->constructors[i] = std::make_unique<TupleType>();
Visit(std::get<std::unique_ptr<TupleType>>(node->constructors[i]).get());
} else {
// error
}
++current_node_n;
current_node_ = parse_node.NthNamedChild(current_node_n);
}
current_node_ = parse_node;

View file

@ -63,6 +63,7 @@ void ExecuteVisitor::Visit(PartitionStatement* node) {
void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern
// TODO
// TODO: tuples
// TODO: non-variant constructor patterns
void ExecuteVisitor::Visit(TypeConstructorPattern* node) {
if (!node->constructor->constructor_id_.has_value()) { // checked in typeckeck visitor ??
@ -475,7 +476,7 @@ void ExecuteVisitor::Visit(ReturnExpression* node) {
void ExecuteVisitor::Visit(TypeConstructorParameter* node) {} // handled in TypeConstructor
// TODO: variants, etc.
void ExecuteVisitor::Visit(TypeConstructor* node) {
// TODO: support for non-tuples
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
@ -493,6 +494,10 @@ void ExecuteVisitor::Visit(TypeConstructor* node) {
current_value_ = context_manager_.AddValue<info::value::TupleValue>(
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
utils::ValueType::Tmp);
// if (constructor_info.order.has_value()) {
// // TODO: construct variant value
// }
}
// TODO

View file

@ -167,42 +167,56 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
definition::Type& moved_type_info = global_info_.types_.back();
// TODO: constructors for tuple types, function types (??), array types (??), ...
if (!std::holds_alternative<definition::AnyType>(moved_type_info.type)) {
error_handling::HandleInternalError("Not AnyType constructor search is not implemented yet",
"GlobalInfo.NamespaceVisitor.AddType");
}
if (std::holds_alternative<definition::AnyType>(moved_type_info.type)) {
definition::AnyType& any_type_info = std::get<definition::AnyType>(moved_type_info.type);
if (std::holds_alternative<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value)) {
interpreter::tokens::VariantType& variant_type_info = *std::get<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value);
for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) {
std::string constructor_name;
definition::Constructor constructor_info;
definition::AnyType& any_type_info = std::get<definition::AnyType>(moved_type_info.type);
if (std::holds_alternative<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value)) {
interpreter::tokens::VariantType& variant_type_info = *std::get<std::unique_ptr<interpreter::tokens::VariantType>>(*any_type_info.value);
for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) {
std::string constructor_name;
definition::Constructor constructor_info;
constructor_info.type_id = id;
constructor_info.order = i;
constructor_info.type_id = id;
constructor_info.order = i;
if (std::holds_alternative<interpreter::tokens::Constructor>(variant_type_info.constructors[i])) {
constructor_name = std::get<interpreter::tokens::Constructor>(variant_type_info.constructors[i]);
} else if (std::holds_alternative<
std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i])) {
constructor_info.constructor_tuple_node =
std::get<std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i]).get();
if (std::holds_alternative<interpreter::tokens::Constructor>(variant_type_info.constructors[i])) {
constructor_name = std::get<interpreter::tokens::Constructor>(variant_type_info.constructors[i]);
} else if (std::holds_alternative<
std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i])) {
constructor_info.constructor_tuple_node =
std::get<std::unique_ptr<interpreter::tokens::TupleType>>(variant_type_info.constructors[i]).get();
auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type;
auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type;
if (maybe_constructor_name.has_value()) {
constructor_name = maybe_constructor_name.value();
} else {
constructor_name = type;
}
if (maybe_constructor_name.has_value()) {
constructor_name = maybe_constructor_name.value();
} else {
// error
constructor_name = type;
}
constructor_info.name = constructor_name;
AddConstructor(constructor_name, std::move(constructor_info), base_node);
} else {
error_handling::HandleInternalError("Unexprected VariantType constructor node type",
"GlobalInfo.NamespaceVisitor.AddType");
}
constructor_info.name = constructor_name;
AddConstructor(constructor_name, std::move(constructor_info), base_node);
}
} else if (std::holds_alternative<std::unique_ptr<interpreter::tokens::TupleType>>(*any_type_info.value)) {
definition::Constructor constructor_info;
constructor_info.type_id = id;
// constructor_info.order = std::nullopt;
constructor_info.name = type;
constructor_info.constructor_tuple_node = std::get<std::unique_ptr<interpreter::tokens::TupleType>>(*any_type_info.value).get();
AddConstructor(type, std::move(constructor_info), base_node);
} else {
// TODO: constructors for function types (??), array types (??), ...
error_handling::HandleInternalError("Not VariantType constructor search is not implemented yet",
"GlobalInfo.NamespaceVisitor.AddType");
}
return id;

View file

@ -1,3 +1,4 @@
#include <bits/types/error_t.h>
#include <optional>
// for clangd
@ -26,6 +27,7 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
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()) {

View file

@ -36,10 +36,12 @@ void TypeCheckVisitor::Visit(Namespace* node) {
if (node->link_typeclass_id_.has_value()) {
utils::IdType graph_id = global_info_.GetTypeclassInfo(node->link_typeclass_id_.value()).graph_id_;
std::vector<utils::IdType> requirements = typeclass_graph_.GetTypeclassDependencies(graph_id);
requirements.push_back(graph_id);
std::vector<utils::IdType> requirement_graph_ids = typeclass_graph_.GetTypeclassDependencies(graph_id);
requirement_graph_ids.push_back(graph_id);
utils::IdType abstract_type = context_manager_.AddValue(
info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements),
info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
node->type,
requirement_graph_ids),
ClassInternalsModifierToValueType(node->modifier));
if (node->modifier != utils::ClassInternalsModifier::Static) {
@ -48,29 +50,42 @@ void TypeCheckVisitor::Visit(Namespace* node) {
} else {
context_manager_.EnterContext();
}
context_manager_.DefineLocalType(node->type, abstract_type);
// including namespace typeclass
// define typeclasses local types as namespace typeclass
for (auto& requirement_graph_id : requirement_graph_ids) {
context_manager_.DefineLocalType(typeclass_graph_.GetTypeclass(requirement_graph_id).name, abstract_type);
}
} else if (node->link_type_id_.has_value()) {
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(node->link_type_id_.value());
if (!maybe_type_info.has_value()) {
error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base);
}
info::definition::AnyType* type_info = maybe_type_info.value();
Visitor::Visit(*type_info->value);
utils::IdType type = context_manager_.AddValue(
info::type::DefinedType(node->link_type_id_.value(),
current_type_,
type_info->modifier,
context_manager_.GetValueManager()),
ClassInternalsModifierToValueType(node->modifier));
if (node->modifier != utils::ClassInternalsModifier::Static) {
auto maybe_type_info = global_info_.GetTypeInfo<info::definition::AnyType>(node->link_type_id_.value());
if (!maybe_type_info.has_value()) {
error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base);
}
Visitor::Visit(*maybe_type_info.value()->value); // handle error?
context_manager_.EnterVariableContext(
utils::ClassInternalVarName,
context_manager_.AddValue(
info::type::DefinedType(node->link_type_id_.value(),
current_type_,
maybe_type_info.value()->modifier,
context_manager_.GetValueManager()),
ClassInternalsModifierToValueType(node->modifier)));
context_manager_.EnterVariableContext(utils::ClassInternalVarName, type);
} else {
context_manager_.EnterContext();
}
// better decision ??
// define typeclasses local types as namespace type
auto typeclass_graph_ids = global_info_.GetAnnotatedTypeTypeclassesVector(type_info->type.node);
for (auto& typeclass_graph_id : typeclass_graph_ids) {
context_manager_.DefineLocalType(typeclass_graph_.GetTypeclass(typeclass_graph_id).name, type);
}
if (type_namespaces_.count(node->link_type_id_.value()) != 0) {
error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base);
}
@ -344,6 +359,7 @@ void TypeCheckVisitor::Visit(AnyAnnotatedType* node) {
void TypeCheckVisitor::Visit(TypeConstructorPatternParameter* node) {} // Handled in TypeConstructorPattern
// TODO
// TODO: check for tuples
void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match named constructor
if (!node->constructor->constructor_id_.has_value()) {
error_handling::HandleTypecheckError("Type constructor pattern constructor name not found", node->base);
@ -815,6 +831,7 @@ void TypeCheckVisitor::Visit(ReturnExpression* node) {
void TypeCheckVisitor::Visit(TypeConstructorParameter* node) {} // Handeled in TypeConstructor visit
// TODO: check for tuples
void TypeCheckVisitor::Visit(TypeConstructor* node) {
if (!node->constructor->constructor_id_.has_value()) {
error_handling::HandleTypecheckError("Type constructor name not found", node->base);
@ -884,10 +901,15 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) {
std::optional<info::type::VariantType*> maybe_variant_type =
context_manager_.GetValue<info::type::VariantType>(current_type_);
if (maybe_type_info.has_value()) {
maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order);
if (maybe_variant_type.has_value()) {
if (!constructor_info.order.has_value()) {
error_handling::HandleInternalError("No order found in constructor of VariantType", "TypeCheckVisitor.TypeConstructor");
}
maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order.value());
}
// if it is tuple, order not required
current_type_ = TypeInContext(current_type_, context);
node->base.type_ = current_type_;
@ -1405,7 +1427,7 @@ std::optional<FunctionDeclaration*>
}
// TODO: internal types ??
// TODO: abstract types, typeclasses
// TODO: handle abstract defined types ??
std::optional<FunctionDeclaration*>
TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node,
TypeExpression* type_node,
@ -1540,26 +1562,30 @@ std::optional<FunctionDeclaration*>
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
if (!maybe_typeclass_graph_id.has_value()) {
error_handling::HandleTypecheckError("Typeclass function not found", node->base);
return std::nullopt;
// error_handling::HandleTypecheckError("Typeclass function not found", node->base);
}
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name,
maybe_typeclass_graph_id.value());
if (abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) {
if (!maybe_typeclass_function_info.has_value()) {
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)",
"TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate");
}
if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) {
return std::nullopt;
}
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
if (!abstract_type_info->HasTypeclass(maybe_typeclass_graph_id.value())) {
error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (abstract type)", node->base);
}
if (!maybe_typeclass_function_info.has_value()) {
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (abstract type)",
"TypeCheckVisitor.FindAbstractTypeTypeclassFunctionAndUpdate");
}
// TODO: check that const functions not called on var expressions
if ((maybe_typeclass_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) {
error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base);
}
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
return maybe_function_declaration;
}
@ -1571,27 +1597,31 @@ std::optional<FunctionDeclaration*>
std::optional<FunctionDeclaration*> maybe_function_declaration;
auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(node->name);
if (maybe_typeclass_graph_id.has_value()) {
auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node);
auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value());
if (function_typeclass_iter != typeclasses.end()) {
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name,
maybe_typeclass_graph_id.value());
if (!maybe_typeclass_function_info.has_value()) {
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (definied type)",
"TypeCheckVisitor.FindDefinedTypeTypeclassFunctionAndUpdate");
}
if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) {
return std::nullopt;
}
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
}
if (!maybe_typeclass_graph_id.has_value()) {
return std::nullopt;
}
auto typeclasses = global_info_.GetAnnotatedTypeTypeclassesSet(defined_type->type.node);
auto function_typeclass_iter = typeclasses.find(maybe_typeclass_graph_id.value());
if (function_typeclass_iter == typeclasses.end()) {
error_handling::HandleTypecheckError("Function typeclass not pesent in type typeclasses list (defined type)", node->base);
}
auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name,
maybe_typeclass_graph_id.value());
if (!maybe_typeclass_function_info.has_value()) {
error_handling::HandleInternalError("Typeclass function info found, but typeclass id not found (definied type)",
"TypeCheckVisitor.FindDefinedTypeTypeclassFunctionAndUpdate");
}
if ((maybe_typeclass_function_info.value()->modifier == utils::ClassInternalsModifier::Static) != is_method) {
return std::nullopt;
}
node->typeclass_graph_id_ = maybe_typeclass_graph_id;
maybe_function_declaration = maybe_typeclass_function_info.value()->declaration;
return maybe_function_declaration;
}

142
src/typeclass_graph.cpp Normal file
View file

@ -0,0 +1,142 @@
// for clangd
#include "../include/typeclass_graph.hpp"
namespace info {
std::optional<utils::IdType> TypeclassGraph::AddTypeclass(
const std::string& name,
interpreter::tokens::TypeclassDefinitionStatement* definition,
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, interpreter::tokens::FunctionDefinitionStatement*>>& function_definitions) {
for (auto& method : function_declarations) {
if (method_to_typeclass_.count(method.first) != 0) {
return std::nullopt;
}
}
is_calculated_ = false;
utils::IdType id = typeclasses_.size();
typeclasses_.emplace_back();
TypeclassVertex& typeclass = typeclasses_.back();
typeclass.name = name;
typeclass.definition = definition;
for (auto& dependency : dependencies) {
typeclass.dependencies.insert(dependency);
}
for (auto& method : function_declarations) {
FunctionInfo function_info;
function_info.modifier = method.second.first;
function_info.declaration = method.second.second;
typeclass.functions[method.first] = function_info;
method_to_typeclass_[method.first] = id;
}
name_to_typeclass_[name] = id;
for (auto& method : function_definitions) {
typeclass.functions[method.first].definition = method.second;
}
return id;
}
std::optional<utils::IdType> TypeclassGraph::FindFunctionTypeclass(const std::string& name) {
auto function_iter = method_to_typeclass_.find(name);
if (function_iter == method_to_typeclass_.end()) {
return std::nullopt;
}
return function_iter->second;
}
std::optional<TypeclassGraph::FunctionInfo*> TypeclassGraph::GetFunctionInfo(const std::string& name,
std::optional<utils::IdType> typeclass_id) {
if (typeclass_id.has_value()) {
return &typeclasses_[typeclass_id.value()].functions[name];
}
auto maybe_function_typeclass_id = FindFunctionTypeclass(name);
if (!maybe_function_typeclass_id.has_value()) {
return std::nullopt;
}
return &typeclasses_[maybe_function_typeclass_id.value()].functions[name];
}
// cache ??
std::vector<utils::IdType> TypeclassGraph::GetTypeclassDependencies(utils::IdType id) {
std::vector<utils::IdType> dependencies;
dependencies.reserve(typeclasses_.at(id).dependencies.size());
for (auto& dependency : typeclasses_[id].dependencies) {
dependencies.push_back(name_to_typeclass_[dependency]);
}
return dependencies;
}
// cache ??
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_) {
return true;
}
std::vector<std::vector<size_t>> edges(typeclasses_.size());
for (size_t i = 0; i < typeclasses_.size(); ++i) {
edges[i].reserve(typeclasses_[i].dependencies.size());
for (auto& dependency :typeclasses_[i].dependencies) {
auto dependency_iter = name_to_typeclass_.find(dependency);
if (dependency_iter == name_to_typeclass_.end()) {
return false;
}
edges[i].push_back(dependency_iter->second);
}
}
std::vector<size_t> sorted_verticles = utils::BackTopSort(edges);
std::reverse(sorted_verticles.begin(), sorted_verticles.end());
for (auto& id : sorted_verticles) {
for (auto& dependency : typeclasses_[id].dependencies) {
for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) {
auto function_iter = typeclasses_[id].functions.find(method.first);
if (function_iter == typeclasses_[id].functions.end()) {
typeclasses_[id].functions[method.first] = method.second;
} else {
if (!function_iter->second.definition.has_value()) {
function_iter->second.definition = method.second.definition;
}
}
}
for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) {
typeclasses_[id].dependencies.insert(inherited_dependency);
}
}
}
is_calculated_ = true;
return true;
}
} // namespace info