diff --git a/include/types.hpp b/include/types.hpp index 0e663df..29c837e 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -14,6 +14,8 @@ namespace info::type { +// TODO: implement DeduceContext + // TODO: move in constructors class TypeManager; @@ -29,8 +31,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const AbstractType& type) const; - bool operator<(const AbstractType& type) const; - bool operator>(const AbstractType& type) const; + bool Require(const AbstractType& type) const; + + bool DeduceContext(const AbstractType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -43,6 +47,10 @@ public: return graph_id == graph_id_ || typeclass_graph_.GetDependenciesSet(graph_id_).count(graph_id) != 0; } + std::string GetName() const { + return typeclass_graph_.GetVertex(graph_id_).name; + } + std::string ToString() const { return "Abstract " + std::to_string(graph_id_) + " ( " + typeclass_graph_.GetVertex(graph_id_).name + " )"; } @@ -63,8 +71,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const DefinedType& type) const; - bool operator<(const DefinedType& type) const; - bool operator>(const DefinedType& type) const; + bool Require(const DefinedType& type) const; + + bool DeduceContext(const DefinedType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -166,8 +176,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const TupleType& type) const; - bool operator<(const TupleType& type) const; - bool operator>(const TupleType& type) const; + bool Require(const TupleType& type) const; + + bool DeduceContext(const TupleType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -193,8 +205,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const VariantType& type) const; - bool operator<(const VariantType& type) const; - bool operator>(const VariantType& type) const; + bool Require(const VariantType& type) const; + + bool DeduceContext(const VariantType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -223,8 +237,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const OptionalType& type) const; - bool operator<(const OptionalType& type) const; - bool operator>(const OptionalType& type) const; + bool Require(const OptionalType& type) const; + + bool DeduceContext(const OptionalType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -254,8 +270,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const ReferenceToType& type) const; - bool operator<(const ReferenceToType& type) const; - bool operator>(const ReferenceToType& type) const; + bool Require(const ReferenceToType& type) const; + + bool DeduceContext(const ReferenceToType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -279,8 +297,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const FunctionType& type) const; - bool operator<(const FunctionType& type) const; - bool operator>(const FunctionType& type) const; + bool Require(const FunctionType& type) const; + + bool DeduceContext(const FunctionType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -302,8 +322,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const ArrayType& type) const; - bool operator<(const ArrayType& type) const; - bool operator>(const ArrayType& type) const; + bool Require(const ArrayType& type) const; + + bool DeduceContext(const ArrayType& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -326,8 +348,10 @@ public: std::optional InContext(const std::unordered_map& context); bool Same(const Type& type) const; - bool operator<(const Type& type) const; // TODO: rule exceptions - bool operator>(const Type& type) const; + bool Require(const Type& type) const; // TODO: check abstract type requirements for not abstract types + + bool DeduceContext(const Type& actual_type, + std::unordered_map>& context) const; std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; @@ -397,7 +421,7 @@ public: } bool AddValueRequirement(utils::IdType type, utils::IdType requrement) { - return *GetAnyValue(requrement) < *GetAnyValue(type); + return GetAnyValue(requrement)->Require(*GetAnyValue(type)); } private: diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 2bc96ea..d9fae1b 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -764,10 +764,6 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { &node->base); } - if (node->name[0] == '_') { - error_handling::HandleTypecheckError("Only builtin functions can start with _. This function is not found", node->base); - } - // try to find function declaration if (node->prefix.has_value()) { if (std::holds_alternative>(node->prefix.value())) { @@ -794,9 +790,14 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } FunctionDeclaration* function_declaration = maybe_function_declaration.value(); + bool deduce_parameters = false; + // check & collect parmeters if (function_declaration->parameters.size() != node->parameters.size()) { - error_handling::HandleTypecheckError("Mismatched parameter count in function call expression", node->base); + if (node->parameters.size() != 0) { + error_handling::HandleTypecheckError("Mismatched parameter count in function call expression", node->base); + } + deduce_parameters = true; } for (size_t i = 0; i < node->parameters.size(); ++i) { Visit(node->parameters[i].get()); @@ -1706,7 +1707,7 @@ std::optional error_handling::HandleTypecheckError("Function not present in typeclass (abstract type)", node->base); } - // TODO: check that const functions not called on var expressions + // TODO: check that var functions not called on const expressions if ((maybe_typeclass_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) { error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); } @@ -1735,7 +1736,7 @@ std::optional // error_handling::HandleTypecheckError("Function is not declared in type", node->base); } - // TODO: check that const functions not called on var expressions + // TODO: check that var functions not called on const expressions if ((maybe_type_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) { error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); } diff --git a/src/types.cpp b/src/types.cpp index 061bfac..bc8827a 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -18,12 +18,13 @@ bool AbstractType::Same(const AbstractType& type) const { return graph_id_ == type.graph_id_; } -bool AbstractType::operator<(const AbstractType& type) const { // TODO: cache DependenciesSet +bool AbstractType::Require(const AbstractType& type) const { // TODO: cache DependenciesSet return typeclass_graph_.GetDependenciesSet(graph_id_).count(type.graph_id_) != 0 || graph_id_ == type.graph_id_; } -bool AbstractType::operator>(const AbstractType& type) const { - return type < *this; +bool AbstractType::DeduceContext(const AbstractType& actual_type, + std::unordered_map>& context) const { + return typeclass_graph_.GetDependenciesSet(graph_id_).count(actual_type.graph_id_) != 0 || graph_id_ == actual_type.graph_id_; } std::optional AbstractType::GetFieldType(const std::string&, @@ -48,13 +49,15 @@ bool DefinedType::Same(const DefinedType& type) const { && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); } -bool DefinedType::operator<(const DefinedType& type) const { +bool DefinedType::Require(const DefinedType& type) const { return type_id_ == type.type_id_ - && *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_); + && type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_)); } -bool DefinedType::operator>(const DefinedType& type) const { - return type < *this; +bool DefinedType::DeduceContext(const DefinedType& actual_type, + std::unordered_map>& context) const { + return type_id_ == actual_type.type_id_ + && type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context); } std::optional DefinedType::GetFieldType(const std::string& name, @@ -97,13 +100,13 @@ bool TupleType::Same(const TupleType& type) const { return true; } -bool TupleType::operator<(const TupleType& type) const { +bool TupleType::Require(const TupleType& type) const { if (fields_.size() != type.fields_.size()) { return false; } for (size_t i = 0; i < fields_.size(); ++i) { - if (!(*type_manager_->GetAnyValue(fields_[i].second) < *type_manager_->GetAnyValue(type.fields_[i].second))) { + if (!type_manager_->GetAnyValue(fields_[i].second)->Require(*type_manager_->GetAnyValue(type.fields_[i].second))) { return false; } } @@ -111,8 +114,19 @@ bool TupleType::operator<(const TupleType& type) const { return true; } -bool TupleType::operator>(const TupleType& type) const { - return type < *this; +bool TupleType::DeduceContext(const TupleType& actual_type, + std::unordered_map>& context) const { + if (fields_.size() != actual_type.fields_.size()) { + return false; + } + + for (size_t i = 0; i < fields_.size(); ++i) { + if (!type_manager_->GetAnyValue(fields_[i].second)->DeduceContext(*type_manager_->GetAnyValue(actual_type.fields_[i].second), context)) { + return false; + } + } + + return true; } std::optional TupleType::GetFieldType(const std::string& name, @@ -158,7 +172,6 @@ bool VariantType::Same(const VariantType& type) const { } for (size_t i = 0; i < constructors_.size(); ++i) { - if (constructors_[i].first != type.constructors_[i].first) { // TODO: decide return false; } @@ -177,22 +190,53 @@ bool VariantType::Same(const VariantType& type) const { return true; } -bool VariantType::operator<(const VariantType& type) const { +bool VariantType::Require(const VariantType& type) const { if (constructors_.size() != type.constructors_.size()) { return false; } for (size_t i = 0; i < constructors_.size(); ++i) { - if (!(constructors_[i] < constructors_[i])) { + if (constructors_[i].first != type.constructors_[i].first) { // TODO: decide return false; } + + if (constructors_[i].second.has_value() != type.constructors_[i].second.has_value()) { + return false; + } + + if (constructors_[i].second.has_value()) { + if (!constructors_[i].second.value().Require(type.constructors_[i].second.value())) { + return false; + } + } } return true; } -bool VariantType::operator>(const VariantType& type) const { - return type < *this; +bool VariantType::DeduceContext(const VariantType& actual_type, + std::unordered_map>& context) const { + if (constructors_.size() != actual_type.constructors_.size()) { + return false; + } + + for (size_t i = 0; i < constructors_.size(); ++i) { + if (constructors_[i].first != actual_type.constructors_[i].first) { // TODO: decide + return false; + } + + if (constructors_[i].second.has_value() != actual_type.constructors_[i].second.has_value()) { + return false; + } + + if (constructors_[i].second.has_value()) { + if (!constructors_[i].second.value().DeduceContext(actual_type.constructors_[i].second.value(), context)) { + return false; + } + } + } + + return true; } std::optional VariantType::GetFieldType(const std::string& name, @@ -237,12 +281,13 @@ bool OptionalType::Same(const OptionalType& type) const { return type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); } -bool OptionalType::operator<(const OptionalType& type) const { - return *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_); +bool OptionalType::Require(const OptionalType& type) const { + return type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_)); } -bool OptionalType::operator>(const OptionalType& type) const { - return type < *this; +bool OptionalType::DeduceContext(const OptionalType& actual_type, + std::unordered_map>& context) const { + return type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context); } std::optional OptionalType::GetFieldType(const std::string&, @@ -270,12 +315,13 @@ bool ReferenceToType::Same(const ReferenceToType& type) const { return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); } -bool ReferenceToType::operator<(const ReferenceToType& type) const { - return references_ == type.references_ && *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_); +bool ReferenceToType::Require(const ReferenceToType& type) const { + return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Require(*type_manager_->GetAnyValue(type.type_)); } -bool ReferenceToType::operator>(const ReferenceToType& type) const { - return type < *this; +bool ReferenceToType::DeduceContext(const ReferenceToType& actual_type, + std::unordered_map>& context) const { + return references_ == actual_type.references_ && type_manager_->GetAnyValue(type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.type_), context); } std::optional ReferenceToType::GetFieldType(const std::string& name, @@ -335,13 +381,13 @@ bool FunctionType::Same(const FunctionType& type) const { return true; } -bool FunctionType::operator<(const FunctionType& type) const { +bool FunctionType::Require(const FunctionType& type) const { if (argument_types_.size() != type.argument_types_.size()) { return false; } for (size_t i = 0; i < argument_types_.size(); ++i) { - if (!(*type_manager_->GetAnyValue(argument_types_[i]) < *type_manager_->GetAnyValue(type.argument_types_[i]))) { + if (!type_manager_->GetAnyValue(argument_types_[i])->Require(*type_manager_->GetAnyValue(type.argument_types_[i]))) { return false; } } @@ -349,8 +395,19 @@ bool FunctionType::operator<(const FunctionType& type) const { return true; } -bool FunctionType::operator>(const FunctionType& type) const { - return type < *this; +bool FunctionType::DeduceContext(const FunctionType& actual_type, + std::unordered_map>& context) const { + if (argument_types_.size() != actual_type.argument_types_.size()) { + return false; + } + + for (size_t i = 0; i < argument_types_.size(); ++i) { + if (!type_manager_->GetAnyValue(argument_types_[i])->DeduceContext(*type_manager_->GetAnyValue(actual_type.argument_types_[i]), context)) { + return false; + } + } + + return true; } std::optional FunctionType::GetFieldType(const std::string&, @@ -395,12 +452,13 @@ bool ArrayType::Same(const ArrayType& type) const { return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Same(*type_manager_->GetAnyValue(type.elements_type_)); } -bool ArrayType::operator<(const ArrayType& type) const { - return size_ == type.size_ && *type_manager_->GetAnyValue(elements_type_) < *type_manager_->GetAnyValue(type.elements_type_); +bool ArrayType::Require(const ArrayType& type) const { + return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Require(*type_manager_->GetAnyValue(type.elements_type_)); } -bool ArrayType::operator>(const ArrayType& type) const { - return type < *this; +bool ArrayType::DeduceContext(const ArrayType& actual_type, + std::unordered_map>& context) const { + return size_ == actual_type.size_ && type_manager_->GetAnyValue(elements_type_)->DeduceContext(*type_manager_->GetAnyValue(actual_type.elements_type_), context); } std::optional ArrayType::GetFieldType(const std::string&, @@ -477,30 +535,30 @@ bool Type::Same(const Type& type) const { return false; } -bool Type::operator<(const Type& type) const { +bool Type::Require(const Type& type) const { // TODO: check abstract type requirements for not abstract types size_t this_index = type_.index(); size_t type_index = type.type_.index(); if (this_index == type_index) { switch (this_index) { case 0: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); case 1: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); case 2: return std::get(type_) == std::get(type.type_); case 3: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); case 4: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); case 5: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); case 6: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); case 7: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); case 8: - return std::get(type_) < std::get(type.type_); + return std::get(type_).Require(std::get(type.type_)); default: // error break; @@ -510,8 +568,57 @@ bool Type::operator<(const Type& type) const { return false; } -bool Type::operator>(const Type& type) const { - return type < *this; +// TODO: check abstract type requirements for not abstract types +bool Type::DeduceContext(const Type& actual_type, + std::unordered_map>& context) const { + size_t this_index = type_.index(); + size_t type_index = actual_type.type_.index(); + + if (this_index == 0) { + std::string type_name = std::get(type_).GetName(); + if (context.count(type_name) != 0) { // is abstract type + // context[type_name] = // TODO: actual_type.id_; ?? + // TODO: fixes + } + } + + error_handling::HandleGeneralError("Type::DeduceContext: not implemented"); + + if (this_index == type_index) { + switch (this_index) { + case 0: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + case 1: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + case 2: + return std::get(type_) == std::get(actual_type.type_); + case 3: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + case 4: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + case 5: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + case 6: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + case 7: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + case 8: + return std::get(type_).DeduceContext(std::get(actual_type.type_), + context); + default: + // error + break; + } + } + + return false; } std::optional Type::GetFieldType(const std::string& name, diff --git a/tests/test_code.lang b/tests/test_code.lang index 99810a0..2dcd6dd 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -280,8 +280,8 @@ exec main { var x = (for _ in 0--n do scan-int:) // $array[int] & 0 var k? = if n < 2 then n * 2 +. 3 in - , print-anything:[string] "n < 2" - , print-anything:[int] k + , print-anything:[string] "n < 2" + , print-anything:[int] k ; print-anything:[int] n