mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-06 06:58:46 +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();
|
return TypeCheckResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit TypeCheckResult(std::optional<TypeProxy> type) : type_(type) {}
|
explicit TypeCheckResult(nodes::TypeProxy type) : type_(type) {}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
@ -478,7 +478,7 @@ private:
|
||||||
TypeCheckResult() = default;
|
TypeCheckResult() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<TypeProxy> type_;
|
nodes::MaybeTypeProxy type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace nodes
|
} // namespace nodes
|
||||||
|
|
|
||||||
|
|
@ -186,8 +186,8 @@ private:
|
||||||
class ContextHolder {
|
class ContextHolder {
|
||||||
public:
|
public:
|
||||||
ContextHolder(State &state, const nodes::Node &node,
|
ContextHolder(State &state, const nodes::Node &node,
|
||||||
error_handling::ErrorLog &error_log)
|
error_handling::ErrorLog &error_log, nodes::MaybeTypeProxy* context_exit_type)
|
||||||
: state(state) {
|
: state_(state), context_exit_type_(context_exit_type) {
|
||||||
state.enter_context(node, error_log);
|
state.enter_context(node, error_log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,10 +197,17 @@ public:
|
||||||
ContextHolder &operator=(const ContextHolder &) = delete;
|
ContextHolder &operator=(const ContextHolder &) = delete;
|
||||||
ContextHolder &operator=(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:
|
private:
|
||||||
State &state;
|
State &state_;
|
||||||
|
nodes::MaybeTypeProxy* context_exit_type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes::TypeCheckResult type_same_to_expected(
|
nodes::TypeCheckResult type_same_to_expected(
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
// IN PROGRESS
|
// IN PROGRESS
|
||||||
|
|
||||||
|
// TODO: typecheck pass in all functions
|
||||||
|
|
||||||
namespace type_check {
|
namespace type_check {
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
|
|
@ -80,7 +82,6 @@ type_check_expression(const nodes::Expression &expression,
|
||||||
|
|
||||||
// --- flow control
|
// --- flow control
|
||||||
|
|
||||||
// TODO
|
|
||||||
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state,
|
State &state,
|
||||||
|
|
@ -98,6 +99,9 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||||
|
|
||||||
std::optional<nodes::TypeCheckResult> expression_result;
|
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) {
|
for (size_t i = 0; i < expression.cases_size(); ++i) {
|
||||||
const nodes::Match::Case *current_case = expression.get_case(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)
|
.expect_builtin(builtin::types::Type::BOOL, sources_manager)
|
||||||
.pass(value_result.is_invalid() ? nodes::MaybeTypeProxy{}
|
.pass(value_result.is_invalid() ? nodes::MaybeTypeProxy{}
|
||||||
: expression_result.value().get()));
|
: expression_result.value().get()));
|
||||||
// TODO: work with case
|
// TODO: use type modifiers ??
|
||||||
// TODO: use type modifiers
|
|
||||||
|
|
||||||
// ... ?? x ...
|
// ... ?? x ...
|
||||||
if (current_case->get_condition().has_value()) {
|
if (current_case->get_condition().has_value()) {
|
||||||
|
|
@ -121,6 +124,7 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||||
|
|
||||||
// ... -> x
|
// ... -> x
|
||||||
if (current_case->get_expression().has_value()) {
|
if (current_case->get_expression().has_value()) {
|
||||||
|
at_least_one_case_with_expression = true;
|
||||||
nodes::TypeCheckResult case_result = type_check_expression(
|
nodes::TypeCheckResult case_result = type_check_expression(
|
||||||
*current_case->get_condition().value(), sources_manager, state,
|
*current_case->get_condition().value(), sources_manager, state,
|
||||||
Arguments{}.expect(expression_result.has_value()
|
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);
|
expression_result = std::move(case_result);
|
||||||
}
|
}
|
||||||
} else {
|
} 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()) {
|
if (!expression_result.has_value()) {
|
||||||
expression_result = nodes::TypeCheckResult{
|
expression_result = nodes::TypeCheckResult{
|
||||||
sources_manager.get_type_storage()->primitive_type(
|
sources_manager.get_type_storage()->primitive_type(
|
||||||
|
|
@ -145,7 +157,7 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||||
expression_result.value().get()),
|
expression_result.value().get()),
|
||||||
arguments.get_expected(), expression,
|
arguments.get_expected(), expression,
|
||||||
*sources_manager.get_error_log());
|
*sources_manager.get_error_log());
|
||||||
} // IN PROGRESS
|
}
|
||||||
|
|
||||||
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
|
|
@ -186,11 +198,6 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
||||||
expression_result = nodes::TypeCheckResult::construct_invalid_result();
|
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(
|
return type_same_to_expected(sources_manager.get_type_storage()->add_array_of(
|
||||||
expression_result.value().get()),
|
expression_result.value().get()),
|
||||||
arguments.get_expected(), expression,
|
arguments.get_expected(), expression,
|
||||||
|
|
@ -203,8 +210,6 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
||||||
const Arguments &arguments) {
|
const Arguments &arguments) {
|
||||||
// TODO: ranges ??
|
// TODO: ranges ??
|
||||||
|
|
||||||
// std::optional<nodes::TypeCheckResult> condition_result;
|
|
||||||
|
|
||||||
std::optional<nodes::TypeCheckResult> interval_result;
|
std::optional<nodes::TypeCheckResult> interval_result;
|
||||||
|
|
||||||
std::optional<nodes::TypeCheckResult> variable_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
|
case nodes::Loop::LOOP: // infinity loop, no params
|
||||||
break;
|
break;
|
||||||
case nodes::Loop::WHILE:
|
case nodes::Loop::WHILE:
|
||||||
/*condition_result = */ type_check_expression(
|
type_check_expression(
|
||||||
*expression.get_condition().value(), sources_manager, state,
|
*expression.get_condition().value(), sources_manager, state,
|
||||||
Arguments{}.expect_builtin(builtin::types::Type::BOOL,
|
Arguments{}.expect_builtin(builtin::types::Type::BOOL,
|
||||||
sources_manager));
|
sources_manager));
|
||||||
|
|
@ -226,17 +231,6 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
||||||
// return condition_result.value();
|
// 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;
|
break;
|
||||||
case nodes::Loop::FOR:
|
case nodes::Loop::FOR:
|
||||||
// TODO: expect range ??
|
// TODO: expect range ??
|
||||||
|
|
@ -296,7 +290,7 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
|
||||||
*expression.get_expression(i),
|
*expression.get_expression(i),
|
||||||
"Elements in array should have same type",
|
"Elements in array should have same type",
|
||||||
error_handling::ErrorType::TYPE_CHECK));
|
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()),
|
last_expression_result.value().get()),
|
||||||
arguments.get_expected(), expression,
|
arguments.get_expected(), expression,
|
||||||
*sources_manager.get_error_log());
|
*sources_manager.get_error_log());
|
||||||
} // IN PROGRESS
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
nodes::TypeCheckResult type_check_block(const nodes::Container &expression,
|
nodes::TypeCheckResult type_check_block(const nodes::Container &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
State &state,
|
State &state,
|
||||||
const Arguments &arguments) {
|
const Arguments &arguments) {
|
||||||
ContextHolder context_holder(state, expression,
|
nodes::MaybeTypeProxy context_exit_type;
|
||||||
*sources_manager.get_error_log());
|
|
||||||
|
|
||||||
} // 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,
|
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
|
|
@ -333,11 +348,9 @@ nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||||
case nodes::Container::ARRAY:
|
case nodes::Container::ARRAY:
|
||||||
return type_check_array(expression, sources_manager, state, arguments);
|
return type_check_array(expression, sources_manager, state, arguments);
|
||||||
case nodes::Container::BLOCK:
|
case nodes::Container::BLOCK:
|
||||||
return type_check_block(expression, sources_manager, state,
|
return type_check_block(expression, sources_manager, state, arguments);
|
||||||
arguments); // TODO: check that expression brought
|
|
||||||
// type are same, -> brought_type
|
|
||||||
}
|
}
|
||||||
} // IN PROGRESS
|
}
|
||||||
|
|
||||||
// --- modifiers
|
// --- modifiers
|
||||||
|
|
||||||
|
|
@ -379,31 +392,33 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
||||||
arguments.get_expected(), expression, *sources_manager.get_error_log());
|
arguments.get_expected(), expression, *sources_manager.get_error_log());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
type_check_name_definition(const nodes::NameDefinition &expression,
|
type_check_name_definition(const nodes::NameDefinition &expression,
|
||||||
SourcesManager &sources_manager, State &state,
|
SourcesManager &sources_manager, State &state,
|
||||||
const Arguments &arguments) {
|
const Arguments &arguments) {
|
||||||
if (!arguments.get_expected().has_value()) {
|
if (!arguments.get_passed().has_value()) {
|
||||||
sources_manager.get_error_log()->add_error(
|
sources_manager.get_error_log()->add_error(
|
||||||
error_handling::ErrorLog::ErrorMessage(
|
error_handling::ErrorLog::ErrorMessage(
|
||||||
expression, "Can't deduce type of new variable from context",
|
expression, "Can't deduce type of new variable from context",
|
||||||
error_handling::ErrorType::TYPE_CHECK));
|
error_handling::ErrorType::TYPE_CHECK));
|
||||||
}
|
}
|
||||||
|
|
||||||
// defined name modifier should be -> (or contain -> ??)
|
// assigned type shold be one of <-, <>, -- (can't be ->)
|
||||||
// TODO: deal with ...|...|... modifiers
|
const auto variable_type = arguments.get_passed().value();
|
||||||
const auto expected_type = arguments.get_expected().value();
|
if (nodes::utils::modifier_contains_OUT(
|
||||||
if (!expected_type.get()->is_modifier(
|
variable_type.get()
|
||||||
nodes::Modifier::OUT)) { // TODO: utils::modifier_contains_OUT
|
->get_modifier())) { // TODO: utils::modifier_contains_OUT
|
||||||
sources_manager.get_error_log()->add_error(
|
sources_manager.get_error_log()->add_error(
|
||||||
error_handling::ErrorLog::ErrorMessage(
|
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));
|
error_handling::ErrorType::TYPE_CHECK));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove modifier ??
|
// variable accessible by reference by default ??
|
||||||
if (!state.insert_variable(*expression.get_name()->get(), expected_type,
|
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())) {
|
expression.get_modifier())) {
|
||||||
sources_manager.get_error_log()->add_error(
|
sources_manager.get_error_log()->add_error(
|
||||||
error_handling::ErrorLog::ErrorMessage(
|
error_handling::ErrorLog::ErrorMessage(
|
||||||
|
|
@ -411,8 +426,12 @@ type_check_name_definition(const nodes::NameDefinition &expression,
|
||||||
error_handling::ErrorType::TYPE_CHECK));
|
error_handling::ErrorType::TYPE_CHECK));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes::TypeCheckResult{expected_type};
|
// Return BOOL as any := / =: expression
|
||||||
} // IN PROGRESS
|
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,
|
nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
|
||||||
SourcesManager &sources_manager,
|
SourcesManager &sources_manager,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue