mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
typecheck for some expressions
This commit is contained in:
parent
070b08dba4
commit
61fa3a19a0
3 changed files with 78 additions and 52 deletions
|
|
@ -446,7 +446,7 @@ public:
|
|||
return TypeCheckResult();
|
||||
}
|
||||
|
||||
explicit TypeCheckResult(std::optional<TypeProxy> type) : type_(type) {}
|
||||
explicit TypeCheckResult(nodes::TypeProxy type) : type_(type) {}
|
||||
|
||||
//
|
||||
|
||||
|
|
@ -478,7 +478,7 @@ private:
|
|||
TypeCheckResult() = default;
|
||||
|
||||
private:
|
||||
std::optional<TypeProxy> type_;
|
||||
nodes::MaybeTypeProxy type_;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
|
|
|
|||
|
|
@ -186,8 +186,8 @@ private:
|
|||
class ContextHolder {
|
||||
public:
|
||||
ContextHolder(State &state, const nodes::Node &node,
|
||||
error_handling::ErrorLog &error_log)
|
||||
: state(state) {
|
||||
error_handling::ErrorLog &error_log, nodes::MaybeTypeProxy* context_exit_type)
|
||||
: state_(state), context_exit_type_(context_exit_type) {
|
||||
state.enter_context(node, error_log);
|
||||
}
|
||||
|
||||
|
|
@ -197,10 +197,17 @@ public:
|
|||
ContextHolder &operator=(const ContextHolder &) = delete;
|
||||
ContextHolder &operator=(ContextHolder &&) = delete;
|
||||
|
||||
~ContextHolder() { state.exit_context(); }
|
||||
~ContextHolder() {
|
||||
if (context_exit_type_) {
|
||||
*context_exit_type_ = state_.exit_context();
|
||||
} else {
|
||||
state_.exit_context();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
State &state;
|
||||
State &state_;
|
||||
nodes::MaybeTypeProxy* context_exit_type_;
|
||||
};
|
||||
|
||||
nodes::TypeCheckResult type_same_to_expected(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
// IN PROGRESS
|
||||
|
||||
// TODO: typecheck pass in all functions
|
||||
|
||||
namespace type_check {
|
||||
|
||||
nodes::TypeCheckResult
|
||||
|
|
@ -80,7 +82,6 @@ type_check_expression(const nodes::Expression &expression,
|
|||
|
||||
// --- flow control
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
|
|
@ -98,6 +99,9 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
|||
|
||||
std::optional<nodes::TypeCheckResult> expression_result;
|
||||
|
||||
bool at_least_one_case_with_expression = false;
|
||||
bool at_least_one_case_without_expression = false;
|
||||
|
||||
for (size_t i = 0; i < expression.cases_size(); ++i) {
|
||||
const nodes::Match::Case *current_case = expression.get_case(i);
|
||||
|
||||
|
|
@ -108,8 +112,7 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
|||
.expect_builtin(builtin::types::Type::BOOL, sources_manager)
|
||||
.pass(value_result.is_invalid() ? nodes::MaybeTypeProxy{}
|
||||
: expression_result.value().get()));
|
||||
// TODO: work with case
|
||||
// TODO: use type modifiers
|
||||
// TODO: use type modifiers ??
|
||||
|
||||
// ... ?? x ...
|
||||
if (current_case->get_condition().has_value()) {
|
||||
|
|
@ -121,6 +124,7 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
|||
|
||||
// ... -> x
|
||||
if (current_case->get_expression().has_value()) {
|
||||
at_least_one_case_with_expression = true;
|
||||
nodes::TypeCheckResult case_result = type_check_expression(
|
||||
*current_case->get_condition().value(), sources_manager, state,
|
||||
Arguments{}.expect(expression_result.has_value()
|
||||
|
|
@ -131,10 +135,18 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
|||
expression_result = std::move(case_result);
|
||||
}
|
||||
} else {
|
||||
// TODO: if there is expression_result, it should be returned in all cases
|
||||
at_least_one_case_without_expression = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (at_least_one_case_with_expression && at_least_one_case_without_expression) {
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "all cases should be with or without expression at the same time",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
expression_result = nodes::TypeCheckResult::construct_invalid_result();
|
||||
}
|
||||
|
||||
if (!expression_result.has_value()) {
|
||||
expression_result = nodes::TypeCheckResult{
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
|
|
@ -145,7 +157,7 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
|||
expression_result.value().get()),
|
||||
arguments.get_expected(), expression,
|
||||
*sources_manager.get_error_log());
|
||||
} // IN PROGRESS
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
||||
SourcesManager &sources_manager,
|
||||
|
|
@ -186,11 +198,6 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
|||
expression_result = nodes::TypeCheckResult::construct_invalid_result();
|
||||
}
|
||||
|
||||
// ??????????????????????????
|
||||
// TODO: extract function argument names
|
||||
// typecheck in statements ??
|
||||
// ??????????????????????????
|
||||
|
||||
return type_same_to_expected(sources_manager.get_type_storage()->add_array_of(
|
||||
expression_result.value().get()),
|
||||
arguments.get_expected(), expression,
|
||||
|
|
@ -203,8 +210,6 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
|||
const Arguments &arguments) {
|
||||
// TODO: ranges ??
|
||||
|
||||
// std::optional<nodes::TypeCheckResult> condition_result;
|
||||
|
||||
std::optional<nodes::TypeCheckResult> interval_result;
|
||||
|
||||
std::optional<nodes::TypeCheckResult> variable_result;
|
||||
|
|
@ -216,7 +221,7 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
|||
case nodes::Loop::LOOP: // infinity loop, no params
|
||||
break;
|
||||
case nodes::Loop::WHILE:
|
||||
/*condition_result = */ type_check_expression(
|
||||
type_check_expression(
|
||||
*expression.get_condition().value(), sources_manager, state,
|
||||
Arguments{}.expect_builtin(builtin::types::Type::BOOL,
|
||||
sources_manager));
|
||||
|
|
@ -226,17 +231,6 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
|||
// return condition_result.value();
|
||||
// }
|
||||
|
||||
// --- done in expect ---
|
||||
// if (!condition_result.value().get().get()->is_builtin(
|
||||
// builtin::types::Type::BOOL)) {
|
||||
// sources_manager.get_error_log()->add_error(
|
||||
// error_handling::ErrorLog::ErrorMessage(
|
||||
// *expression.get_condition().value(),
|
||||
// "While loop condition should have type Bool",
|
||||
// error_handling::ErrorType::TYPE_CHECK));
|
||||
// return nodes::TypeCheckResult::construct_invalid_result();
|
||||
// }
|
||||
|
||||
break;
|
||||
case nodes::Loop::FOR:
|
||||
// TODO: expect range ??
|
||||
|
|
@ -296,7 +290,7 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
|
|||
*expression.get_expression(i),
|
||||
"Elements in array should have same type",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
return nodes::TypeCheckResult::construct_invalid_result();
|
||||
// return nodes::TypeCheckResult::construct_invalid_result(); // max possible checks, so no return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -313,17 +307,38 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
|
|||
last_expression_result.value().get()),
|
||||
arguments.get_expected(), expression,
|
||||
*sources_manager.get_error_log());
|
||||
} // IN PROGRESS
|
||||
}
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult type_check_block(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
ContextHolder context_holder(state, expression,
|
||||
*sources_manager.get_error_log());
|
||||
nodes::MaybeTypeProxy context_exit_type;
|
||||
|
||||
} // IN PROGRESS
|
||||
{
|
||||
ContextHolder context_holder(state, expression,
|
||||
*sources_manager.get_error_log(),
|
||||
&context_exit_type); // TODO: is brought type returned
|
||||
|
||||
for (size_t i = 0; i < expression.expressions_size(); ++i) {
|
||||
// result types in block are discarded
|
||||
type_check_expression(*expression.get_expression(i), sources_manager,
|
||||
state, Arguments{});
|
||||
}
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult block_brought_type =
|
||||
context_exit_type.has_value()
|
||||
? nodes::TypeCheckResult(context_exit_type.value())
|
||||
: nodes::TypeCheckResult(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::UNIT));
|
||||
|
||||
return type_same_to_expected(sources_manager.get_type_storage()->add_array_of(
|
||||
block_brought_type.get()),
|
||||
arguments.get_expected(), expression,
|
||||
*sources_manager.get_error_log());
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager,
|
||||
|
|
@ -333,11 +348,9 @@ nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
|||
case nodes::Container::ARRAY:
|
||||
return type_check_array(expression, sources_manager, state, arguments);
|
||||
case nodes::Container::BLOCK:
|
||||
return type_check_block(expression, sources_manager, state,
|
||||
arguments); // TODO: check that expression brought
|
||||
// type are same, -> brought_type
|
||||
return type_check_block(expression, sources_manager, state, arguments);
|
||||
}
|
||||
} // IN PROGRESS
|
||||
}
|
||||
|
||||
// --- modifiers
|
||||
|
||||
|
|
@ -379,31 +392,33 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
|||
arguments.get_expected(), expression, *sources_manager.get_error_log());
|
||||
}
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult
|
||||
type_check_name_definition(const nodes::NameDefinition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {
|
||||
if (!arguments.get_expected().has_value()) {
|
||||
if (!arguments.get_passed().has_value()) {
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "Can't deduce type of new variable from context",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
// defined name modifier should be -> (or contain -> ??)
|
||||
// TODO: deal with ...|...|... modifiers
|
||||
const auto expected_type = arguments.get_expected().value();
|
||||
if (!expected_type.get()->is_modifier(
|
||||
nodes::Modifier::OUT)) { // TODO: utils::modifier_contains_OUT
|
||||
// assigned type shold be one of <-, <>, -- (can't be ->)
|
||||
const auto variable_type = arguments.get_passed().value();
|
||||
if (nodes::utils::modifier_contains_OUT(
|
||||
variable_type.get()
|
||||
->get_modifier())) { // TODO: utils::modifier_contains_OUT
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "Type of lambda function should be function",
|
||||
expression, "Variabla cant be asignet from out (->) value",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
// TODO: remove modifier ??
|
||||
if (!state.insert_variable(*expression.get_name()->get(), expected_type,
|
||||
// variable accessible by reference by default ??
|
||||
sources_manager.get_type_storage()->add_modification_of(variable_type,
|
||||
nodes::Modifier::REF);
|
||||
|
||||
if (!state.insert_variable(*expression.get_name()->get(), variable_type,
|
||||
expression.get_modifier())) {
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
|
|
@ -411,8 +426,12 @@ type_check_name_definition(const nodes::NameDefinition &expression,
|
|||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
return nodes::TypeCheckResult{expected_type};
|
||||
} // IN PROGRESS
|
||||
// Return BOOL as any := / =: expression
|
||||
return type_same_to_expected(
|
||||
sources_manager.get_type_storage()->primitive_type(
|
||||
builtin::types::Type::BOOL),
|
||||
arguments.get_expected(), expression, *sources_manager.get_error_log());
|
||||
}
|
||||
|
||||
nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue