diff --git a/lang/nodes/include/type_nodes.hpp b/lang/nodes/include/type_nodes.hpp index 9579c69..198a952 100644 --- a/lang/nodes/include/type_nodes.hpp +++ b/lang/nodes/include/type_nodes.hpp @@ -176,11 +176,9 @@ public: kCheckLeftIsSubmode, // only check is performed }; - // TODO: next iteration of type check - bool Unify(Type left, Type right, UnifyModePolicy policy); + bool Unify(Type left_id, Type right_id, UnifyModePolicy policy); - bool Resolve(Type generic, - const TypeData &replacement /* TODO , Mode mode = {}*/); + bool Resolve(Type generic, const TypeData &replacement, Modifier modifier); // TODO: needed ?? diff --git a/lang/nodes/src/type_nodes.cpp b/lang/nodes/src/type_nodes.cpp index bc89806..b0ff2af 100644 --- a/lang/nodes/src/type_nodes.cpp +++ b/lang/nodes/src/type_nodes.cpp @@ -222,80 +222,98 @@ nodes::Type TypeStorage::AddModificationOf(Type type, Modifier modifier) { // TODO -bool TypeStorage::Unify(Type /*left*/, Type /*right*/, - UnifyModePolicy /*policy*/) { - // Type &left = left_id.get(); - // Type &right = right_id.get(); +// TODO: FIXME: Handle "equal to builtin type without params" in some way +// TODO: return Optional instead ?? +bool TypeStorage::Unify(Type left_id, Type right_id, UnifyModePolicy policy) { + TypeData &left = left_id.get(); + TypeData &right = right_id.get(); - // switch (policy) { - // case UnifyModePolicy::Ignore: - // break; - // case UnifyModePolicy::ApplyStrongest: - // left.mode = Mode::choose_min(left.mode, right.mode); - // right.mode = left.mode; - // break; - // case UnifyModePolicy::CheckLeftIsSubmode: - // if (not left.mode.is_submode(right.mode)) { - // return false; - // } - // break; - // } + // --- modifiers - // if (const auto *left_generic = get_if(&left.type); - // left_generic != nullptr) { - // // TODO: check if other type contains generic - // std::clog << "left is resolved with policy <" << - // static_cast(policy) << ">\n"; resolve(*left_generic, right, - // left.mode); return true; - // } + switch (policy) { + case UnifyModePolicy::kIgnore: + break; + case UnifyModePolicy::kApplyStrongest: + left.modifier = utils::ChooseMinModifier(left.modifier, right.modifier); + right.modifier = left.modifier; + break; + case UnifyModePolicy::kCheckLeftIsSubmode: + if (not utils::IsSubmodifier(left.modifier, right.modifier)) { + return false; + } + break; + } - // if (const auto *right_generic = get_if(&right.type); - // right_generic != nullptr) { - // // TODO: check if other type contains generic - // std::clog << "right is resolved with policy <" << - // static_cast(policy) << ">\n"; resolve(*right_generic, left, - // right.mode); return true; - // } + // --- generics - // if (left.type.index() != right.type.index()) { - // return false; - // } + // TODO: check if other type contains this generic (prevent inf loops ??) - // if (holds_alternative(left.type)) { - // const auto &left_types = std::get(left.type).types; - // const auto &right_types = std::get(right.type).types; + if (left.IsGeneric()) { + // TODO: use Log + // std::clog << "left is resolved with policy <" << + // static_cast(policy) + // << ">\n"; + Resolve(left_id, right, left.modifier); + return true; + } - // if (left_types.size() != right_types.size()) { - // return false; - // } + if (right.IsGeneric()) { + // TODO: use Log + // std::clog << "right is resolved with policy <" + // << static_cast(policy) << ">\n"; + Resolve(right_id, left, right.modifier); + return true; + } - // bool all_unify_passed = true; - // for (size_t i = 0; i < left_types.size(); ++i) { - // if (not unify(left_types[i], right_types[i], policy)) { - // all_unify_passed = false; - // } - // } + // --- name - // return all_unify_passed; - // } + if (left.name != right.name) { + return false; + } - // TODO - // return true; - throw std::exception(); -} + // --- annotations -bool TypeStorage::Resolve( - Type generic, const TypeData &replacement /* TODO , Mode mode = {}*/) { - error_handling::ensure(generic.get().IsGeneric(), "Type should be generic"); - error_handling::ensure(generic.get().IsGeneric(), "Type should be generic"); - for (auto &type : storage_) { - if (type.IsGeneric() && type.name == generic.get().name) { - type = replacement; - // type.mode = mode; + if (left.HasAnnotation() and right.HasAnnotation() and + left.annotation != right.annotation) { + return false; + } + + if (not left.HasAnnotation()) { + left.annotation = right.annotation; + } + + if (not right.HasAnnotation()) { + right.annotation = left.annotation; + } + + // --- params + + if (left.params.size() != right.params.size()) { + return false; + } + + bool all_unifications_passed = true; + for (size_t i = 0; i < left.params.size(); ++i) { + if (not Unify(left.params[i], right.params[i], policy)) { + all_unifications_passed = false; + } + } + + return all_unifications_passed; +} + +bool TypeStorage::Resolve(Type generic, const TypeData &replacement, + Modifier modifier) { + // TODO: use Log + // error_handling::ensure(generic.get().IsGeneric(), "Type should be + // generic"); error_handling::ensure(generic.get().IsGeneric(), "Type should + // be generic"); + for (auto &type : storage_) { + if (type.IsGeneric() and type.name == generic.get().name) { + type = replacement; + type.modifier = modifier; } } - // TODO - throw std::exception(); } //