abstract types typecheck, fixes

This commit is contained in:
ProgramSnail 2023-05-16 12:43:55 +03:00
parent 9aeba7b0de
commit c433448952
9 changed files with 143 additions and 94 deletions

View file

@ -26,6 +26,8 @@ struct TypeUsage {
struct Parameter { struct Parameter {
std::string type; std::string type;
std::vector<interpreter::tokens::ParametrizedTypeclass*> typeclass_nodes; std::vector<interpreter::tokens::ParametrizedTypeclass*> typeclass_nodes;
interpreter::tokens::AnyAnnotatedType* node = nullptr;
}; };
struct AbstractType { struct AbstractType {
@ -82,15 +84,16 @@ struct Typeclass {
interpreter::tokens::TypeclassDefinitionStatement* node; interpreter::tokens::TypeclassDefinitionStatement* node;
utils::IdType parent_namespace; utils::IdType parent_namespace;
utils::IdType graph_id_; // TODO: make safe??
}; };
struct Import { struct Import {
std::string module_name; std::string module_name;
std::vector<std::string> symbols; // size = 0 => all symbols imported std::vector<std::string> symbols; // size == 0 => all symbols imported
}; };
struct Namespace { struct Namespace {
std::unordered_map<std::string, utils::IdType> types; std::unordered_map<std::string, utils::IdType> types;
std::unordered_map<std::string, utils::IdType> functions; std::unordered_map<std::string, utils::IdType> functions;
std::unordered_map<std::string, utils::IdType> constructors; std::unordered_map<std::string, utils::IdType> constructors;
@ -103,7 +106,8 @@ struct Namespace {
utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static;
std::string type_name; std::string type_name;
std::optional<interpreter::tokens::Namespace*> node; // all nodes have same info
std::optional<interpreter::tokens::Namespace*> any_node;
}; };
} // namespace info::definition } // namespace info::definition

View file

@ -55,4 +55,17 @@ inline void HandleRuntimeError(const std::string& message,
exit(1); exit(1);
} }
inline void HandleNamesError(const std::string& message,
const interpreter::tokens::BaseNode& node) {
std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at ";
PrintPosition(std::cerr, node.start_position, node.end_position);
std::cerr << ".\n";
exit(1);
}
template<typename T>
inline void DebugPrint(const T& value) {
std::cerr << "\x1b[1;33mDebug:\x1b[0m " << value << '\n';
}
} // namespace error_handling } // namespace error_handling

View file

@ -3,6 +3,7 @@
#include <string> #include <string>
#include <functional> #include <functional>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
// for clangd // for clangd
#include "definitions.hpp" #include "definitions.hpp"
@ -12,7 +13,6 @@
namespace info { namespace info {
// TODO: better test / executable partitions support (tree, etc.)
// TODO: add classes / structs and functions module interface // TODO: add classes / structs and functions module interface
class GlobalInfo { class GlobalInfo {
friend class NamespaceVisitor; friend class NamespaceVisitor;
@ -300,6 +300,29 @@ public:
return &typeclass_graph_; return &typeclass_graph_;
} }
// cache ??
std::vector<utils::IdType> GetAnnotatedTypeTypeclasses(interpreter::tokens::AnnotatedType* node) {
std::unordered_set<utils::IdType> typeclasses;
for (auto& typeclass : node->typeclasses) {
utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_;
std::vector<utils::IdType> dependencies = typeclass_graph_.GetTypeclassDependencies(graph_id);
for (auto& dependency : dependencies) {
typeclasses.insert(dependency);
}
typeclasses.insert(graph_id);
}
std::vector<utils::IdType> collected_typeclasses;
collected_typeclasses.reserve(typeclasses.size());
for (auto& typeclass : typeclasses) {
collected_typeclasses.push_back(typeclass);
}
return collected_typeclasses;
}
std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass); std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass);
private: private:

View file

@ -3,6 +3,7 @@
#include <ostream> #include <ostream>
// for clangd // for clangd
#include "error_handling.hpp"
#include "visitor.hpp" #include "visitor.hpp"
#include "global_info.hpp" #include "global_info.hpp"
@ -14,6 +15,13 @@ public:
explicit LinkSymbolsVisitor(info::GlobalInfo& global_info) explicit LinkSymbolsVisitor(info::GlobalInfo& global_info)
: namespace_visitor_(global_info.CreateVisitor()) {} : namespace_visitor_(global_info.CreateVisitor()) {}
void VisitSourceFile(SourceFile* source_file) override {
Visitor::Visit(source_file);
if (!namespace_visitor_.GetTypeclassGraph()->CalculateGraph()) {
error_handling::HandleInternalError("Can't calculate typeclass graph", "LinkSymbolsVisitor.VisitSourceFile");
}
}
private: private:
// Sources ----------------- // Sources -----------------

View file

@ -3,13 +3,11 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
// for clangd // for clangd
#include "error_handling.hpp"
#include "global_info.hpp"
#include "utils.hpp" #include "utils.hpp"
#include "interpreter_tree.hpp" #include "interpreter_tree.hpp"
#include "definitions.hpp"
namespace info { namespace info {
@ -21,23 +19,17 @@ public:
std::optional<interpreter::tokens::FunctionDefinitionStatement*> definition; std::optional<interpreter::tokens::FunctionDefinitionStatement*> definition;
}; };
struct ParametrizedTypeclass {
std::string typeclass;
// TODO: parameters
};
struct TypeclassVertex { struct TypeclassVertex {
std::string name; std::string name;
interpreter::tokens::TypeclassDefinitionStatement* definition = nullptr; interpreter::tokens::TypeclassDefinitionStatement* definition = nullptr;
std::unordered_map<std::string, FunctionInfo> functions; std::unordered_map<std::string, FunctionInfo> functions;
std::vector<ParametrizedTypeclass> dependencies; std::unordered_set<std::string> dependencies; // TODO: parameters
// TODO: parameters
}; };
std::optional<utils::IdType> AddTypeclass( // move parameters ?? std::optional<utils::IdType> AddTypeclass( // move parameters ??
const std::string& name, const std::string& name,
interpreter::tokens::TypeclassDefinitionStatement* definition, interpreter::tokens::TypeclassDefinitionStatement* definition,
const std::vector<ParametrizedTypeclass>& 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) {
for (auto& method : function_declarations) { for (auto& method : function_declarations) {
@ -52,7 +44,10 @@ public:
TypeclassVertex& typeclass = typeclasses_.back(); TypeclassVertex& typeclass = typeclasses_.back();
typeclass.name = name; typeclass.name = name;
typeclass.definition = definition; typeclass.definition = definition;
typeclass.dependencies = dependencies;
for (auto& dependency : dependencies) {
typeclass.dependencies.insert(dependency);
}
for (auto& method : function_declarations) { for (auto& method : function_declarations) {
FunctionInfo function_info; FunctionInfo function_info;
@ -84,6 +79,18 @@ public:
return typeclasses_.at(id); return typeclasses_.at(id);
} }
// cache ??
const 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;
}
bool IsCalculated() { bool IsCalculated() {
return is_calculated_; return is_calculated_;
} }
@ -96,15 +103,15 @@ public:
std::vector<std::vector<size_t>> edges(typeclasses_.size()); std::vector<std::vector<size_t>> edges(typeclasses_.size());
for (size_t i = 0; i < typeclasses_.size(); ++i) { for (size_t i = 0; i < typeclasses_.size(); ++i) {
edges[i].resize(typeclasses_[i].dependencies.size()); edges[i].reserve(typeclasses_[i].dependencies.size());
for (size_t j = 0; j < edges[i].size(); ++j) { for (auto& dependency :typeclasses_[i].dependencies) {
auto dependency_iter = name_to_typeclass_.find(typeclasses_[i].dependencies[j].typeclass); auto dependency_iter = name_to_typeclass_.find(dependency);
if (dependency_iter == name_to_typeclass_.end()) { if (dependency_iter == name_to_typeclass_.end()) {
return false; return false;
} }
edges[i][j] = dependency_iter->second; edges[i].push_back(dependency_iter->second);
} }
} }
@ -113,7 +120,7 @@ public:
for (auto& id : sorted_verticles) { for (auto& id : sorted_verticles) {
for (auto& dependency : typeclasses_[id].dependencies) { for (auto& dependency : typeclasses_[id].dependencies) {
for (auto& method : typeclasses_[name_to_typeclass_[dependency.typeclass]].functions) { for (auto& method : typeclasses_[name_to_typeclass_[dependency]].functions) {
auto function_iter = typeclasses_[id].functions.find(method.first); auto function_iter = typeclasses_[id].functions.find(method.first);
if (function_iter == typeclasses_[id].functions.end()) { if (function_iter == typeclasses_[id].functions.end()) {
typeclasses_[id].functions[method.first] = method.second; typeclasses_[id].functions[method.first] = method.second;
@ -123,6 +130,9 @@ public:
} }
} }
} }
for (auto& inherited_dependency : typeclasses_[name_to_typeclass_[dependency]].dependencies) {
typeclasses_[id].dependencies.insert(inherited_dependency);
}
} }
} }

View file

@ -1,6 +1,7 @@
#include <iostream> #include <iostream>
// for clangd // for clangd
#include "../include/error_handling.hpp"
#include "../include/find_symbols_visitor.hpp" #include "../include/find_symbols_visitor.hpp"
namespace interpreter { namespace interpreter {
@ -44,11 +45,6 @@ void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) {
} }
void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
info::definition::Namespace* current_namespace = namespace_visitor_.GetCurrentNamespace();
if (current_namespace->node.has_value() && current_namespace->node.value()->link_typeclass_id_.has_value()) {
error_handling::HandleTypecheckError("Can't declare typeclass methods not as requirements", node->base);
}
info::definition::FunctionDeclaration info; info::definition::FunctionDeclaration info;
info.parameters.resize(node->parameters.size()); info.parameters.resize(node->parameters.size());
@ -131,7 +127,7 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
auto definition = node->definition.get(); auto definition = node->definition.get();
std::string& type_name = definition->type.get()->type; std::string& typeclass_name = definition->type.get()->type;
info.parameters.resize(definition->parameters.size()); info.parameters.resize(definition->parameters.size());
for (size_t i = 0; i < definition->parameters.size(); ++i) { for (size_t i = 0; i < definition->parameters.size(); ++i) {
@ -141,7 +137,7 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
} }
for (size_t i = 0; i < node->requirements.size(); ++i) { for (size_t i = 0; i < node->requirements.size(); ++i) {
namespace_visitor_.AddEnterNamespace(type_name, node->requirements[i].first, std::nullopt, node->base); namespace_visitor_.AddEnterNamespace(typeclass_name, node->requirements[i].first, std::nullopt, node->base);
Visit(node->requirements[i].second.get()); Visit(node->requirements[i].second.get());
namespace_visitor_.ExitNamespace(); namespace_visitor_.ExitNamespace();
} }
@ -149,7 +145,7 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
info.node = node; info.node = node;
info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId(); info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId();
node->typeclass_id_ = namespace_visitor_.AddTypeclass(type_name, std::move(info), node->base); node->typeclass_id_ = namespace_visitor_.AddTypeclass(typeclass_name, std::move(info), node->base);
} }
void FindSymbolsVisitor::Visit(PartitionStatement* node) { void FindSymbolsVisitor::Visit(PartitionStatement* node) {
@ -168,6 +164,8 @@ void FindSymbolsVisitor::Visit(AnyAnnotatedType* node) {
info.typeclass_nodes[i] = node->typeclasses[i].get(); info.typeclass_nodes[i] = node->typeclasses[i].get();
} }
info.node = node;
current_info_ = std::move(info); current_info_ = std::move(info);
} }

View file

@ -22,7 +22,7 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name,
std::optional<interpreter::tokens::Namespace*> node, std::optional<interpreter::tokens::Namespace*> node,
const interpreter::tokens::BaseNode& base_node) { const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(name).has_value()) { if (type::ToInternalType(name).has_value()) {
error_handling::HandleTypecheckError("Can't define basic type namespace", base_node); error_handling::HandleNamesError("Can't define basic type namespace", base_node);
} }
auto current_namespaces = ChooseNamespaces(modifier, namespace_stack_.back()); auto current_namespaces = ChooseNamespaces(modifier, namespace_stack_.back());
@ -36,12 +36,16 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name,
global_info_.namespaces_.emplace_back(); global_info_.namespaces_.emplace_back();
global_info_.namespaces_.back().modifier = modifier; global_info_.namespaces_.back().modifier = modifier;
global_info_.namespaces_.back().node = node;
} else { } else {
id = namespace_iter->second; id = namespace_iter->second;
} }
definition::Namespace* namespace_info = &global_info_.namespaces_[id]; definition::Namespace* namespace_info = &global_info_.namespaces_[id];
if (!namespace_info->any_node.has_value()) { // ??
namespace_info->any_node = node;
}
namespace_info->parent_namespace = namespace_stack_.back(); namespace_info->parent_namespace = namespace_stack_.back();
namespace_info->type_name = name; namespace_info->type_name = name;
@ -99,12 +103,12 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration(
} else { } else {
id = function_id_iter->second; id = function_id_iter->second;
if (global_info_.functions_[id].argument_count != function_declaration_info.argument_types.size()) { if (global_info_.functions_[id].argument_count != function_declaration_info.argument_types.size()) {
error_handling::HandleTypecheckError("Function declaration: not same argument count in function definition and declaration", base_node); error_handling::HandleNamesError("Function declaration: not same argument count in function definition and declaration", base_node);
} }
} }
if (global_info_.functions_[id].declaration.has_value()) { if (global_info_.functions_[id].declaration.has_value()) {
error_handling::HandleTypecheckError("Second function declaration", base_node); error_handling::HandleNamesError("Second function declaration", base_node);
} }
global_info_.functions_[id].declaration = std::move(function_declaration_info); global_info_.functions_[id].declaration = std::move(function_declaration_info);
@ -126,12 +130,12 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(
} else { } else {
id = function_id_iter->second; id = function_id_iter->second;
if (global_info_.functions_[id].argument_count != function_definition_info.argument_names.size() + 1) { if (global_info_.functions_[id].argument_count != function_definition_info.argument_names.size() + 1) {
error_handling::HandleTypecheckError("Function definition: not same argument count in function definition and declaration", base_node); error_handling::HandleNamesError("Function definition: not same argument count in function definition and declaration", base_node);
} }
} }
if (global_info_.functions_[id].definition.has_value()) { if (global_info_.functions_[id].definition.has_value()) {
error_handling::HandleTypecheckError("Second function definition", base_node); error_handling::HandleNamesError("Second function definition", base_node);
} }
global_info_.functions_[id].definition = std::move(function_definition_info); global_info_.functions_[id].definition = std::move(function_definition_info);
@ -144,7 +148,7 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
definition::Type&& type_info, definition::Type&& type_info,
const interpreter::tokens::BaseNode& base_node) { const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(type).has_value()) { if (type::ToInternalType(type).has_value()) {
error_handling::HandleTypecheckError("Can't redefine basic type", base_node); error_handling::HandleNamesError("Can't redefine basic type", base_node);
} }
utils::IdType id = 0; utils::IdType id = 0;
@ -156,8 +160,8 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
global_info_.namespaces_[namespace_stack_.back()].types[type] = id; global_info_.namespaces_[namespace_stack_.back()].types[type] = id;
global_info_.types_.push_back(std::move(type_info)); global_info_.types_.push_back(std::move(type_info));
} else { } else {
error_handling::HandleTypecheckError("More then one type with the same name in namespace", base_node); error_handling::HandleNamesError("More then one type with the same name in namespace", base_node);
} // TODO: typecheck error?? }
definition::Type& moved_type_info = global_info_.types_.back(); definition::Type& moved_type_info = global_info_.types_.back();
@ -207,12 +211,11 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& a
definition::AbstractType&& abstract_type_info, definition::AbstractType&& abstract_type_info,
const interpreter::tokens::BaseNode& base_node) { const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(abstract_type).has_value()) { if (type::ToInternalType(abstract_type).has_value()) {
error_handling::HandleTypecheckError("Can't redefine basic type as abstract type", base_node); error_handling::HandleNamesError("Can't redefine basic type as abstract type", base_node);
} }
if (FindAbstractType(abstract_type).has_value()) { if (FindAbstractType(abstract_type).has_value()) {
error_handling::HandleTypecheckError("More then one abstract type with the same name in namespace", error_handling::HandleNamesError("More then one abstract type with the same name in namespace", base_node);
base_node);
} }
utils::IdType id = global_info_.abstract_types_.size(); utils::IdType id = global_info_.abstract_types_.size();
@ -227,23 +230,17 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& type
definition::Typeclass&& typeclass_info, definition::Typeclass&& typeclass_info,
const interpreter::tokens::BaseNode& base_node) { const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(typeclass).has_value()) { if (type::ToInternalType(typeclass).has_value()) {
error_handling::HandleTypecheckError("Can't redefine basic type as typeclass", base_node); error_handling::HandleNamesError("Can't redefine basic type as typeclass", base_node);
} }
if (FindTypeclass(typeclass).has_value()) { if (FindTypeclass(typeclass).has_value()) {
error_handling::HandleTypecheckError("More then one typeclass with the same name in namespace", base_node); error_handling::HandleNamesError("More then one typeclass with the same name", base_node);
} }
utils::IdType id = global_info_.typeclasses_.size(); utils::IdType id = global_info_.typeclasses_.size();
global_info_.name_to_typeclass_[typeclass] = id; global_info_.name_to_typeclass_[typeclass] = id;
global_info_.typeclasses_.push_back(std::move(typeclass_info)); global_info_.typeclasses_.push_back(std::move(typeclass_info));
definition::Typeclass& moved_typeclass_info = global_info_.typeclasses_.back();
// global_info_.typeclass_graph_.AddTypeclassByNode(moved_typeclass_info.node); // TODO
error_handling::HandleInternalError("Typeclasses are not implemented properly yet",
"GlobalInfo.NamespaceVisitor.AddTypeclass");
return id; return id;
} }
@ -251,13 +248,13 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& co
definition::Constructor&& constructor_info, definition::Constructor&& constructor_info,
const interpreter::tokens::BaseNode& base_node) { const interpreter::tokens::BaseNode& base_node) {
if (type::ToInternalType(constructor).has_value()) { if (type::ToInternalType(constructor).has_value()) {
error_handling::HandleTypecheckError("Can't redefine basic type as constructor", base_node); error_handling::HandleNamesError("Can't redefine basic type as constructor", base_node);
} }
auto constructor_id_iter = global_info_.namespaces_[namespace_stack_.back()].constructors.find(constructor); auto constructor_id_iter = global_info_.namespaces_[namespace_stack_.back()].constructors.find(constructor);
if (constructor_id_iter != global_info_.namespaces_[namespace_stack_.back()].constructors.end()) { if (constructor_id_iter != global_info_.namespaces_[namespace_stack_.back()].constructors.end()) {
error_handling::HandleTypecheckError("More then one constructor with the same name in namespace", base_node); error_handling::HandleNamesError("More then one constructor with the same name in namespace", base_node);
} }
utils::IdType id = global_info_.constructors_.size(); utils::IdType id = global_info_.constructors_.size();
@ -316,8 +313,6 @@ std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindMethodId(
const std::string& type, const std::string& type,
const std::string& name, const std::string& name,
utils::IsConstModifier modifier) { utils::IsConstModifier modifier) {
// TODO: remove overhead
return GlobalInfo::NamespaceVisitor::FindSomething<utils::IdType>(path, return GlobalInfo::NamespaceVisitor::FindSomething<utils::IdType>(path,
[type, name, modifier, this] (utils::IdType current_namespace) -> std::optional<utils::IdType> { [type, name, modifier, this] (utils::IdType current_namespace) -> std::optional<utils::IdType> {
@ -471,13 +466,12 @@ 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;
std::vector<TypeclassGraph::ParametrizedTypeclass> 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;
for (auto& dependency_node : typeclass_info->node->definition->type->typeclasses) { for (auto& dependency_node : typeclass_info->node->definition->type->typeclasses) {
TypeclassGraph::ParametrizedTypeclass dependency; std::string dependency = dependency_node->typeclass;
dependency.typeclass = 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"); "TypeclassGraph.AddTypeclassByNode");
@ -494,23 +488,21 @@ std::optional<utils::IdType> GlobalInfo::AddTypeclassToGraph(utils::IdType typec
} }
auto const_namespace_iter = parent_namespace->const_namespaces.find(name); auto const_namespace_iter = parent_namespace->const_namespaces.find(name);
if (namespace_iter != parent_namespace->const_namespaces.end()) { if (const_namespace_iter != parent_namespace->const_namespaces.end()) {
CollectFunctionInfo(namespace_iter->second, CollectFunctionInfo(const_namespace_iter->second,
utils::ClassInternalsModifier::Const, utils::ClassInternalsModifier::Const,
function_declarations, function_declarations,
function_definitions); function_definitions);
} }
auto var_namespace_iter = parent_namespace->var_namespaces.find(name); auto var_namespace_iter = parent_namespace->var_namespaces.find(name);
if (namespace_iter != parent_namespace->var_namespaces.end()) { if (var_namespace_iter != parent_namespace->var_namespaces.end()) {
CollectFunctionInfo(namespace_iter->second, CollectFunctionInfo(var_namespace_iter->second,
utils::ClassInternalsModifier::Var, utils::ClassInternalsModifier::Var,
function_declarations, function_declarations,
function_definitions); function_definitions);
} }
// TODO
return typeclass_graph_.AddTypeclass(name, return typeclass_graph_.AddTypeclass(name,
typeclass_info->node, typeclass_info->node,
dependencies, dependencies,

View file

@ -15,12 +15,12 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindLocalTypeId(node->type); std::optional<utils::IdType> maybe_type = namespace_visitor_.FindLocalTypeId(node->type);
std::optional<utils::IdType> maybe_typeclass; std::optional<utils::IdType> maybe_typeclass;
if (namespace_visitor_.GetCurrentPath().size() == 0) { if (namespace_visitor_.IsInGlobalNamespace()) {
maybe_typeclass = namespace_visitor_.FindTypeclassId(node->type); maybe_typeclass = namespace_visitor_.FindTypeclassId(node->type);
} }
if (maybe_type.has_value() && maybe_typeclass.has_value()) { if (maybe_type.has_value() && maybe_typeclass.has_value()) {
error_handling::HandleTypecheckError("Ambigious namespace name (typeclass or type)", node->base); error_handling::HandleNamesError("Ambigious namespace name (typeclass or type)", node->base);
} }
if (maybe_type.has_value()) { if (maybe_type.has_value()) {
@ -39,21 +39,26 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
// Definitions ----------------- // Definitions -----------------
// TODO: add to typeclass graph, etc. (+ check)
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) {
namespace_visitor_.EnterNamespace(node->definition->type->type, function_requirement.first);
Visitor::Visit(function_requirement.second.get()); Visitor::Visit(function_requirement.second.get());
namespace_visitor_.ExitNamespace();
} }
namespace_visitor_.GetGlobalInfo()->AddTypeclassToGraph(node->typeclass_id_); auto maybe_graph_id = namespace_visitor_.GetGlobalInfo()->AddTypeclassToGraph(node->typeclass_id_);
if (!maybe_graph_id.has_value()) {
error_handling::HandleNamesError("Can't add typeclass to graph", node->base);
}
namespace_visitor_.GetGlobalInfo()->GetTypeclassInfo(node->typeclass_id_).graph_id_ = maybe_graph_id.value();
} }
// Type, typeclass, etc. ----------------- // Type, typeclass, etc. -----------------
// Type // Type
void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check void LinkSymbolsVisitor::Visit(TypeExpression* node) {
std::vector<std::string> path; std::vector<std::string> path;
path.reserve(node->path.size()); path.reserve(node->path.size());
@ -67,11 +72,11 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
// internal type // internal type
if (info::type::ToInternalType(node->type.type).has_value()) { if (info::type::ToInternalType(node->type.type).has_value()) {
if (!node->path.empty()) { if (!node->path.empty()) {
error_handling::HandleTypecheckError("Internal type is not in namespace", node->base); error_handling::HandleNamesError("Internal type is not in namespace", node->base);
} }
if (!node->type.parameters.empty()) { if (!node->type.parameters.empty()) {
error_handling::HandleTypecheckError("Can't parametrize internal type", node->base); error_handling::HandleNamesError("Can't parametrize internal type", node->base);
} }
return; return;
} }
@ -93,7 +98,7 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
utils::IdType constructor_type_id = namespace_visitor_.GetGlobalInfo()->GetConstructorInfo(node->constructor_id_.value()).type_id; 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) { if (node->type_id_.has_value() && node->type_id_.value() != constructor_type_id) {
error_handling::HandleTypecheckError("Contructor and type with same name have different types", node->base); error_handling::HandleNamesError("Contructor and type with same name have different types", node->base);
} }
node->type_id_ = constructor_type_id; node->type_id_ = constructor_type_id;
@ -122,13 +127,17 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
// Typeclass // Typeclass
void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) { // TODO: check void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) {
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclassId(node->typeclass); std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclassId(node->typeclass);
if (maybe_typeclass.has_value()) { if (maybe_typeclass.has_value()) {
node->typeclass_id_ = maybe_typeclass.value(); node->typeclass_id_ = maybe_typeclass.value();
} else { } else {
error_handling::HandleTypecheckError("Typeclass not found", node->base); error_handling::HandleNamesError("Typeclass not found", node->base);
}
if (node->parameters.size() > 0) {
error_handling::HandleNamesError("Parametrized typeclasses not implemented yet", node->base);
} }
} }

View file

@ -32,10 +32,12 @@ void TypeCheckVisitor::Visit(NamespaceSources* node) {
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for class: const and var void TypeCheckVisitor::Visit(Namespace* node) {
if (node->link_typeclass_id_.has_value()) { // TODO: think about typeclass if (node->link_typeclass_id_.has_value()) {
utils::IdType graph_id = namespace_visitor_.GetGlobalInfo()->GetTypeclassInfo(node->link_typeclass_id_.value()).graph_id_;
std::vector<utils::IdType> requirements {node->link_typeclass_id_.value()}; std::vector<utils::IdType> requirements = namespace_visitor_.GetTypeclassGraph()->GetTypeclassDependencies(graph_id);
requirements.push_back(graph_id);
utils::IdType abstract_type = context_manager_.AddValue( utils::IdType abstract_type = context_manager_.AddValue(
info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements), info::type::AbstractType(utils::AbstractTypeModifier::Abstract, node->type, requirements),
ClassInternalsModifierToValueType(node->modifier)); ClassInternalsModifierToValueType(node->modifier));
@ -95,7 +97,6 @@ void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for c
void TypeCheckVisitor::Visit(ImportStatement* node) {} void TypeCheckVisitor::Visit(ImportStatement* node) {}
// TODO // TODO
// + TODO: let bindings for abstract types
void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) { void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) {
error_handling::HandleInternalError("Unimplemented", error_handling::HandleInternalError("Unimplemented",
"TypeCheckVisitor.AliasDefinitionStatement"); "TypeCheckVisitor.AliasDefinitionStatement");
@ -128,12 +129,12 @@ void TypeCheckVisitor::Visit(FunctionDeclaration* node) {
context_manager_.EnterContext(); context_manager_.EnterContext();
for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed?? for (auto& parameter : node->parameters) { // declaration correctness check // TODO: needed??
std::vector<utils::IdType> requirements; std::vector<utils::IdType> requirements =
// TODO: namespace_visitor_.GetGlobalInfo()->GetAnnotatedTypeTypeclasses(parameter.get());
current_type_ = context_manager_.AddValue( current_type_ = context_manager_.AddValue(
info::type::AbstractType(utils::AbstractTypeModifier::Abstract, info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
parameter->type, parameter->type,
requirements), // TODO: typeclasses-requirements requirements),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.DefineLocalType(parameter->type, current_type_); context_manager_.DefineLocalType(parameter->type, current_type_);
} }
@ -161,12 +162,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
info::definition::FunctionDeclaration& declaration = function_info.declaration.value(); info::definition::FunctionDeclaration& declaration = function_info.declaration.value();
for (auto parameter : declaration.parameters) { for (auto parameter : declaration.parameters) {
std::vector<utils::IdType> requirements; std::vector<utils::IdType> requirements =
requirements.reserve(parameter.typeclass_nodes.size()); namespace_visitor_.GetGlobalInfo()->GetAnnotatedTypeTypeclasses(parameter.node);
for (ParametrizedTypeclass* typeclass : parameter.typeclass_nodes) {
requirements.push_back(typeclass->typeclass_id_);
}
// TODO: add recursive typeclasses from typeclass tree
current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract,
parameter.type, parameter.type,
requirements), requirements),
@ -210,13 +207,8 @@ void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
is_in_statement_ = true; is_in_statement_ = true;
std::vector<utils::IdType> requirements; std::vector<utils::IdType> requirements =
requirements.reserve(node->type->typeclasses.size()); namespace_visitor_.GetGlobalInfo()->GetAnnotatedTypeTypeclasses(node->type.get());
for (auto& typeclass : node->type->typeclasses) {
requirements.push_back(typeclass->typeclass_id_);
}
// TODO: add recursive typeclasses from typeclass tree
current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements), current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements),
utils::ValueType::Tmp); utils::ValueType::Tmp);
if (!context_manager_.DefineLocalType(node->type->type, current_type_)) { if (!context_manager_.DefineLocalType(node->type->type, current_type_)) {