diff --git a/CMakeLists.txt b/CMakeLists.txt index c44c1f9..6ff28e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ include_directories(include add_executable(lang_interpreter src/main.cpp src/types.cpp src/values.cpp + src/utils.cpp src/global_info.cpp src/typeclass_graph.cpp src/visitor.cpp diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index 0ff48be..c71e2b3 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -172,7 +172,14 @@ private: } } - // + void AddGraphIdLocalTypes(utils::IdType graph_id, utils::IdType type) { + std::unordered_set requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id); + requirement_graph_ids.insert(graph_id); + + for (auto& requirement_graph_id : requirement_graph_ids) { + context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, type); + } + } private: info::GlobalInfo::NamespaceVisitor namespace_visitor_; diff --git a/include/types.hpp b/include/types.hpp index 3af1975..760a128 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -50,14 +50,12 @@ public: } bool HasTypeclass(utils::IdType graph_id) { - error_handling::DebugPrint(name_); - error_handling::DebugPrint(requirement_graph_ids_.size()); - for (auto& requirement_graph_id : requirement_graph_ids_) { - error_handling::DebugPrint(requirement_graph_id); - } return requirement_graph_ids_.count(graph_id) != 0; } + std::string ToString() { + return "Abstract"; + } private: utils::AbstractTypeModifier modifier_; std::string name_; @@ -93,6 +91,9 @@ public: return class_modifier_; } + std::string ToString() { + return "Defined"; + } private: utils::IdType type_id_; // in defined types utils::IdType type_; // in types manager, created using context types (if specific type) @@ -140,6 +141,32 @@ inline std::optional ToInternalType(const std::string& type) { return std::nullopt; } +inline std::string ToString(InternalType type) { + std::string result; + + switch (type) { + case InternalType::Float: + result = "Float"; + break; + case InternalType::Int: + result = "Int"; + break; + case InternalType::String: + result = "String"; + break; + case InternalType::Char: + result = "Char"; + break; + case InternalType::Bool: + result = "Bool"; + break; + case InternalType::Unit: + result = "Unit"; + break; + } + return result; +} + class TupleType { public: TupleType() = default; @@ -160,6 +187,7 @@ public: return fields_; } + std::string ToString(); private: std::optional name_; std::vector, utils::IdType>> fields_; @@ -190,6 +218,7 @@ public: current_constructor_ = constructor; } + std::string ToString(); private: std::optional name_; std::vector constructors_; @@ -211,6 +240,7 @@ public: std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; + std::string ToString(); private: utils::IdType type_; TypeManager* type_manager_ = nullptr; @@ -232,6 +262,7 @@ public: std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; + std::string ToString(); private: std::vector references_; utils::IdType type_; @@ -256,6 +287,7 @@ public: std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; + std::string ToString(); private: std::vector argument_types_; utils::IdType return_type_; @@ -282,6 +314,7 @@ public: return elements_type_; } + std::string ToString(); private: size_t size_; // = 0 for dynamic utils::IdType elements_type_; @@ -316,6 +349,8 @@ public: OptionalType>& GetType() { return type_; } + + std::string ToString(); private: std::variant builtin_functions; - - builtin_functions.insert("="); - builtin_functions.insert("<-"); - builtin_functions.insert("=="); - builtin_functions.insert("!="); - builtin_functions.insert("<"); - builtin_functions.insert(">"); - builtin_functions.insert("<="); - builtin_functions.insert(">="); - builtin_functions.insert("+="); - builtin_functions.insert("-="); - builtin_functions.insert("*="); - builtin_functions.insert("div"); - builtin_functions.insert("mod"); - builtin_functions.insert("/="); - // builtin_functions.insert("+"); - // builtin_functions.insert("-"); - // builtin_functions.insert("*"); - // builtin_functions.insert("/"); - builtin_functions.insert("&&"); - builtin_functions.insert("||"); - builtin_functions.insert("size"); - builtin_functions.insert("random"); - builtin_functions.insert("print"); - builtin_functions.insert("scan"); - builtin_functions.insert("zero"); - builtin_functions.insert("one"); - - return builtin_functions.count(name) != 0; -} +bool IsBuiltinFunction(const std::string& name); template class Storage { @@ -265,34 +214,12 @@ private: std::vector ranks_; }; -// move to .cpp ?? -inline void BackVisitDfs(size_t id, - std::vector& verticles, - std::vector& marks, - const std::vector>& edges, - size_t mark) { - if (marks[id] != 0) { - return; - } +void BackVisitDfs(size_t id, + std::vector& verticles, + std::vector& marks, + const std::vector>& edges, + size_t mark); - marks[id] = mark; - verticles.push_back(id); - - for (size_t i = 0; i < edges[id].size(); ++i) { - BackVisitDfs(id, verticles, marks, edges, mark); - } -} - -// move to .cpp ?? -inline std::vector BackTopSort(const std::vector>& edges_) { - std::vector sorted_verticles; - std::vector marks(edges_.size(), 0); - - for (size_t i = 0; i < marks.size(); ++i) { - BackVisitDfs(i, sorted_verticles, marks, edges_, 1); - } - - return sorted_verticles; -} +std::vector BackTopSort(const std::vector>& edges_); } // namespace utils diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 9f37969..5a3bee1 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -52,11 +52,9 @@ void TypeCheckVisitor::Visit(Namespace* node) { context_manager_.EnterContext(); } - // including namespace typeclass - // define typeclasses local types as namespace typeclass - for (auto& requirement_graph_id : requirement_graph_ids) { - context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, abstract_type); - } + abstract_type = context_manager_.ToModifiedValue(abstract_type, utils::ValueType::Tmp); // ?? + + AddGraphIdLocalTypes(graph_id, abstract_type); } else if (node->link_type_id_.has_value()) { auto maybe_type_info = global_info_.GetTypeInfo(node->link_type_id_.value()); @@ -80,12 +78,7 @@ void TypeCheckVisitor::Visit(Namespace* node) { context_manager_.EnterContext(); } - // better decision ?? - // define typeclasses local types as namespace type - auto typeclass_graph_ids = typeclass_graph_.GetDependenciesVector(type_info->type.node->graph_id_); - for (auto& typeclass_graph_id : typeclass_graph_ids) { - context_manager_.DefineLocalType(typeclass_graph_.GetVertex(typeclass_graph_id).name, type); - } + AddGraphIdLocalTypes(type_info->type.node->graph_id_, type); if (type_namespaces_.count(node->link_type_id_.value()) != 0) { error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base); @@ -269,6 +262,8 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { returned_type_ = current_type_; } if (!context_manager_.EqualValues(returned_type, returned_type_.value())) { + error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type)->ToString()); + error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type_.value())->ToString()); error_handling::HandleTypecheckError("Wrong function return type", node->base); } returned_type_ = std::nullopt; @@ -319,7 +314,7 @@ void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, node->type->type, requirements), utils::ValueType::Tmp); if (!context_manager_.DefineLocalType(node->type->type, current_type_)) { - error_handling::HandleTypecheckError("Can't define basic / astract type: abstract type redefinition", node->base); + error_handling::HandleTypecheckError("Can't define basic / abstract type: abstract type redefinition", node->base); } current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); @@ -731,6 +726,8 @@ void TypeCheckVisitor::Visit(AccessExpression* node) { // TODO: more builtin functions, better handling (??) void TypeCheckVisitor::Visit(FunctionCallExpression* node) { + context_manager_.EnterContext(); + std::optional maybe_function_declaration; std::unordered_map context; @@ -749,7 +746,8 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { if (node->prefix.has_value()) { if (std::holds_alternative>(node->prefix.value())) { Visitor::Visit(*std::get>(node->prefix.value())); - maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_); + utils::IdType expression_type = current_type_; + maybe_function_declaration = FindExpressionMethodAndUpdate(node, expression_type); } else if (std::holds_alternative>(node->prefix.value())) { maybe_function_declaration = FindTypeFunctionAndUpdate( node, @@ -843,6 +841,8 @@ void TypeCheckVisitor::Visit(TupleExpression* node) { info::type::TupleType(std::nullopt, fields, context_manager_.GetValueManager()), utils::ValueType::Tmp); + context_manager_.ExitContext(); + node->base.type_ = current_type_; } @@ -988,7 +988,10 @@ void TypeCheckVisitor::Visit(TypeConstructor* node) { current_type_ = TypeInContext(current_type_, context); current_type_ = context_manager_.AddValue( - info::type::DefinedType(type_id, current_type_, type_info.modifier, context_manager_.GetValueManager()), + info::type::DefinedType(type_id, + current_type_, + type_info.modifier, + context_manager_.GetValueManager()), utils::ValueType::Tmp); node->base.type_ = current_type_; @@ -1279,7 +1282,7 @@ void TypeCheckVisitor::Visit(TypeExpression* node) { auto maybe_internal_type = info::type::ToInternalType(node->type.type); - if (maybe_internal_type.has_value()) { + if (maybe_internal_type.has_value()) { // TODO: ??? // checks made in link_symbols_visitor current_type_ = context_manager_.AddValue( @@ -1471,6 +1474,18 @@ std::optional utils::IdType expression_type) { std::optional maybe_function_declaration; + auto maybe_internal_type_info = context_manager_.GetValue(expression_type); + if (maybe_internal_type_info.has_value()) { + auto maybe_abstract_type_id = context_manager_.FindLocalType(info::type::ToString(*maybe_internal_type_info.value())); + if (maybe_abstract_type_id.has_value()) { + expression_type = maybe_abstract_type_id.value(); + } else { + error_handling::HandleInternalError("InternalType local abstract type not found", + "TypeCheckVisitor.FindExpressionMethodAndUpdate", + &node->base); + } + } + auto maybe_abstract_type_info = context_manager_.GetValue(expression_type); if (maybe_abstract_type_info.has_value()) { @@ -1478,8 +1493,7 @@ std::optional maybe_abstract_type_info.value(), true); } else { - auto maybe_defined_type_info = - context_manager_.GetValue(expression_type); + auto maybe_defined_type_info = context_manager_.GetValue(expression_type); if (!maybe_defined_type_info.has_value()) { error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", node->base); } @@ -1488,7 +1502,7 @@ std::optional auto maybe_type_info = global_info_.GetTypeInfo(type_id); if (!maybe_type_info.has_value()) { error_handling::HandleInternalError("Functions / Methods implemented only for AnyType", - "TypeCheckVisitor.FunctionCallExpresssion", + "TypeCheckVisitor.FindExpressionMethodAndUpdate", &node->base); } info::definition::AnyType* type_info = maybe_type_info.value(); @@ -1645,6 +1659,7 @@ std::optional } node->graph_id_ = maybe_typeclass_graph_id; + node->abstract_type_name_ = abstract_type_info->GetName(); maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; @@ -1671,6 +1686,7 @@ std::optional } node->graph_id_ = defined_type->type.node->graph_id_; + // type defined -> abstract type name not needed maybe_function_declaration = maybe_type_function_info.value()->declaration; diff --git a/src/typeclass_graph.cpp b/src/typeclass_graph.cpp index 0fa996c..3dd8e93 100644 --- a/src/typeclass_graph.cpp +++ b/src/typeclass_graph.cpp @@ -128,7 +128,7 @@ void TypeclassGraph::CalculateGraph() { } std::vector sorted_verticles = utils::BackTopSort(edges); - std::reverse(sorted_verticles.begin(), sorted_verticles.end()); + // std::reverse(sorted_verticles.begin(), sorted_verticles.end()); for (auto& id : sorted_verticles) { for (auto& dependency : verticles_[id].dependencies) { @@ -146,7 +146,7 @@ void TypeclassGraph::CalculateGraph() { } } } - for (auto& inherited_dependency : verticles_[method_to_vertex_[dependency]].dependencies) { + for (auto& inherited_dependency : verticles_[name_to_typeclass_[dependency]].dependencies) { verticles_[id].dependencies.insert(inherited_dependency); } } diff --git a/src/types.cpp b/src/types.cpp index 6a36158..0d9d9eb 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -124,6 +124,21 @@ std::optional TupleType::GetFieldType(const std::string& name, return std::nullopt; } +std::string TupleType::ToString() { + std::string result; + + result += "("; + + for (auto& field : fields_) { + result += "& "; + result += type_manager_->GetAnyValue(field.second)->ToString(); + } + + result += ")"; + + return result; +} + // std::optional VariantType::InContext(const std::unordered_map& context) { @@ -174,6 +189,21 @@ std::optional VariantType::GetFieldType(const std::string& name, return std::nullopt; } +std::string VariantType::ToString() { + std::string result; + + result += "("; + + for (auto& constructor : constructors_) { + result += "& "; + result += constructor.ToString(); + } + + result += ")"; + + return result; +} + // std::optional OptionalType::InContext(const std::unordered_map& context) { @@ -203,6 +233,10 @@ std::optional OptionalType::GetFieldType(const std::string&, return std::nullopt; } +std::string OptionalType::ToString() { + return "Optional " + type_manager_->GetAnyValue(type_)->ToString(); +} + // std::optional ReferenceToType::InContext(const std::unordered_map& context) { @@ -232,6 +266,29 @@ std::optional ReferenceToType::GetFieldType(const std::string& na return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces); } + +std::string ReferenceToType::ToString() { + std::string result; + + for (auto& reference : references_) { + switch (reference) { + case utils::ReferenceModifier::Dereference: + result += '~'; + break; + case utils::ReferenceModifier::Reference: + result += '^'; + break; + case utils::ReferenceModifier::UniqueReference: + result += '@'; + break; + } + } + + result += type_manager_->GetAnyValue(type_)->ToString(); + + return result; +} + // std::optional FunctionType::InContext(const std::unordered_map& context) { @@ -284,6 +341,26 @@ std::optional FunctionType::GetFieldType(const std::string&, return std::nullopt; } +std::string FunctionType::ToString() { + std::string result; + + result += "("; + + bool is_first_argument = true; + for (auto& argument_type : argument_types_) { + if (is_first_argument) { + is_first_argument = false; + } else { + result += " -> "; + } + result += type_manager_->GetAnyValue(argument_type)->ToString(); + } + + result += " -> " + type_manager_->GetAnyValue(return_type_)->ToString() + ")"; + + return result; +} + // std::optional ArrayType::InContext(const std::unordered_map& context) { @@ -314,6 +391,10 @@ std::optional ArrayType::GetFieldType(const std::string&, return std::nullopt; } +std::string ArrayType::ToString() { + return "Array (" + std::to_string(size_) + ") " + type_manager_->GetAnyValue(elements_type_)->ToString(); +} + // std::optional Type::InContext(const std::unordered_map& context) { @@ -477,5 +558,35 @@ std::string Type::GetTypeName() const { return ""; // ?? } +std::string Type::ToString() { + size_t index = type_.index(); + + switch (index) { + case 0: + return std::get(type_).ToString(); + case 1: + return std::get(type_).ToString(); + case 2: + return ::info::type::ToString(std::get(type_)); + case 3: + return std::get(type_).ToString(); + case 4: + return std::get(type_).ToString(); + case 5: + return std::get(type_).ToString(); + case 6: + return std::get(type_).ToString(); + case 7: + return std::get(type_).ToString(); + case 8: + return std::get(type_).ToString(); + default: + // error + break; + } + + return ""; +} + } // namespace info::type diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..5d80484 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,99 @@ +// for clangd +#include "../include/utils.hpp" +#include"../include/error_handling.hpp" + +namespace utils { + +using std::size_t; + +using IdType = size_t; + +ValueType IsConstModifierToValueType(IsConstModifier modifier) { + switch (modifier) { + case IsConstModifier::Const: + return ValueType::Const; + case IsConstModifier::Var: + return ValueType::Var; + } + + exit(1); // unreachable +} + +ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier) { + switch (modifier) { + case ClassInternalsModifier::Const: + return ValueType::Const; + case ClassInternalsModifier::Var: + return ValueType::Var; + case ClassInternalsModifier::Static: + throw std::bad_cast(); // ?? + } + + exit(1); // unreachable +} + +bool IsBuiltinFunction(const std::string& name) { // optimize ?? + std::unordered_set builtin_functions; + + builtin_functions.insert("="); + builtin_functions.insert("<-"); + builtin_functions.insert("=="); + // builtin_functions.insert("!="); + builtin_functions.insert("<"); + // builtin_functions.insert(">"); + // builtin_functions.insert("<="); + // builtin_functions.insert(">="); + builtin_functions.insert("+="); + builtin_functions.insert("-="); + builtin_functions.insert("*="); + builtin_functions.insert("div"); + builtin_functions.insert("mod"); + builtin_functions.insert("/="); + // builtin_functions.insert("+"); + // builtin_functions.insert("-"); + // builtin_functions.insert("*"); + // builtin_functions.insert("/"); + builtin_functions.insert("&&"); + builtin_functions.insert("||"); + builtin_functions.insert("size"); + builtin_functions.insert("random"); + builtin_functions.insert("print"); + builtin_functions.insert("scan"); + builtin_functions.insert("zero"); + builtin_functions.insert("one"); + + return builtin_functions.count(name) != 0; +} + +void BackVisitDfs(size_t id, + std::vector& verticles, + std::vector& marks, + const std::vector>& edges, + size_t mark) { + if (marks[id] != 0) { + return; + } + + marks[id] = mark; + + for (size_t i = 0; i < edges[id].size(); ++i) { + BackVisitDfs(edges[id][i], verticles, marks, edges, mark); + } + + verticles.push_back(id); +} + +std::vector BackTopSort(const std::vector>& edges_) { + std::vector sorted_verticles; + std::vector marks(edges_.size(), 0); + + for (size_t i = 0; i < edges_.size(); ++i) { + if (marks[i] == 0) { + BackVisitDfs(i, sorted_verticles, marks, edges_, 1); + } + } + + return sorted_verticles; +} + +} // namespace utils diff --git a/tests/test_code.lang b/tests/test_code.lang index eac5aea..559ecd8 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -77,8 +77,8 @@ namespace var Mult { } typeclass (IDiv : #Mult) = - & var div : IDiv -> Unit - & var mod : IDiv -> Unit + & var div : IDiv -> IDiv + & var mod : IDiv -> IDiv namespace var IDiv { def mod : x = self -. x * self.div: x @@ -190,7 +190,7 @@ def ( -- ) : begin end = { var current = begin return (while current < end do { ; current += 1 - return current - 1 + bring current - 1 }) }