From 00bf9705a91a9c54941d231613a107fad7525b19 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Fri, 13 Sep 2024 23:13:44 +0300 Subject: [PATCH] typecheck refactoring start --- lang/type_check/include/type_check_utils.hpp | 22 ++- lang/type_check/src/expression_type_check.cpp | 133 +++++++++--------- 2 files changed, 85 insertions(+), 70 deletions(-) diff --git a/lang/type_check/include/type_check_utils.hpp b/lang/type_check/include/type_check_utils.hpp index 8889aff..1f975d1 100644 --- a/lang/type_check/include/type_check_utils.hpp +++ b/lang/type_check/include/type_check_utils.hpp @@ -11,10 +11,11 @@ namespace type_check { -class ContextHolder; +template class ContextHolder; class State { - friend ContextHolder; + friend ContextHolder; + friend ContextHolder; public: struct VariableInfo { @@ -92,7 +93,7 @@ private: // TODO: argument for property is returned type should be merged // returns brought type, return type is merged with next context or with // brought type in last context - nodes::MaybeType exit_context() { + nodes::MaybeType ExitContext(nodes::Return::Kind result_kind) { Log::Context logc(log_, Log::Area::kTypeCheck); if (contexts_.empty()) { @@ -129,7 +130,14 @@ private: } } - return brought_type; + switch (result_kind) { + case nodes::Return::Kind::BRING: + return brought_type; + case nodes::Return::Kind::RETURN: + return returned_type; + } + + utils::unreachable(); } public: @@ -239,7 +247,7 @@ private: // -class ContextHolder { +template class ContextHolder { public: ContextHolder(State &state, const utils::Pos &pos, nodes::MaybeType *context_exit_type) @@ -255,9 +263,9 @@ public: ~ContextHolder() { if (context_exit_type_) { - *context_exit_type_ = state_.exit_context(); + *context_exit_type_ = state_.ExitContext(kind); } else { - state_.exit_context(); + state_.ExitContext(kind); } } diff --git a/lang/type_check/src/expression_type_check.cpp b/lang/type_check/src/expression_type_check.cpp index 600b1d5..241ecb6 100644 --- a/lang/type_check/src/expression_type_check.cpp +++ b/lang/type_check/src/expression_type_check.cpp @@ -148,18 +148,16 @@ Result CheckTask::operator()(const nodes::Condition &expr, return TypeCheckFromArgs(expr_result.value().Get(), args, current_pos); } +// NOTE: change to ranges in future Result CheckTask::operator()(const nodes::Loop &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); - // TODO: ranges ?? + // MaybeResult interval_result; - MaybeResult variable_result; - Result expression_result = Run(expr.expr, {expr.expr}); switch (expr.kind) { @@ -168,74 +166,67 @@ Result CheckTask::operator()(const nodes::Loop &expr, case nodes::Loop::WHILE: Run(expr.condition.value(), Args{expr.condition.value()}.ExpectBuiltin( builtin::Type::BOOL, executor)); - - // --- type check is independent from loop itself --- - // if (condition_result.value().is_invalid()) { - // return condition_result.value(); - // } - break; case nodes::Loop::FOR: - // TODO: expect range ?? interval_result = - Run(expr.interval.value(), Args{expr.interval.value()}.ExpectBuiltin( - builtin::Type::ARRAY, executor)); + Run(expr.interval.value(), + Args{expr.interval.value()}.ExpectBuiltin( + builtin::Type::ARRAY /* NOTE: range in future */, executor)); if (interval_result.value().is_invalid()) { - // --- type check is independent from loop itself --- - // return interval_result.value(); break; } - variable_result = - Run(expr.variable.value(), - Args{expr.variable.value()}.Expect( - interval_result.value().Get().get()->get_parameter_proxy(0))); + const auto range_elem_type = + interval_result.value().Get().get()->get_parameter_proxy(0); - // --- type check is independent from loop itself --- - // if (variable_result.value().is_invalid()) { - // return variable_result.value(); - // } + variable_result = Run(expr.variable.value(), + Args{expr.variable.value()}.Expect( + range_elem_type)); // TODO: or pass type ?? break; } - if (expression_result.is_invalid()) { // TODO: log invalid - return expression_result; + if (expression_result.is_invalid()) { + TypeCheckError("Invalid loop expression", PosOf(expr.expr)); + return Result::invalid(); } - // TODO: modifier checks ??, modifiers ?? - return TypeCheckFromArgs(state().add_array_of(expression_result.Get()), args, current_pos); -} // IN PROGRESS +} // --- containers Result CheckTask::CheckArray(const nodes::Container &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); + // + MaybeResult last_expr_result; for (const auto &elem_expr : expr.exprs) { - // elements should have same type, but type is not expected + // elements should have the same type, but no type expected auto expr_result = Run(elem_expr, {elem_expr}); - if (!last_expr_result.has_value()) { + if (expr_result.is_invalid()) { + TypeCheckError("Invalid array element", PosOf(args.current_id)); + continue; + } + + if (not last_expr_result.has_value()) { last_expr_result = expr_result; } else { if (last_expr_result.value().Get() != expr_result.Get()) { TypeCheckError("Elements in array should have same type", PosOf(args.current_id)); - // return TypeCheckResult::construct_invalid_result(); // max - // possible checks, so no return + // type is not modified to max possible type deduction } } } - if (!last_expr_result.has_value()) { + if (not last_expr_result.has_value()) { TypeCheckError("Array with zero elements", current_pos); return Result::invalid(); } @@ -248,15 +239,16 @@ Result CheckTask::CheckArray(const nodes::Container &expr, Result CheckTask::CheckBlock(const nodes::Container &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); + // + nodes::MaybeType context_exit_type; { - ContextHolder context_holder( - state(), current_pos, - &context_exit_type); // TODO: is brought type returned + // brought type returned + ContextHolder context_holder( + state(), current_pos, &context_exit_type); for (const auto &elem_expr : expr.exprs) { // result types in block are discarded @@ -269,8 +261,7 @@ Result CheckTask::CheckBlock(const nodes::Container &expr, ? Result(context_exit_type.value()) : Result(state().primitive(builtin::Type::UNIT)); - return TypeCheckFromArgs( - state().add_array_of(block_brought_type.Get()), args, current_pos); + return TypeCheckFromArgs(block_brought_type.Get(), args, current_pos); } Result CheckTask::operator()(const nodes::Container &expr, @@ -288,24 +279,25 @@ Result CheckTask::operator()(const nodes::Container &expr, Result CheckTask::operator()(const nodes::Return &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); + // + auto returned_result = Run(expr.expr, {expr.expr}); if (returned_result.is_invalid()) { - return returned_result; + return Result::invalid(); } switch (expr.kind) { case nodes::Return::BRING: - if (state().BringType(returned_result.Get())) { + if (not state().BringType(returned_result.Get())) { TypeCheckError("Different brought type to current one", current_pos); return Result::invalid(); } break; case nodes::Return::RETURN: - if (!state().ReturnType(returned_result.Get())) { + if (not state().ReturnType(returned_result.Get())) { TypeCheckError("Different returned type to current one", current_pos); return Result::invalid(); } @@ -316,6 +308,8 @@ Result CheckTask::operator()(const nodes::Return &expr, current_pos); } +// <------ NOTE: CHECK ENDED THERE + // TODO: warning if name is same to package prefix, function prefix, etc. ?? Result CheckTask::operator()(const nodes::NameDefinition &expr, @@ -351,46 +345,51 @@ CheckTask::operator()(const nodes::NameDefinition &expr, current_pos); } +// NOTE: CHECKED Result CheckTask::CheckArrayAccess(const nodes::Access &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); + // + auto index_result = Run(expr.index, Args{expr.index}.ExpectBuiltin(builtin::Type::INDEX, executor)); + // TODO: check expect for parametrized type without parametears auto value_result = Run(expr.value, Args{expr.value}.ExpectBuiltin(builtin::Type::ARRAY, executor)); if (index_result.is_invalid()) { - return index_result; + return Result::invalid(); } if (value_result.is_invalid()) { - return value_result; + return Result::invalid(); } - // TODO: modifier checks ?? - + // NOTE: 0 - type of array return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(0), args, current_pos); } +// NOTE: CHECKED Result CheckTask::CheckTupleAccess(const nodes::Access &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); + // + + // TODO: check expect for parametrized type without parametears auto value_result = Run(expr.value, Args{expr.value}.ExpectBuiltin(builtin::Type::TUPLE, executor)); if (value_result.is_invalid()) { - return value_result; + return Result::invalid(); } size_t index = *Ext(expr.index) @@ -398,12 +397,11 @@ Result CheckTask::CheckTupleAccess(const nodes::Access &expr, .get() // Index type .value(); - // TODO: modifier checks ?? - return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(index), args, current_pos); } +// NOTE: CHECKED Result CheckTask::operator()(const nodes::Access &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); @@ -416,12 +414,14 @@ Result CheckTask::operator()(const nodes::Access &expr, } } +// NOTE: CHECKED Result CheckTask::operator()(const nodes::LoopControl &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); + // + return TypeCheckFromArgs(state().primitive(builtin::Type::UNIT), args, current_pos); } @@ -429,28 +429,27 @@ Result CheckTask::operator()(const nodes::LoopControl &expr, Result CheckTask::operator()( const nodes::ModifierExpression &expr, const Args &args) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); - const auto current_pos = PosOf(args.current_id); + // + + // TODO: expext Optional or Result ?? auto modified_result = Run(expr.expr, {expr.expr}); if (modified_result.is_invalid()) { return Result::invalid(); } - if (nodes::utils::is_suffix_modifier( - expr.modifier)) { // optional, result - // '?' - open optional / result in -> - // (execute or not execute pattern - // matching expression) / (value / - // return) (TODO: alternative for bring) + if (nodes::utils::is_suffix_modifier(expr.modifier)) { // optional, result + + // '?' - open optional / result in -> (execute or not execute pattern + // matching expression) / (value / return) (TODO: alternative for bring) // '!' - open optional / result -> value / panic switch (modified_result.Get().get()->to_builtin()) { case builtin::Type::OPTIONAL: case builtin::Type::RESULT: - // TODO: how to unwrap external modifier ?? modified_result.Set(modified_result.Get().get()->get_parameter_proxy(0)); break; default: @@ -458,7 +457,9 @@ Result CheckTask::operator()( return Result::invalid(); } } else { - // TODO: check that modifier can be applied + // NOTE: other modifiers applied instead of current one + + // TODO: check thatmodification is possible modified_result.Set(state().add_modification_of( modified_result.Get(), expr.modifier)); } @@ -937,16 +938,22 @@ Result CheckTask::operator()(const nodes::Lambda &expr, return TypeCheckFromArgs(expected_type, args, current_pos); } // IN PROGRESS +// NOTE: CHECKED Result CheckTask::operator()(const nodes::Extra &, const Args &) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); + // + return Result(state().primitive(builtin::Type::UNIT)); } +// NOTE: CHECKED Result CheckTask::operator()(const nodes::EmptyLines &, const Args &) { Log::Context logc(executor.log(), Log::Area::kTypeCheck); + // + return Result(state().primitive(builtin::Type::UNIT)); }