diff --git a/include/definitions.hpp b/include/definitions.hpp index 9d3de5b..2f09f23 100644 --- a/include/definitions.hpp +++ b/include/definitions.hpp @@ -44,8 +44,9 @@ struct AnyType { Parameter type; std::vector parameters; interpreter::tokens::AnyType* value; + utils::ClassModifier modifier; - Namespace* parent_namespace = nullptr; + utils::IdType parent_namespace; }; struct Type { @@ -92,11 +93,11 @@ struct Namespace { std::unordered_map types; std::unordered_map functions; std::unordered_map constructors; - std::unordered_map namespaces; - std::unordered_map var_namespaces; - std::unordered_map const_namespaces; + std::unordered_map namespaces; + std::unordered_map var_namespaces; + std::unordered_map const_namespaces; - Namespace* parent_namespace = nullptr; + utils::IdType parent_namespace; std::optional modifier; // modifier => variable namespace std::string type_name; diff --git a/include/global_info.hpp b/include/global_info.hpp index 27a8b93..d61cfdd 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -17,6 +17,10 @@ namespace info { class GlobalInfo { friend class NamespaceVisitor; public: + GlobalInfo() { + namespaces_.emplace_back(); // global namespace + } + struct PartitionInfo { std::vector path; std::string name; @@ -39,7 +43,8 @@ public: std::optional modifier, const interpreter::tokens::BaseNode& base_node); - void EnterNamespace(const std::string& name); + void EnterNamespace(const std::string& name, + std::optional modifier); void ExitNamespace(); @@ -70,7 +75,7 @@ public: utils::IdType AddPartition(const std::vector& path, // including name interpreter::tokens::PartitionStatement* node); - std::optional FindNamespace(const std::optional>& path); + std::optional FindNamespace(const std::optional>& path); std::optional FindFunction(const std::optional>& path, const std::string& name); @@ -104,25 +109,25 @@ public: return current_path_; } - definition::Namespace* GetCurrentNamespace() { + utils::IdType GetCurrentNamespace() { return namespace_stack_.back(); } private: NamespaceVisitor(GlobalInfo& global_info) : global_info_(global_info), - namespace_stack_({&global_info.global_namespace_}) {} + namespace_stack_ {global_info.GlobalNamespaceId} {} template std::optional FindSomething( const std::optional>& path, - std::function(definition::Namespace*)> search_func); + std::function(utils::IdType)> search_func); - std::optional FindNamespaceIn( - definition::Namespace* current_namespace, + std::optional FindNamespaceIn( + utils::IdType current_namespace, const std::vector& path); private: GlobalInfo& global_info_; - std::vector namespace_stack_; + std::vector namespace_stack_; std::vector current_path_; }; @@ -131,7 +136,7 @@ public: } // remember about vector realloc - const definition::Function& GetFunctionInfo(utils::IdType id) { + definition::Function& GetFunctionInfo(utils::IdType id) { return functions_.at(id); } @@ -144,22 +149,27 @@ public: } // remember about vector realloc - const definition::Type& GetAnyTypeInfo(utils::IdType id) { + definition::Type& GetAnyTypeInfo(utils::IdType id) { return types_.at(id); } // remember about vector realloc - const definition::Typeclass& GetTypeclassInfo(utils::IdType id) { + definition::Typeclass& GetTypeclassInfo(utils::IdType id) { return typeclasses_.at(id); } // remember about vector realloc - const definition::Constructor& GetConstructorInfo(utils::IdType id) { + definition::Constructor& GetConstructorInfo(utils::IdType id) { return constructors_.at(id); } // remember about vector realloc - const PartitionInfo& GetPartitionInfo(utils::IdType id) { + definition::Namespace& GetNamespaceInfo(utils::IdType id) { + return namespaces_.at(id); + } + + // remember about vector realloc + PartitionInfo& GetPartitionInfo(utils::IdType id) { return partitions_.at(id); } @@ -181,6 +191,7 @@ public: } private: + const utils::IdType GlobalNamespaceId = 0; std::vector functions_; std::vector types_; @@ -188,13 +199,14 @@ private: std::vector typeclasses_; std::vector constructors_; + std::vector namespaces_; + std::unordered_map name_to_typeclass_; std::unordered_map name_to_abstract_type_; std::vector partitions_; utils::Trie partitions_trie_; - definition::Namespace global_namespace_; std::vector imports_; std::unordered_map usages_; }; diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index ac5ce44..dbdd483 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -7,6 +7,7 @@ #include "utils.hpp" #include "visitor.hpp" #include "global_info.hpp" +#include // TODO: class fields and constructors can't be accessed not from associated namespace @@ -139,6 +140,7 @@ private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; info::ContextManager& context_manager_; + std::unordered_set type_namespaces_; utils::IdType current_type_; std::optional returned_type_; std::optional is_const_definition_; diff --git a/include/types.hpp b/include/types.hpp index 40092e2..657dc88 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -32,7 +32,8 @@ public: bool operator<(const AbstractType& type) const; bool operator>(const AbstractType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; private: utils::AbstractTypeModifier modifier_; @@ -45,6 +46,7 @@ public: DefinedType() = default; DefinedType(utils::IdType type_id, utils::IdType type, + utils::ClassModifier class_modifier, TypeManager* type_manager) : type_id_(type_id), type_(type), type_manager_(type_manager) {} @@ -53,7 +55,8 @@ public: bool operator<(const DefinedType& type) const; bool operator>(const DefinedType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; utils::IdType GetTypeId() const { return type_id_; @@ -63,9 +66,14 @@ public: return type_; } + utils::ClassModifier GetClassModifier() const { + return class_modifier_; + } + private: utils::IdType type_id_; // in defined types utils::IdType type_; // in types manager, created using context types (if specific type) + utils::ClassModifier class_modifier_; TypeManager* type_manager_ = nullptr; }; @@ -122,7 +130,8 @@ public: bool operator<(const TupleType& type) const; bool operator>(const TupleType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; const std::vector, utils::IdType>>& GetFields() const { return fields_; @@ -147,7 +156,8 @@ public: bool operator<(const VariantType& type) const; bool operator>(const VariantType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; const std::vector& GetConstructors() const { return constructors_; @@ -175,7 +185,8 @@ public: bool operator<(const OptionalType& type) const; bool operator>(const OptionalType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; private: utils::IdType type_; @@ -195,7 +206,8 @@ public: bool operator<(const ReferenceToType& type) const; bool operator>(const ReferenceToType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; private: std::vector references_; @@ -218,7 +230,8 @@ public: bool operator<(const FunctionType& type) const; bool operator>(const FunctionType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; private: std::vector argument_types_; @@ -239,7 +252,8 @@ public: bool operator<(const ArrayType& type) const; bool operator>(const ArrayType& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; utils::IdType GetElementsType() { return elements_type_; @@ -263,7 +277,8 @@ public: bool operator<(const Type& type) const; // TODO: rule exceptions bool operator>(const Type& type) const; - std::optional GetFieldType(const std::string& name) const; + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; std::string GetTypeName() const; diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 3d8014c..179dfd1 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -271,7 +271,7 @@ void BuildVisitor::Visit(TypeclassDefinitionStatement* node) { for (size_t i = 0; i + 1 < child_count; ++i) { current_node_ = parse_node.NthNamedChild(i + 1); - if (parse_node.PreviousSibling().GetValue() != "var") { + if (current_node_.PreviousSibling().GetValue() != "var") { node->function_requirements.push_back(std::make_unique()); Visit(node->function_requirements.back().get()); } else { diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index f58bca6..537b0b2 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -9,7 +9,9 @@ namespace interpreter { void FindSymbolsVisitor::Visit(Namespace* node) { namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node->base); + Visitor::Visit(&node->scope); + namespace_visitor_.ExitNamespace(); } @@ -118,6 +120,7 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { any_type_info.value = &node->value; any_type_info.parent_namespace = namespace_visitor_.GetCurrentNamespace(); + any_type_info.modifier = node->modifier; std::string type = any_type_info.type.type; @@ -160,14 +163,14 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { current_info_.reset(); } - info.function_requirements.reserve(node->function_requirements.size()); + info.function_requirements.resize(node->function_requirements.size()); for (size_t i = 0; i < node->function_requirements.size(); ++i) { Visit(node->function_requirements[i].get()); info.function_requirements[i] = std::move(std::any_cast(current_info_)); current_info_.reset(); } - info.method_requirements.reserve(node->method_requirements.size()); + info.method_requirements.resize(node->method_requirements.size()); for (size_t i = 0; i < node->method_requirements.size(); ++i) { Visit(node->method_requirements[i].get()); info.method_requirements[i] = std::move(std::any_cast(current_info_)); diff --git a/src/global_info.cpp b/src/global_info.cpp index 8f5054a..361c6e5 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -24,44 +24,71 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, error_handling::HandleTypecheckError("Can't define basic type namespace", base_node); } - definition::Namespace* namespace_info = nullptr; + size_t id = global_info_.namespaces_.size(); + global_info_.namespaces_.emplace_back(); + definition::Namespace* namespace_info = &global_info_.namespaces_.back(); + if (modifier.has_value()) { if (modifier.value() == utils::IsConstModifier::Const) { - namespace_info = &namespace_stack_.back()->const_namespaces[name]; + global_info_.namespaces_[namespace_stack_.back()].const_namespaces[name] = id; } else { - namespace_info = &namespace_stack_.back()->var_namespaces[name]; + global_info_.namespaces_[namespace_stack_.back()].var_namespaces[name] = id; } - namespace_stack_.push_back(namespace_info); namespace_info->modifier = modifier; } else { - namespace_info = &namespace_stack_.back()->namespaces[name]; - namespace_stack_.push_back(namespace_info); + global_info_.namespaces_[namespace_stack_.back()].namespaces[name] = id; } namespace_info->parent_namespace = namespace_stack_.back(); namespace_info->type_name = name; + + namespace_stack_.push_back(id); current_path_.push_back(name); } -void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name) { - for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { - auto namespace_iter = namespace_stack_[i]->namespaces.find(name); - if (namespace_iter != namespace_stack_[i]->namespaces.end()) { - namespace_stack_.push_back(&namespace_iter->second); - current_path_.push_back(name); - return; +// better code ?? +void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name, + std::optional modifier) { + + if (!modifier.has_value()) { + for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { + auto namespace_iter = global_info_.namespaces_[namespace_stack_[i]].namespaces.find(name); + if (namespace_iter != global_info_.namespaces_[namespace_stack_[i]].namespaces.end()) { + namespace_stack_.push_back(namespace_iter->second); + current_path_.push_back(name); + return; + } + } + } else if (modifier.has_value() && modifier.value() == utils::IsConstModifier::Const) { + for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { + auto const_namespace_iter = global_info_.namespaces_[namespace_stack_[i]].const_namespaces.find(name); + if (const_namespace_iter != global_info_.namespaces_[namespace_stack_[i]].const_namespaces.end()) { + namespace_stack_.push_back(const_namespace_iter->second); + current_path_.push_back(name); + return; + } + } + } else { + for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { + auto var_namespace_iter = global_info_.namespaces_[namespace_stack_[i]].var_namespaces.find(name); + if (var_namespace_iter != global_info_.namespaces_[namespace_stack_[i]].var_namespaces.end()) { + namespace_stack_.push_back(var_namespace_iter->second); + current_path_.push_back(name); + return; + } } } - error_handling::HandleInternalError("Can't find namespace", + error_handling::HandleInternalError("Can't find namespace " + name, "GlobalInfo.NamespaceVisitor.EnterNamespace"); } void GlobalInfo::NamespaceVisitor::ExitNamespace() { if (namespace_stack_.size() <= 1) { - // error + error_handling::HandleInternalError("Can't exit from global namespace", + "GlobalInfo.NamespaceVisitor.ExitNamespace"); return; } @@ -73,7 +100,7 @@ void GlobalInfo::NamespaceVisitor::ToGlobalNamespace() { namespace_stack_.clear(); current_path_.clear(); - namespace_stack_.push_back(&global_info_.global_namespace_); + namespace_stack_.push_back(global_info_.GlobalNamespaceId); } utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration( @@ -82,11 +109,11 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration( size_t id = 0; - auto function_id_iter = namespace_stack_.back()->functions.find(name); + auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); - if (function_id_iter == namespace_stack_.back()->functions.end()) { + if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { id = global_info_.functions_.size(); - namespace_stack_.back()->functions[name] = id; + global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size(); // add return type global_info_.functions_.back().declaration = std::move(function_declaration_info); @@ -106,11 +133,11 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::str definition::FunctionDefinition&& function_definition_info) { size_t id = 0; - auto function_id_iter = namespace_stack_.back()->functions.find(name); + auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); - if (function_id_iter == namespace_stack_.back()->functions.end()) { + if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { id = global_info_.functions_.size(); - namespace_stack_.back()->functions[name] = id; + global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; global_info_.functions_.emplace_back(); global_info_.functions_.back().argument_count = function_definition_info.argument_names.size() + 1; global_info_.functions_.back().definition = std::move(function_definition_info); @@ -136,11 +163,11 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, size_t id = 0; - auto type_id_iter = namespace_stack_.back()->types.find(type); + auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type); - if (type_id_iter == namespace_stack_.back()->types.end()) { + if (type_id_iter == global_info_.namespaces_[namespace_stack_.back()].types.end()) { id = global_info_.types_.size(); - namespace_stack_.back()->types[type] = id; + global_info_.namespaces_[namespace_stack_.back()].types[type] = id; global_info_.types_.push_back(std::move(type_info)); } else { error_handling::HandleTypecheckError("More then one type with the same name in namespace", base_node); @@ -221,6 +248,8 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& type size_t id = global_info_.typeclasses_.size(); global_info_.name_to_typeclass_[typeclass] = id; global_info_.typeclasses_.push_back(std::move(typeclass_info)); + + return id; } @@ -235,16 +264,18 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& co error_handling::HandleTypecheckError("Can't redefine basic type as constructor", base_node); } - auto constructor_id_iter = namespace_stack_.back()->constructors.find(constructor); + auto constructor_id_iter = global_info_.namespaces_[namespace_stack_.back()].constructors.find(constructor); - if (constructor_id_iter == namespace_stack_.back()->constructors.end()) { + if (constructor_id_iter == global_info_.namespaces_[namespace_stack_.back()].constructors.end()) { size_t id = global_info_.constructors_.size(); - namespace_stack_.back()->constructors[constructor] = id; + global_info_.namespaces_[namespace_stack_.back()].constructors[constructor] = id; global_info_.constructors_.push_back(std::move(constructor_info)); + + return id; } error_handling::HandleTypecheckError("More then one constructor with the same name in namespace", base_node); - return 0; + exit(1); } utils::IdType GlobalInfo::NamespaceVisitor::AddPartition(const std::vector& path, @@ -269,9 +300,9 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddPartition(const std::vector GlobalInfo::NamespaceVisitor::FindNamespace(const std::optional>& path) { - return FindSomething(path, - [] (definition::Namespace* current_namespace) -> std::optional { +std::optional GlobalInfo::NamespaceVisitor::FindNamespace(const std::optional>& path) { + return FindSomething(path, + [] (utils::IdType current_namespace) -> std::optional { return current_namespace; }); } @@ -280,10 +311,10 @@ std::optional GlobalInfo::NamespaceVisitor::FindFunction( const std::optional>& path, const std::string& name) { return FindSomething(path, - [name] (definition::Namespace* current_namespace) -> std::optional { + [name, this] (utils::IdType current_namespace) -> std::optional { - auto function_info_iter = current_namespace->functions.find(name); - if (function_info_iter == current_namespace->functions.end()) { + auto function_info_iter = global_info_.namespaces_[current_namespace].functions.find(name); + if (function_info_iter == global_info_.namespaces_[current_namespace].functions.end()) { return std::nullopt; } @@ -299,22 +330,22 @@ std::optional GlobalInfo::NamespaceVisitor::FindMethod( // TODO: remove overhead return GlobalInfo::NamespaceVisitor::FindSomething(path, - [type, name, modifier] (definition::Namespace* current_namespace) -> std::optional { + [type, name, modifier, this] (utils::IdType current_namespace) -> std::optional { auto variable_namespace_iter = (modifier == utils::IsConstModifier::Const - ? current_namespace->const_namespaces.find(type) - : current_namespace->var_namespaces.find(type)); + ? global_info_.namespaces_[current_namespace].const_namespaces.find(type) + : global_info_.namespaces_[current_namespace].var_namespaces.find(type)); if (variable_namespace_iter == (modifier == utils::IsConstModifier::Const - ? current_namespace->const_namespaces.end() - : current_namespace->var_namespaces.end())) { + ? global_info_.namespaces_[current_namespace].const_namespaces.end() + : global_info_.namespaces_[current_namespace].var_namespaces.end())) { return std::nullopt; } - auto method_iter = variable_namespace_iter->second.functions.find(name); - if (method_iter == variable_namespace_iter->second.functions.end()) { + auto method_iter = global_info_.namespaces_[variable_namespace_iter->second].functions.find(name); + if (method_iter == global_info_.namespaces_[variable_namespace_iter->second].functions.end()) { return std::nullopt; } @@ -326,10 +357,10 @@ std::optional GlobalInfo::NamespaceVisitor::FindType( const std::optional>& path, const std::string& type) { return FindSomething(path, - [type] (definition::Namespace* current_namespace) -> std::optional { + [type, this] (utils::IdType current_namespace) -> std::optional { - auto type_info_iter = current_namespace->types.find(type); - if (type_info_iter == current_namespace->types.end()) { + auto type_info_iter = global_info_.namespaces_[current_namespace].types.find(type); + if (type_info_iter == global_info_.namespaces_[current_namespace].types.end()) { return std::nullopt; } @@ -338,9 +369,9 @@ std::optional GlobalInfo::NamespaceVisitor::FindType( } std::optional GlobalInfo::NamespaceVisitor::FindLocalType(const std::string& type) { - auto type_id_iter = namespace_stack_.back()->types.find(type); + auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type); - if (type_id_iter != namespace_stack_.back()->types.end()) { + if (type_id_iter != global_info_.namespaces_[namespace_stack_.back()].types.end()) { return type_id_iter->second; } @@ -371,10 +402,10 @@ std::optional GlobalInfo::NamespaceVisitor::FindConstructor( const std::optional>& path, const std::string& constructor) { return FindSomething(path, - [constructor] (definition::Namespace* current_namespace) -> std::optional { + [constructor, this] (utils::IdType current_namespace) -> std::optional { - auto constructor_info_iter = current_namespace->constructors.find(constructor); - if (constructor_info_iter == current_namespace->constructors.end()) { + auto constructor_info_iter = global_info_.namespaces_[current_namespace].constructors.find(constructor); + if (constructor_info_iter == global_info_.namespaces_[current_namespace].constructors.end()) { return std::nullopt; } @@ -385,9 +416,9 @@ std::optional GlobalInfo::NamespaceVisitor::FindConstructor( template std::optional GlobalInfo::NamespaceVisitor::FindSomething( const std::optional>& path, - std::function(definition::Namespace*)> search_func) { + std::function(utils::IdType)> search_func) { for (ssize_t i = namespace_stack_.size() - 1; i >= 0; --i) { - definition::Namespace* current_namespace = nullptr; + utils::IdType current_namespace; if (path.has_value()) { auto maybe_namespace = FindNamespaceIn(namespace_stack_[i], path.value()); @@ -410,16 +441,16 @@ std::optional GlobalInfo::NamespaceVisitor::FindSomething( return std::nullopt; } -std::optional GlobalInfo::NamespaceVisitor::FindNamespaceIn( - definition::Namespace* current_namespace, +std::optional GlobalInfo::NamespaceVisitor::FindNamespaceIn( + utils::IdType current_namespace, const std::vector& path) { - definition::Namespace* next_namespace = current_namespace; + utils::IdType next_namespace = current_namespace; for (auto& name : path) { - auto next_namespace_iter = next_namespace->namespaces.find(name); - if (next_namespace_iter == next_namespace->namespaces.end()) { + auto next_namespace_iter = global_info_.namespaces_[next_namespace].namespaces.find(name); + if (next_namespace_iter == global_info_.namespaces_[next_namespace].namespaces.end()) { return std::nullopt; } - next_namespace = &next_namespace_iter->second; + next_namespace = next_namespace_iter->second; } return next_namespace; diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 3c8b006..5d939c3 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -30,7 +30,7 @@ void LinkSymbolsVisitor::Visit(Namespace* node) { node->link_typeclass_id_ = maybe_typeclass.value(); } - namespace_visitor_.EnterNamespace(node->type); + namespace_visitor_.EnterNamespace(node->type, node->modifier); Visitor::Visit(&node->scope); @@ -64,13 +64,17 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check return; } + // check made in typecheck visitor ?? + ////////////////////////////////////////////////////////// // abstract / basic / TODO: local abstract type - if (path.size() == 0 && namespace_visitor_.FindAbstractType(node->type.type).has_value()) { // TODO - return; - } + // if (path.size() == 0 && (namespace_visitor_.FindAbstractType(node->type.type).has_value()) { + // return; + // } + ////////////////////////////////////////////////////////// - if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) { // TODO: check, that not bastract types - error_handling::HandleTypecheckError("Type or constructor not found", node->base); + if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) { + // check made in typecheck visitor ?? + return; } if (node->constructor_id_.has_value()) { @@ -87,22 +91,18 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check node->type.type_id_ = node->type_id_.value(); } - std::optional maybe_type_namespace = namespace_visitor_.FindNamespace(path); + std::optional maybe_type_namespace = namespace_visitor_.FindNamespace(path); if (maybe_type_namespace.has_value()) { - info::definition::Namespace* type_namespace = maybe_type_namespace.value(); + info::definition::Namespace* type_namespace = &namespace_visitor_.GetGlobalInfo()->GetNamespaceInfo(maybe_type_namespace.value()); for (ssize_t i = (ssize_t)node->path.size(); i >= 0; --i) { - info::definition::Namespace* parent_namespace = type_namespace->parent_namespace; + info::definition::Namespace* parent_namespace = &namespace_visitor_.GetGlobalInfo()->GetNamespaceInfo(type_namespace->parent_namespace); auto type_iter = parent_namespace->types.find(type_namespace->type_name); if (type_iter != parent_namespace->types.end()) { node->path[i].type_id_ = type_iter->second; } - if (parent_namespace == nullptr) { - error_handling::HandleInternalError("Parent namespace is null in type expression", "LinkSymbolsVisitor"); - } - type_namespace = parent_namespace; } } @@ -116,7 +116,7 @@ void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) { // TODO: check if (maybe_typeclass.has_value()) { node->typeclass_id_ = maybe_typeclass.value(); } else { - error_handling::HandleTypecheckError("Type not found", node->base); + error_handling::HandleTypecheckError("Typeclass not found", node->base); } } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 849b207..32d63b9 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -45,21 +45,39 @@ void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for c abstract_type); context_manager_.DefineLocalType(node->type, abstract_type); } else if (node->link_type_id_.has_value()) { - Visitor::Visit(*namespace_visitor_.GetGlobalInfo()->GetTypeInfo(node->link_type_id_.value()).value()->value); // handle error? + auto maybe_type_info = namespace_visitor_.GetGlobalInfo()->GetTypeInfo(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, // TODO: different name + utils::ClassInternalVarName, context_manager_.AddValue( - info::type::DefinedType(node->link_type_id_.value(), current_type_, context_manager_.GetValueManager()), + info::type::DefinedType(node->link_type_id_.value(), + current_type_, + maybe_type_info.value()->modifier, + context_manager_.GetValueManager()), IsConstModifierToValueType(node->modifier.value()))); } } else { - if (node->link_typeclass_id_.has_value()) { // ?? + if (node->link_typeclass_id_.has_value()) { // TODO error_handling::HandleTypecheckError("Typeclass can't have not variable namespace", node->base); } + context_manager_.EnterContext(); } - namespace_visitor_.EnterNamespace(node->type); + + if (node->link_type_id_.has_value()) { + if (type_namespaces_.count(node->link_type_id_.value()) != 0) { + error_handling::HandleTypecheckError("Namespaces of one type one in another", node->base); + } + type_namespaces_.insert(node->link_type_id_.value()); + } + + namespace_visitor_.EnterNamespace(node->type, node->modifier); Visit(&node->scope); @@ -67,6 +85,10 @@ void TypeCheckVisitor::Visit(Namespace* node) { // TODO: two var namespces for c context_manager_.ExitContext(); current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); + if (node->link_type_id_.has_value()) { + type_namespaces_.erase(node->link_type_id_.value()); + } + node->base.type_ = current_type_; } @@ -79,26 +101,6 @@ void TypeCheckVisitor::Visit(ImportStatement* node) {} void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) { error_handling::HandleInternalError("Unimplemented", "TypeCheckVisitor.AliasDefinitionStatement"); - // if (!is_in_statement_) { // do nothing if alias is not applied - // current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); - // return; - // } - // - // context_manager_.EnterContext(); - // - // for (auto& parameter : node->parameters) { - // current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, - // parameter, - // /*TODO*/{}), - // utils::ValueType::Tmp); - // context_manager_.DefineLocalType(parameter, current_type_); - // } - // - // Visit(node->value.get()); - // - // context_manager_.ExitContext(); - // - // node->base.type_ = current_type_; } void TypeCheckVisitor::Visit(VariableDefinitionStatement* node) { @@ -152,13 +154,13 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { is_in_statement_ = true; context_manager_.EnterContext(); - const info::definition::Function& function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_); + info::definition::Function& function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_); if (!function_info.declaration.has_value()) { error_handling::HandleTypecheckError("Function defined, but not declared", node->base); } - const info::definition::FunctionDeclaration& declaration = function_info.declaration.value(); + info::definition::FunctionDeclaration& declaration = function_info.declaration.value(); for (auto parameter : declaration.parameters) { std::vector requirements; @@ -598,7 +600,7 @@ void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { // TODO: Check, that type is not abstract ?? auto maybe_operator_id = namespace_visitor_.FindFunction(std::nullopt, node->operator_name); - const info::definition::Function* operator_info = nullptr; + info::definition::Function* operator_info = nullptr; node->is_method_ = false; @@ -757,7 +759,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } // TODO: better decision ?? - std::optional maybe_const_function_id = maybe_type_info.value()->parent_namespace->const_namespaces.at(maybe_type_info.value()->type.type).functions[node->name]; + std::optional maybe_const_function_id = namespace_visitor_.GetGlobalInfo()->GetNamespaceInfo(namespace_visitor_.GetGlobalInfo()->GetNamespaceInfo(maybe_type_info.value()->parent_namespace).const_namespaces.at(maybe_type_info.value()->type.type)).functions[node->name]; utils::ValueType expression_value_type = context_manager_.GetValueType(current_type_); @@ -768,7 +770,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { if (expression_value_type == utils::ValueType::Var || expression_value_type == utils::ValueType::Tmp) { // TODO: choose expression value types - maybe_function_id = maybe_type_info.value()->parent_namespace->var_namespaces.at(maybe_type_info.value()->type.type).functions[node->name]; + maybe_function_id = namespace_visitor_.GetGlobalInfo()->GetNamespaceInfo(namespace_visitor_.GetGlobalInfo()->GetNamespaceInfo(maybe_type_info.value()->parent_namespace).var_namespaces.at(maybe_type_info.value()->type.type)).functions[node->name]; } if (maybe_const_function_id.has_value() && maybe_function_id.has_value()) { // TODO: handle on link_types stage @@ -1032,7 +1034,8 @@ void TypeCheckVisitor::Visit(NameExpression* node) { utils::ValueType variable_value_type = context_manager_.GetValueType(current_type_); for (size_t i = 1; i < node->names.size(); ++i) { - std::optional maybe_type_value = context_manager_.GetAnyValue(current_type_)->GetFieldType(node->names[i]); + std::optional maybe_type_value = + context_manager_.GetAnyValue(current_type_)->GetFieldType(node->names[i], type_namespaces_); if (!maybe_type_value.has_value()) { error_handling::HandleTypecheckError("Variable field not found", node->base); } @@ -1251,7 +1254,6 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { if (maybe_internal_type.has_value()) { // checks made in link_symbols_visitor - current_type_ = context_manager_.AddValue(maybe_internal_type.value(), utils::ValueType::Tmp); } else { std::optional maybe_local_abstract_type = context_manager_.GetLocalType(node->type.type); @@ -1268,6 +1270,11 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { Visitor::Visit(*maybe_type_info.value()->value); current_type_ = TypeInContext(current_type_, context); + current_type_ = context_manager_.AddValue(info::type::DefinedType(node->type_id_.value(), + current_type_, + maybe_type_info.value()->modifier, + context_manager_.GetValueManager()), + utils::ValueType::Tmp); } else { error_handling::HandleTypecheckError("Type not found", node->base); } diff --git a/src/types.cpp b/src/types.cpp index 7e4ef44..b0319f4 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -29,7 +29,8 @@ bool AbstractType::operator>(const AbstractType& type) const { return type < *this; } -std::optional AbstractType::GetFieldType(const std::string& name) const { +std::optional AbstractType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { return std::nullopt; } @@ -59,8 +60,12 @@ bool DefinedType::operator>(const DefinedType& type) const { return type < *this; } -std::optional DefinedType::GetFieldType(const std::string& name) const { - return type_manager_->GetAnyValue(type_)->GetFieldType(name); +std::optional DefinedType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { + if (class_modifier_ == utils::ClassModifier::Struct || type_namespaces.count(type_id_) != 0) { + return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces); + } + return std::nullopt; } // @@ -109,7 +114,8 @@ bool TupleType::operator>(const TupleType& type) const { return type < *this; } -std::optional TupleType::GetFieldType(const std::string& name) const { +std::optional TupleType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { for (size_t i = 0; i < fields_.size(); ++i) { // TODO: optimize?? if (fields_[i].first.has_value() && fields_[i].first.value() == name) { return fields_[i].second; @@ -160,9 +166,10 @@ bool VariantType::operator>(const VariantType& type) const { return type < *this; } -std::optional VariantType::GetFieldType(const std::string& name) const { +std::optional VariantType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { if (current_constructor_.has_value()) { - return constructors_.at(current_constructor_.value()).GetFieldType(name); + return constructors_.at(current_constructor_.value()).GetFieldType(name, type_namespaces); } return std::nullopt; } @@ -191,7 +198,8 @@ bool OptionalType::operator>(const OptionalType& type) const { return type < *this; } -std::optional OptionalType::GetFieldType(const std::string& name) const { +std::optional OptionalType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { return std::nullopt; } @@ -219,8 +227,9 @@ bool ReferenceToType::operator>(const ReferenceToType& type) const { return type < *this; } -std::optional ReferenceToType::GetFieldType(const std::string& name) const { - return type_manager_->GetAnyValue(type_)->GetFieldType(name); +std::optional ReferenceToType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { + return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces); } // @@ -270,7 +279,8 @@ bool FunctionType::operator>(const FunctionType& type) const { return type < *this; } -std::optional FunctionType::GetFieldType(const std::string& name) const { +std::optional FunctionType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { return std::nullopt; } @@ -299,7 +309,8 @@ bool ArrayType::operator>(const ArrayType& type) const { return type < *this; } -std::optional ArrayType::GetFieldType(const std::string& name) const { +std::optional ArrayType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { return std::nullopt; } @@ -405,28 +416,29 @@ bool Type::operator>(const Type& type) const { return type < *this; } -std::optional Type::GetFieldType(const std::string& name) const { +std::optional Type::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { size_t index = type_.index(); switch (index) { case 0: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); case 1: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); case 2: return std::nullopt; case 3: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); case 4: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); case 5: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); case 6: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); case 7: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); case 8: - return std::get(type_).GetFieldType(name); + return std::get(type_).GetFieldType(name, type_namespaces); default: // error break; diff --git a/tests/test_code.lang b/tests/test_code.lang index 798f106..a442cd0 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -1,17 +1,17 @@ -basic Float -basic Int -basic String -basic Char -basic Bool -basic Unit +// basic Float +// basic Int +// basic String +// basic Char +// basic Bool +// basic Unit // decl not : Bool -> Bool def not : x = - match x with - | true -> false - | false -> true + (match x with + | true -> false + | false -> true) decl ( && ) : Bool -> Bool -> Bool def ( && ) : x y = @@ -40,7 +40,7 @@ typeclass Eq = & var ( != ) : Eq -> Bool namespace const Eq { - def var ( != ) : x = not: (self == x) + def ( != ) : x = not: (self == x) } // @@ -101,13 +101,11 @@ typeclass Bounded = typeclass Enum = & var succ : -> (Optional Enum) & var pred : -> (Optional Enum) - & toEnum : Int -> Enum - & var fromEnum : -> Int + & to_enum : Int -> Enum + & var from_enum : -> Int // - - // // bad // typeclass Functor 'A = // & fmap 'B ('F : (#Functor 'B)) : ('A -> 'B) -> Functor -> 'F @@ -120,11 +118,6 @@ typeclass Enum = // & begin : -> 'Iter // & end : -> 'Iter -// - -class Slice ('Elem : ) ('Structure : (#Iterable)) = - - // decl ( -- ) : Int -> Int -> Int_0