mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-05 22:48:42 +00:00
check, that type satisfy typeclass requirements made in type_check_visitor
This commit is contained in:
parent
090f638e45
commit
ce0ca2a5cb
4 changed files with 118 additions and 40 deletions
|
|
@ -267,10 +267,6 @@ public:
|
||||||
std::optional<utils::IdType> FindNamespaceIn(
|
std::optional<utils::IdType> FindNamespaceIn(
|
||||||
utils::IdType current_namespace,
|
utils::IdType current_namespace,
|
||||||
const std::vector<std::string>& path);
|
const std::vector<std::string>& path);
|
||||||
|
|
||||||
std::unordered_map<std::string, utils::IdType>*
|
|
||||||
ChooseNamespaces(utils::ClassInternalsModifier modifier,
|
|
||||||
utils::IdType namespace_id);
|
|
||||||
private:
|
private:
|
||||||
GlobalInfo& global_info_;
|
GlobalInfo& global_info_;
|
||||||
|
|
||||||
|
|
@ -339,33 +335,21 @@ public:
|
||||||
return &typeclass_graph_;
|
return &typeclass_graph_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache ??
|
std::unordered_set<utils::IdType>
|
||||||
std::unordered_set<utils::IdType> GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node) {
|
GetAnnotatedTypeTypeclassesSet(interpreter::tokens::AnnotatedType* node);
|
||||||
std::unordered_set<utils::IdType> typeclasses;
|
|
||||||
|
|
||||||
for (auto& typeclass : node->typeclasses) {
|
std::vector<utils::IdType>
|
||||||
utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_;
|
GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node);
|
||||||
|
|
||||||
std::vector<utils::IdType> dependencies = typeclass_graph_.GetTypeclassDependencies(graph_id);
|
std::unordered_map<std::string, utils::ClassInternalsModifier>
|
||||||
for (auto& dependency : dependencies) {
|
GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node);
|
||||||
typeclasses.insert(dependency);
|
|
||||||
}
|
|
||||||
|
|
||||||
typeclasses.insert(graph_id);
|
std::vector<std::pair<std::string, utils::ClassInternalsModifier>>
|
||||||
}
|
GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node);
|
||||||
return typeclasses;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<utils::IdType> GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node) {
|
std::unordered_map<std::string, utils::IdType>* ChooseNamespaces(
|
||||||
std::unordered_set<utils::IdType> typeclasses_set = GetAnnotatedTypeTypeclassesSet(node);
|
utils::ClassInternalsModifier modifier,
|
||||||
|
definition::Namespace* current_namespace);
|
||||||
std::vector<utils::IdType> typeclasses_vector;
|
|
||||||
typeclasses_vector.reserve(typeclasses_vector.size());
|
|
||||||
for (auto& typeclass : typeclasses_set) {
|
|
||||||
typeclasses_vector.push_back(typeclass);
|
|
||||||
}
|
|
||||||
return typeclasses_vector;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass);
|
std::optional<utils::IdType> AddTypeclassToGraph(utils::IdType typeclass);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace info {
|
||||||
class TypeclassGraph {
|
class TypeclassGraph {
|
||||||
public:
|
public:
|
||||||
struct FunctionInfo {
|
struct FunctionInfo {
|
||||||
utils::ClassInternalsModifier modifier;
|
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;
|
||||||
};
|
};
|
||||||
|
|
@ -100,7 +100,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache ??
|
// cache ??
|
||||||
const std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id) {
|
std::vector<utils::IdType> GetTypeclassDependencies(utils::IdType id) {
|
||||||
std::vector<utils::IdType> dependencies;
|
std::vector<utils::IdType> dependencies;
|
||||||
|
|
||||||
dependencies.reserve(typeclasses_.at(id).dependencies.size());
|
dependencies.reserve(typeclasses_.at(id).dependencies.size());
|
||||||
|
|
@ -111,6 +111,18 @@ public:
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cache ??
|
||||||
|
std::vector<std::pair<std::string, utils::ClassInternalsModifier>> GetTypeclassFunctions(utils::IdType id) {
|
||||||
|
std::vector<std::pair<std::string, utils::ClassInternalsModifier>> functions;
|
||||||
|
|
||||||
|
functions.reserve(typeclasses_.at(id).functions.size());
|
||||||
|
for (auto& function : typeclasses_[id].functions) {
|
||||||
|
functions.push_back({function.first, function.second.modifier});
|
||||||
|
}
|
||||||
|
|
||||||
|
return functions;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsCalculated() {
|
bool IsCalculated() {
|
||||||
return is_calculated_;
|
return is_calculated_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name,
|
||||||
error_handling::HandleNamesError("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 =
|
||||||
|
global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[namespace_stack_.back()]);
|
||||||
|
|
||||||
utils::IdType id = 0;
|
utils::IdType id = 0;
|
||||||
|
|
||||||
|
|
@ -57,7 +58,8 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name,
|
||||||
void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name,
|
void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name,
|
||||||
utils::ClassInternalsModifier modifier) {
|
utils::ClassInternalsModifier modifier) {
|
||||||
for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) {
|
for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) {
|
||||||
auto current_namespaces = ChooseNamespaces(modifier, i);
|
auto current_namespaces =
|
||||||
|
global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[i]);
|
||||||
auto namespace_iter = current_namespaces->find(name);
|
auto namespace_iter = current_namespaces->find(name);
|
||||||
if (namespace_iter != current_namespaces->end()) {
|
if (namespace_iter != current_namespaces->end()) {
|
||||||
namespace_stack_.push_back(namespace_iter->second);
|
namespace_stack_.push_back(namespace_iter->second);
|
||||||
|
|
@ -440,27 +442,88 @@ std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindNamespaceIn(
|
||||||
return next_namespace;
|
return next_namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
// cache ??
|
||||||
|
std::unordered_set<utils::IdType>
|
||||||
|
GlobalInfo::GetAnnotatedTypeTypeclassesSet(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);
|
||||||
|
}
|
||||||
|
return typeclasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<utils::IdType>
|
||||||
|
GlobalInfo::GetAnnotatedTypeTypeclassesVector(interpreter::tokens::AnnotatedType* node) {
|
||||||
|
|
||||||
|
std::unordered_set<utils::IdType> typeclasses_set = GetAnnotatedTypeTypeclassesSet(node);
|
||||||
|
|
||||||
|
std::vector<utils::IdType> typeclasses_vector;
|
||||||
|
typeclasses_vector.reserve(typeclasses_vector.size());
|
||||||
|
for (auto& typeclass : typeclasses_set) {
|
||||||
|
typeclasses_vector.push_back(typeclass);
|
||||||
|
}
|
||||||
|
return typeclasses_vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, utils::ClassInternalsModifier>
|
||||||
|
GlobalInfo::GetAnnotatedTypeFunctionsMap(interpreter::tokens::AnnotatedType* node) {
|
||||||
|
|
||||||
|
std::unordered_map<std::string, utils::ClassInternalsModifier> functions;
|
||||||
|
|
||||||
|
for (auto& typeclass : node->typeclasses) {
|
||||||
|
utils::IdType graph_id = typeclasses_[typeclass->typeclass_id_].graph_id_;
|
||||||
|
|
||||||
|
auto requirements = typeclass_graph_.GetTypeclassFunctions(graph_id);
|
||||||
|
for (auto& requirement : requirements) {
|
||||||
|
functions[requirement.first] = requirement.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, utils::ClassInternalsModifier>>
|
||||||
|
GlobalInfo::GetAnnotatedTypeFunctionsVector(interpreter::tokens::AnnotatedType* node) {
|
||||||
|
|
||||||
|
std::unordered_map<std::string, utils::ClassInternalsModifier> functions_set = GetAnnotatedTypeFunctionsMap(node);
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, utils::ClassInternalsModifier>> functions_vector;
|
||||||
|
functions_vector.reserve(functions_vector.size());
|
||||||
|
for (auto& typeclass : functions_set) {
|
||||||
|
functions_vector.push_back(typeclass);
|
||||||
|
}
|
||||||
|
return functions_vector;
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, utils::IdType>*
|
std::unordered_map<std::string, utils::IdType>*
|
||||||
GlobalInfo::NamespaceVisitor::ChooseNamespaces(utils::ClassInternalsModifier modifier,
|
GlobalInfo::ChooseNamespaces(utils::ClassInternalsModifier modifier,
|
||||||
utils::IdType namespace_id) {
|
definition::Namespace* current_namespace) {
|
||||||
std::unordered_map<std::string, utils::IdType>* current_namespaces = nullptr;
|
std::unordered_map<std::string, utils::IdType>* current_namespaces = nullptr;
|
||||||
switch (modifier) {
|
switch (modifier) {
|
||||||
case utils::ClassInternalsModifier::Const:
|
case utils::ClassInternalsModifier::Const:
|
||||||
current_namespaces = &global_info_.namespaces_[namespace_id].const_namespaces;
|
current_namespaces = ¤t_namespace->const_namespaces;
|
||||||
break;
|
break;
|
||||||
case utils::ClassInternalsModifier::Var:
|
case utils::ClassInternalsModifier::Var:
|
||||||
current_namespaces = &global_info_.namespaces_[namespace_id].var_namespaces;
|
current_namespaces = ¤t_namespace->var_namespaces;
|
||||||
break;
|
break;
|
||||||
case utils::ClassInternalsModifier::Static:
|
case utils::ClassInternalsModifier::Static:
|
||||||
current_namespaces = &global_info_.namespaces_[namespace_id].namespaces;
|
current_namespaces = ¤t_namespace->namespaces;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_namespaces;
|
return current_namespaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
std::optional<utils::IdType> GlobalInfo::AddTypeclassToGraph(utils::IdType typeclass) {
|
std::optional<utils::IdType> GlobalInfo::AddTypeclassToGraph(utils::IdType typeclass) {
|
||||||
definition::Typeclass* typeclass_info = &GetTypeclassInfo(typeclass);
|
definition::Typeclass* typeclass_info = &GetTypeclassInfo(typeclass);
|
||||||
definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace);
|
definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace);
|
||||||
|
|
|
||||||
|
|
@ -231,8 +231,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
||||||
|
|
||||||
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
||||||
Visitor::Visit(declaration->type->types[i]);
|
Visitor::Visit(declaration->type->types[i]);
|
||||||
current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); // TODO: var function arguments??
|
current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); // TODO: Var??
|
||||||
if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) { // TODO: watch to reference
|
if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) {
|
||||||
error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base);
|
error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -255,6 +255,25 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
|
void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
|
||||||
is_in_statement_ = true;
|
is_in_statement_ = true;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, utils::ClassInternalsModifier> required_functions =
|
||||||
|
global_info_.GetAnnotatedTypeFunctionsMap(node->definition->type.get());
|
||||||
|
|
||||||
|
std::string& type_name = node->definition->type->type;
|
||||||
|
|
||||||
|
for (auto& function : required_functions) { // TODO: optimize
|
||||||
|
std::unordered_map<std::string, utils::IdType>* current_namespaces =
|
||||||
|
global_info_.ChooseNamespaces(function.second, namespace_visitor_.GetCurrentNamespace());
|
||||||
|
|
||||||
|
auto& type_functions = global_info_.GetNamespaceInfo((*current_namespaces)[type_name]).functions;
|
||||||
|
|
||||||
|
auto function_iter = type_functions.find(function.first);
|
||||||
|
|
||||||
|
if (function_iter == type_functions.end() || !global_info_.GetFunctionInfo(function_iter->second).definition.has_value()) {
|
||||||
|
error_handling::HandleTypecheckError("Type is not satisfy typeclass requirements: " + function.first + " is not defined", node->base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp);
|
current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp);
|
||||||
is_in_statement_ = false;
|
is_in_statement_ = false;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue