Arguments: change structure, pass in match (v0)

This commit is contained in:
ProgramSnail 2024-02-12 23:43:43 +03:00
parent cf9311eb8b
commit 070b08dba4
2 changed files with 61 additions and 62 deletions

View file

@ -142,44 +142,41 @@ public:
class Arguments { class Arguments {
public: public:
static Arguments expect_builtin(builtin::types::Type type, Arguments() = default;
SourcesManager &sources_manager) {
return Arguments(sources_manager.get_type_storage()->primitive_type(type), Arguments expect_builtin(builtin::types::Type type,
{}); SourcesManager &sources_manager) const {
Arguments copy(*this);
copy.expected_type_ =
sources_manager.get_type_storage()->primitive_type(type);
} }
static Arguments nothing() { return Arguments({}, {}); } Arguments pass_builtin(builtin::types::Type type,
SourcesManager &sources_manager) const {
static Arguments expect(nodes::TypeProxy type) { return Arguments(type, {}); } Arguments copy(*this);
copy.passed_type_ =
static Arguments pass(nodes::TypeProxy type) { return Arguments({}, type); } sources_manager.get_type_storage()->primitive_type(type);
return copy;
static Arguments maybe_expect(nodes::MaybeTypeProxy type) {
return Arguments(type, {});
} }
static Arguments maybe_pass(nodes::MaybeTypeProxy type) { Arguments expect(nodes::MaybeTypeProxy type) const {
return Arguments({}, type); Arguments copy(*this);
copy.expected_type_ = type;
return copy;
} }
static Arguments expect_and_pass(nodes::TypeProxy expected_type, Arguments pass(nodes::MaybeTypeProxy type) const {
nodes::TypeProxy passed_type) { Arguments copy(*this);
return Arguments(expected_type, passed_type); copy.passed_type_ = type;
} return copy;
static Arguments maybe_expect_and_pass(nodes::MaybeTypeProxy expected_type,
nodes::MaybeTypeProxy passed_type) {
return Arguments(expected_type, passed_type);
} }
nodes::MaybeTypeProxy get_expected() const { return expected_type_; }; nodes::MaybeTypeProxy get_expected() const { return expected_type_; };
nodes::MaybeTypeProxy get_passed() const { return passed_type_; }; nodes::MaybeTypeProxy get_passed() const { return passed_type_; };
private: // TODO: add check, that there is no passed type for some nodes ??
explicit Arguments(nodes::MaybeTypeProxy expected_type = {}, // TODO: arguments builder ??
nodes::MaybeTypeProxy passed_type = {})
: expected_type_(expected_type), passed_type_(passed_type) {}
private: private:
nodes::MaybeTypeProxy expected_type_ = {}; nodes::MaybeTypeProxy expected_type_ = {};

View file

@ -86,8 +86,9 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
State &state, State &state,
const Arguments &arguments) { const Arguments &arguments) {
nodes::TypeCheckResult value_result = type_check_expression( nodes::TypeCheckResult value_result = type_check_expression(
*expression.get_value(), sources_manager, state, Arguments::nothing()); *expression.get_value(), sources_manager, state, Arguments{});
// x :=/=: ...
if (value_result.is_invalid()) { if (value_result.is_invalid()) {
sources_manager.get_error_log()->add_error( sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage( error_handling::ErrorLog::ErrorMessage(
@ -100,25 +101,29 @@ nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
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);
// :=/=: x ...
type_check_expression( type_check_expression(
*current_case->get_value(), sources_manager, state, *current_case->get_value(), sources_manager, state,
Arguments::maybe_expect(value_result.is_invalid() Arguments{}
? nodes::MaybeTypeProxy{} .expect_builtin(builtin::types::Type::BOOL, sources_manager)
.pass(value_result.is_invalid() ? nodes::MaybeTypeProxy{}
: expression_result.value().get())); : expression_result.value().get()));
// TODO: work with case // TODO: work with case
// TODO: use type modifiers // TODO: use type modifiers
// ... ?? x ...
if (current_case->get_condition().has_value()) { if (current_case->get_condition().has_value()) {
type_check_expression(*current_case->get_condition().value(), type_check_expression(*current_case->get_condition().value(),
sources_manager, state, sources_manager, state,
Arguments::expect_builtin( Arguments{}.expect_builtin(
builtin::types::Type::BOOL, sources_manager)); builtin::types::Type::BOOL, sources_manager));
} }
// ... -> x
if (current_case->get_expression().has_value()) { if (current_case->get_expression().has_value()) {
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::maybe_expect(expression_result.has_value() Arguments{}.expect(expression_result.has_value()
? expression_result.value().get() ? expression_result.value().get()
: nodes::MaybeTypeProxy{})); : nodes::MaybeTypeProxy{}));
@ -150,13 +155,13 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
std::optional<nodes::TypeCheckResult> expression_result; std::optional<nodes::TypeCheckResult> expression_result;
for (size_t i = 0; i < expression.cases_size(); ++i) { for (size_t i = 0; i < expression.cases_size(); ++i) {
type_check_expression( type_check_expression(*expression.get_case(i).first, sources_manager, state,
*expression.get_case(i).first, sources_manager, state, Arguments{}.expect_builtin(builtin::types::Type::BOOL,
Arguments::expect_builtin(builtin::types::Type::BOOL, sources_manager)); sources_manager));
nodes::TypeCheckResult case_result = type_check_expression( nodes::TypeCheckResult case_result = type_check_expression(
*expression.get_case(i).first, sources_manager, state, *expression.get_case(i).first, sources_manager, state,
Arguments::maybe_expect(expression_result.has_value() Arguments{}.expect(expression_result.has_value()
? expression_result.value().get() ? expression_result.value().get()
: nodes::MaybeTypeProxy{})); : nodes::MaybeTypeProxy{}));
@ -168,7 +173,7 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
if (expression.get_else_case().has_value()) { if (expression.get_else_case().has_value()) {
type_check_expression( type_check_expression(
*expression.get_else_case().value(), sources_manager, state, *expression.get_else_case().value(), sources_manager, state,
Arguments::maybe_expect(expression_result.has_value() Arguments{}.expect(expression_result.has_value()
? expression_result.value().get() ? expression_result.value().get()
: nodes::MaybeTypeProxy{})); : nodes::MaybeTypeProxy{}));
} }
@ -204,9 +209,8 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
std::optional<nodes::TypeCheckResult> variable_result; std::optional<nodes::TypeCheckResult> variable_result;
nodes::TypeCheckResult expression_result = nodes::TypeCheckResult expression_result = type_check_expression(
type_check_expression(*expression.get_expression(), sources_manager, *expression.get_expression(), sources_manager, state, Arguments{});
state, Arguments::nothing());
switch (expression.get_type()) { switch (expression.get_type()) {
case nodes::Loop::LOOP: // infinity loop, no params case nodes::Loop::LOOP: // infinity loop, no params
@ -214,7 +218,8 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
case nodes::Loop::WHILE: case nodes::Loop::WHILE:
/*condition_result = */ type_check_expression( /*condition_result = */ type_check_expression(
*expression.get_condition().value(), sources_manager, state, *expression.get_condition().value(), sources_manager, state,
Arguments::expect_builtin(builtin::types::Type::BOOL, sources_manager)); Arguments{}.expect_builtin(builtin::types::Type::BOOL,
sources_manager));
// --- type check is independent from loop itself --- // --- type check is independent from loop itself ---
// if (condition_result.value().is_invalid()) { // if (condition_result.value().is_invalid()) {
@ -237,7 +242,7 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
// TODO: expect range ?? // TODO: expect range ??
interval_result = type_check_expression( interval_result = type_check_expression(
*expression.get_interval().value(), sources_manager, state, *expression.get_interval().value(), sources_manager, state,
Arguments::expect_builtin(builtin::types::Type::ARRAY, Arguments{}.expect_builtin(builtin::types::Type::ARRAY,
sources_manager)); sources_manager));
if (interval_result.value().is_invalid()) { if (interval_result.value().is_invalid()) {
@ -248,7 +253,7 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
variable_result = type_check_expression( variable_result = type_check_expression(
*expression.get_variable().value(), sources_manager, state, *expression.get_variable().value(), sources_manager, state,
Arguments::expect( Arguments{}.expect(
interval_result.value().get().get()->get_parameter_proxy(0))); interval_result.value().get().get()->get_parameter_proxy(0)));
// --- type check is independent from loop itself --- // --- type check is independent from loop itself ---
@ -279,9 +284,8 @@ nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
for (size_t i = 0; i < expression.expressions_size(); ++i) { for (size_t i = 0; i < expression.expressions_size(); ++i) {
// elements should have same type, but type is not expected // elements should have same type, but type is not expected
auto expression_result = auto expression_result = type_check_expression(
type_check_expression(*expression.get_expression(i), sources_manager, *expression.get_expression(i), sources_manager, state, Arguments{});
state, Arguments::nothing());
if (!last_expression_result.has_value()) { if (!last_expression_result.has_value()) {
last_expression_result = expression_result; last_expression_result = expression_result;
@ -341,9 +345,8 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
SourcesManager &sources_manager, SourcesManager &sources_manager,
State &state, State &state,
const Arguments &arguments) { const Arguments &arguments) {
auto returned_result = auto returned_result = type_check_expression(
type_check_expression(*expression.get_expression(), sources_manager, *expression.get_expression(), sources_manager, state, Arguments{});
state, Arguments::nothing());
if (returned_result.is_invalid()) { if (returned_result.is_invalid()) {
return returned_result; return returned_result;
@ -418,11 +421,11 @@ nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
auto index_result = type_check_expression( auto index_result = type_check_expression(
*expression.get_index(), sources_manager, state, *expression.get_index(), sources_manager, state,
Arguments::expect_builtin(builtin::types::Type::INDEX, sources_manager)); Arguments{}.expect_builtin(builtin::types::Type::INDEX, sources_manager));
auto value_result = type_check_expression( auto value_result = type_check_expression(
*expression.get_value(), sources_manager, state, *expression.get_value(), sources_manager, state,
Arguments::expect_builtin(builtin::types::Type::ARRAY, sources_manager)); Arguments{}.expect_builtin(builtin::types::Type::ARRAY, sources_manager));
if (index_result.is_invalid()) { if (index_result.is_invalid()) {
return index_result; return index_result;
@ -445,7 +448,7 @@ nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression,
const Arguments &arguments) { const Arguments &arguments) {
auto value_result = type_check_expression( auto value_result = type_check_expression(
*expression.get_value(), sources_manager, state, *expression.get_value(), sources_manager, state,
Arguments::expect_builtin(builtin::types::Type::TUPLE, sources_manager)); Arguments{}.expect_builtin(builtin::types::Type::TUPLE, sources_manager));
if (value_result.is_invalid()) { if (value_result.is_invalid()) {
return value_result; return value_result;
@ -492,9 +495,8 @@ nodes::TypeCheckResult
type_check_modifier_expression(const nodes::ModifierExpression &expression, type_check_modifier_expression(const nodes::ModifierExpression &expression,
SourcesManager &sources_manager, State &state, SourcesManager &sources_manager, State &state,
const Arguments &arguments) { const Arguments &arguments) {
auto modified_result = auto modified_result = type_check_expression(
type_check_expression(*expression.get_expression(), sources_manager, *expression.get_expression(), sources_manager, state, Arguments{});
state, Arguments::nothing());
if (modified_result.is_invalid()) { if (modified_result.is_invalid()) {
return nodes::TypeCheckResult::construct_invalid_result(); return nodes::TypeCheckResult::construct_invalid_result();