part of type checker, type heck result type

This commit is contained in:
ProgramSnail 2023-08-12 14:36:00 +03:00
parent 48c9e200be
commit 17ff590048
13 changed files with 1022 additions and 321 deletions

View file

@ -25,111 +25,130 @@ build_expression(parser::ParseTree::Node parser_node,
// --- flow control
case tokens::Type::MATCH:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_match(parser_node, expression_storage, type_storage), is_scoped));
case tokens::Type::CONDITION:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_condition(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::LOOP:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_loop(parser_node, expression_storage, type_storage), is_scoped));
// --- operators
case tokens::Type::COMMA_EXPRESSION:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_comma_expression(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::OPERATOR_EXPRESSION:
return expression_storage.add_expression(
nodes::Expression(build_operator_expression(
nodes::Expression(build_node(parser_node),
build_operator_expression(
parser_node, expression_storage, type_storage),
is_scoped));
// --- containers
case tokens::Type::BLOCK:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_block(parser_node, expression_storage, type_storage), is_scoped));
case tokens::Type::ARRAY:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_array(parser_node, expression_storage, type_storage), is_scoped));
// --- modifiers
case tokens::Type::RETURN:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_return(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::NAME_DEFINITION:
return expression_storage.add_expression(
nodes::Expression(build_name_definition(parser_node), is_scoped));
nodes::Expression(build_node(parser_node),
build_name_definition(parser_node), is_scoped));
case tokens::Type::ARRAY_ACCESS:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_array_access(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::TUPLE_ACCESS:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_tuple_access(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::LOOP_CONTROL:
return expression_storage.add_expression(
nodes::Expression(build_loop_control(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_loop_control(parser_node), is_scoped));
case tokens::Type::REFERENCE_EXPRESSION:
return expression_storage.add_expression(
nodes::Expression(build_reference_expression(
nodes::Expression(build_node(parser_node),
build_reference_expression(
parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::SUFFIX_EXPRESSION:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_suffix_expression(parser_node, expression_storage, type_storage),
is_scoped));
// --- other
case tokens::Type::NAME_EXPRESSION:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_name_expression(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::ARGUMENT_NAME_IDENTIFIER:
case tokens::Type::SIMPLE_NAME_IDENTIFIER:
case tokens::Type::PLACEHOLDER:
return expression_storage.add_expression(
nodes::Expression(nodes::NameExpression(build_node(parser_node),
nodes::Expression(build_node(parser_node),
nodes::NameExpression(build_node(parser_node),
build_identifier(parser_node)),
is_scoped));
case tokens::Type::CONSTRUCTOR:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_constructor(parser_node, expression_storage, type_storage),
is_scoped));
case tokens::Type::LAMBDA:
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node),
build_lambda(parser_node, expression_storage, type_storage),
is_scoped));
// --- literals
case tokens::Type::FLOAT_NUMBER_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_float_number_literal(parser_node), is_scoped));
nodes::Expression(build_node(parser_node),
build_float_number_literal(parser_node), is_scoped));
case tokens::Type::NUMBER_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_number_literal(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_number_literal(parser_node), is_scoped));
case tokens::Type::STRING_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_string_literal(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_string_literal(parser_node), is_scoped));
case tokens::Type::CHAR_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_char_literal(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_char_literal(parser_node), is_scoped));
case tokens::Type::BOOL_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_bool_literal(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_bool_literal(parser_node), is_scoped));
case tokens::Type::UNIT_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_unit_literal(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_unit_literal(parser_node), is_scoped));
case tokens::Type::NULL_LITERAL:
return expression_storage.add_expression(
nodes::Expression(build_null_literal(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_null_literal(parser_node), is_scoped));
case tokens::Type::EXTRA:
return expression_storage.add_expression(
nodes::Expression(build_extra(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_extra(parser_node), is_scoped));
case tokens::Type::EMPTY_LINES:
return expression_storage.add_expression(
nodes::Expression(build_empty_lines(parser_node), is_scoped));
return expression_storage.add_expression(nodes::Expression(
build_node(parser_node), build_empty_lines(parser_node), is_scoped));
default:
error_handling::handle_parsing_error("Unexprected expression node type",
parser_node);
}
error_handling::handle_general_error("Unreachable");
exit(1); // unreachable
}
@ -392,6 +411,7 @@ nodes::Access build_tuple_access(parser::ParseTree::Node parser_node,
build_expression(parser_node.nth_named_child(0), expression_storage,
type_storage),
expression_storage.add_expression(nodes::Expression(
build_node(parser_node.nth_named_child(1)),
build_number_literal(parser_node.nth_named_child(1)), false)));
}

View file

@ -53,7 +53,8 @@ build_statement(parser::ParseTree::Node parser_node,
switch (type) {
case tokens::Type::IMPORT:
statement = nodes::Statement(build_import(parser_node));
statement =
nodes::Statement(build_node(parser_node), build_import(parser_node));
statement_name = *statement.value()
.get<nodes::Import>()
.value()
@ -62,7 +63,8 @@ build_statement(parser::ParseTree::Node parser_node,
break;
case tokens::Type::TYPE_DEFINITION:
statement =
nodes::Statement(build_type_definition(parser_node, type_storage));
nodes::Statement(build_node(parser_node),
build_type_definition(parser_node, type_storage));
last_defined_type_name =
*statement.value().get<nodes::TypeDefinition>().value()->get_name();
statement_name = *statement.value()
@ -72,8 +74,10 @@ build_statement(parser::ParseTree::Node parser_node,
->get();
break;
case tokens::Type::FUNCTION_DEFINITION:
statement = nodes::Statement(build_function_definition(
parser_node, last_defined_type_name, expression_storage, type_storage));
statement = nodes::Statement(
build_node(parser_node),
build_function_definition(parser_node, last_defined_type_name,
expression_storage, type_storage));
statement_name = *statement.value()
.get<nodes::FunctionDefinition>()
.value()
@ -81,10 +85,12 @@ build_statement(parser::ParseTree::Node parser_node,
->get();
break;
case tokens::Type::EXTRA:
statement = nodes::Statement(build_extra(parser_node));
statement =
nodes::Statement(build_node(parser_node), build_extra(parser_node));
break;
case tokens::Type::EMPTY_LINES:
statement = nodes::Statement(build_empty_lines(parser_node));
statement = nodes::Statement(build_node(parser_node),
build_empty_lines(parser_node));
break;
default:
error_handling::handle_parsing_error("Unexprected statement node type",
@ -315,7 +321,7 @@ nodes::FunctionDefinition build_function_definition(
return_modifier = build_modifier(current_node);
// only optional, result allowed
if (!utils::is_suffix_modifier(return_modifier)) {
if (!nodes::utils::is_suffix_modifier(return_modifier)) {
return_modifier = nodes::Modifier::NONE;
}
}
@ -341,7 +347,7 @@ nodes::FunctionDefinition build_function_definition(
last_before_modifier = build_modifier(maybe_reference_node);
// only out, in, ref allowed
if (utils::is_suffix_modifier(last_before_modifier)) {
if (nodes::utils::is_suffix_modifier(last_before_modifier)) {
last_before_modifier = nodes::Modifier::NONE;
}
}
@ -357,7 +363,7 @@ nodes::FunctionDefinition build_function_definition(
last_after_modifier = build_modifier(maybe_reference_node);
// only optional, result allowed
if (!utils::is_suffix_modifier(last_after_modifier)) {
if (!nodes::utils::is_suffix_modifier(last_after_modifier)) {
last_after_modifier = nodes::Modifier::NONE;
}
}

View file

@ -12,7 +12,7 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage) {
tokens::Type type = tokens::string_to_type(parser_node.get_type());
// TODO
// TODO: for better formatted printing
// auto maybe_parenthesis = parser_node.previous_sibling();
// bool is_scoped =
// (!maybe_parenthesis.is_null() && !maybe_parenthesis.is_named() &&
@ -39,10 +39,9 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parser_node,
exit(1); // unreachable
}
nodes::TypeProxy
build_buildin_container_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage,
const std::string &type_name) {
nodes::TypeProxy build_container_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage,
builtin::types::Type container) {
std::vector<nodes::TypeProxy> parameters;
std::optional<std::string> current_annotation;
@ -61,39 +60,31 @@ build_buildin_container_type(parser::ParseTree::Node parser_node,
current_node = current_node.next_named_sibling();
}
return type_storage.add_type(
nodes::Type(build_node(parser_node),
nodes::Identifier(build_node(parser_node),
nodes::Identifier::SIMPLE_TYPE, type_name),
std::move(parameters), false));
return type_storage.add_container_of(std::move(parameters), container,
build_node(parser_node));
}
// '|'? annotation? type ('|' annotation? type)+
nodes::TypeProxy build_variant_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage) {
return build_buildin_container_type(parser_node, type_storage,
builtin::VARIANT_IDENTIFIER);
return build_container_type(parser_node, type_storage,
builtin::types::Type::VARIANT);
}
// '&'? annotation? type ('&' annotation? type)+
nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage) {
return build_buildin_container_type(parser_node, type_storage,
builtin::TUPLE_IDENTIFIER);
return build_container_type(parser_node, type_storage,
builtin::types::Type::TUPLE);
}
// '[[' type ']]'
nodes::TypeProxy build_array_type(parser::ParseTree::Node parser_node,
nodes::TypeStorage &type_storage) {
std::vector<nodes::TypeProxy> parameters;
parameters.push_back(
build_type(parser_node.nth_named_child(0), type_storage));
return type_storage.add_type(nodes::Type(
build_node(parser_node),
nodes::Identifier(build_node(parser_node), nodes::Identifier::SIMPLE_TYPE,
builtin::ARRAY_IDENTIFIER),
std::move(parameters), false));
return type_storage.add_array_of(
build_type(parser_node.nth_named_child(0), type_storage),
build_node(parser_node));
}
// '^' type
@ -119,10 +110,10 @@ nodes::TypeProxy build_modified_type(parser::ParseTree::Node parser_node,
switch (modifier) {
case nodes::Modifier::OPTIONAL:
identifier = builtin::OPTIONAL_IDENTIFIER;
identifier = builtin::types::OPTIONAL_IDENTIFIER;
break;
case nodes::Modifier::RESULT:
identifier = builtin::RESULT_IDENTIFIER;
identifier = builtin::types::RESULT_IDENTIFIER;
break;
default:
error_handling::handle_parsing_error(
@ -131,8 +122,7 @@ nodes::TypeProxy build_modified_type(parser::ParseTree::Node parser_node,
}
return type_storage.add_type(
nodes::Type(build_node(parser_node),
nodes::Identifier(build_node(parser_node),
nodes::Type(nodes::Identifier(build_node(parser_node),
nodes::Identifier::SIMPLE_TYPE, identifier),
std::move(parameters), false));
}
@ -150,9 +140,8 @@ nodes::TypeProxy build_simple_type(parser::ParseTree::Node parser_node,
current_node = current_node.next_named_sibling();
}
return type_storage.add_type(nodes::Type(build_node(parser_node),
build_identifier(name_node),
std::move(parameters), false));
return type_storage.add_type(
nodes::Type(build_identifier(name_node), std::move(parameters), false));
}
} // namespace builders

View file

@ -1,69 +1,431 @@
#include "expression_type_check.hpp"
#include "basic_nodes.hpp"
#include "builtin_types.hpp"
#include "error_log.hpp"
#include "sources_manager.hpp"
#include "type_nodes.hpp"
#include "utils.hpp"
// IN PROGRESS
namespace type_check {
void type_check_expression(const nodes::Expression &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
nodes::TypeCheckResult
type_check_expression(const nodes::Expression &expression,
SourcesManager &sources_manager, State &state) {
switch (expression.get_any()->index()) {
// --- flow control
case 0: // Match
return type_check_match(*expression.get<nodes::Match>().value(),
sources_manager, state);
case 1: // Condition
return type_check_condition(*expression.get<nodes::Condition>().value(),
sources_manager, state);
case 2: // Loop
return type_check_loop(*expression.get<nodes::Loop>().value(),
sources_manager, state);
// --- containers
case 3: // Container
return type_check_container(*expression.get<nodes::Container>().value(),
sources_manager, state);
// --- modifiers
case 4: // Return
return type_check_return(*expression.get<nodes::Return>().value(),
sources_manager, state);
case 5: // NameDefinition
return type_check_name_definition(
*expression.get<nodes::NameDefinition>().value(), sources_manager,
state);
case 6: // Access
return type_check_access(*expression.get<nodes::Access>().value(),
sources_manager, state);
case 7: // LoopControl
return type_check_loop_control(
*expression.get<nodes::LoopControl>().value(), sources_manager, state);
case 8: // ModifierExpression
return type_check_modifier_expression(
*expression.get<nodes::ModifierExpression>().value(), sources_manager,
state);
// --- other
case 9: // NameExpression
return type_check_name_expression(
*expression.get<nodes::NameExpression>().value(), sources_manager,
state);
case 10: // Constructor
return type_check_constructor(*expression.get<nodes::Constructor>().value(),
sources_manager, state);
case 11: // Lambda
return type_check_lambda(*expression.get<nodes::Lambda>().value(),
sources_manager, state);
// --- literal
case 12: // Literal
// TODO
return type_check_literal(*expression.get<nodes::Literal>().value(),
sources_manager, state);
// --- empty lines
case 13: // Extra
return nodes::TypeCheckResult(
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::UNIT));
case 14: // EmptyLines
return nodes::TypeCheckResult(
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::UNIT));
}
}
// --- flow control
void type_check_case(const nodes::Match::Case &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
// TODO
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
SourcesManager &sources_manager,
State &state) {} // IN PROGRESS
void type_check_match(const nodes::Match &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
// TODO
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
SourcesManager &sources_manager,
State &state) {} // IN PROGRESS
void type_check_condition(const nodes::Condition &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
SourcesManager &sources_manager,
State &state) {
// TODO: ranges ??
void type_check_loop(const nodes::Loop &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
std::optional<nodes::TypeCheckResult> condition_result;
std::optional<nodes::TypeCheckResult> variable_result;
std::optional<nodes::TypeCheckResult> interval_result;
nodes::TypeCheckResult expression_result = type_check_expression(
*expression.get_expression(), sources_manager, state);
switch (expression.get_type()) {
case nodes::Loop::LOOP:
break;
case nodes::Loop::WHILE:
condition_result = type_check_expression(
*expression.get_condition().value(), sources_manager, state);
if (condition_result.value().is_invalid()) {
return condition_result.value();
}
if (condition_result.value().get().get_type()->to_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:
variable_result = type_check_expression(*expression.get_variable().value(),
sources_manager, state);
interval_result = type_check_expression(*expression.get_interval().value(),
sources_manager, state);
if (variable_result.value().is_invalid()) {
return variable_result.value();
}
if (interval_result.value().is_invalid()) {
return interval_result.value();
}
// // TODO ??
// if (variable_result.value().get().get_type()->to_builtin() !=
// builtin::types::Type::BOOL) {
// sources_manager.get_error_log()->add_error(
// error_handling::ErrorLog::ErrorMessage(
// *expression.get_condition().value(),
// "For loop variable should have type ...",
// error_handling::ErrorType::TYPE_CHECK));
// return nodes::TypeCheckResult::construct_invalid_result();
// }
// TODO: ranges ??
if (condition_result.value().get().get_type()->to_builtin() !=
builtin::types::Type::ARRAY) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
*expression.get_condition().value(),
"For loop interval should have type Array",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
break;
}
if (expression_result.is_invalid()) {
return expression_result;
}
// TODO: modifier checks ??
return nodes::TypeCheckResult(
nodes::ModifiedTypeProxy(sources_manager.get_type_storage()->add_array_of(
expression_result.get().get_type_proxy()),
expression_result.get().get_modifier()));
} // IN PROGRESS
// --- containers
void type_check_container(const nodes::Container &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
nodes::TypeCheckResult type_check_array(const nodes::Container &expression,
SourcesManager &sources_manager,
State &state) {
std::optional<nodes::TypeCheckResult> last_expression_result;
for (size_t i = 0; i < expression.expressions_size(); ++i) {
auto expression_result = type_check_expression(
*expression.get_expression(i), sources_manager, state);
if (!last_expression_result.has_value()) {
last_expression_result = expression_result;
} else {
if (last_expression_result.value().get() != expression_result.get()) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
*expression.get_expression(i),
"Elements in array should have same type",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
}
}
if (!last_expression_result.has_value()) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
expression, "Array with zero elements",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
return nodes::TypeCheckResult(nodes::ModifiedTypeProxy(
sources_manager.get_type_storage()->add_array_of(
last_expression_result.value().get().get_type_proxy()),
last_expression_result.value().get().get_modifier()));
} // IN PROGRESS
// TODO
nodes::TypeCheckResult type_check_block(const nodes::Container &expression,
SourcesManager &sources_manager,
State &state) {} // IN PROGRESS
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
SourcesManager &sources_manager,
State &state) {
switch (expression.get_type()) {
case nodes::Container::ARRAY:
return type_check_array(expression, sources_manager, state);
case nodes::Container::BLOCK:
return type_check_block(expression, sources_manager,
state); // TODO: check that expression brought
// type are same, -> brought_type
}
} // IN PROGRESS
// --- modifiers
void type_check_return(const nodes::Return &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
SourcesManager &sources_manager,
State &state) {
auto returned_result = type_check_expression(*expression.get_expression(),
sources_manager, state);
void type_check_name_definition(const nodes::NameDefinition &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
if (returned_result.is_invalid()) {
return returned_result;
}
void type_check_access(const nodes::Access &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
switch (expression.get_type()) {
case nodes::Return::BRING:
if (state.brought_type.has_value()) {
if (*state.brought_type.value().get_type() !=
*returned_result.get().get_type()) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
expression, "Different brought type to current one",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
} else {
state.brought_type = returned_result.get();
}
break;
case nodes::Return::RETURN:
if (state.returned_type.has_value()) {
if (*state.returned_type.value().get_type() !=
*returned_result.get().get_type()) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
expression, "Different returned type to current one",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
} else {
state.returned_type = returned_result.get();
}
}
void type_check_loop_control(const nodes::LoopControl &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
return nodes::TypeCheckResult(
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::UNIT));
}
void type_check_modifier_expression(const nodes::ModifierExpression &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
// TODO
nodes::TypeCheckResult
type_check_name_definition(const nodes::NameDefinition &expression,
SourcesManager &sources_manager, State &state) {
} // IN PROGRESS
nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
SourcesManager &sources_manager,
State &state) {
auto index_result =
type_check_expression(*expression.get_index(), sources_manager, state);
auto value_result =
type_check_expression(*expression.get_value(), sources_manager, state);
if (index_result.is_invalid()) {
return index_result;
}
if (value_result.is_invalid()) {
return value_result;
}
if (index_result.get().get_type()->to_builtin() !=
builtin::types::Type::INDEX) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
expression, "Can access only by Index",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
if (value_result.get().get_type()->to_builtin() !=
builtin::types::Type::ARRAY) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
expression, "Can apply array access only to Array",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
// TODO: modifier checks ??
return nodes::TypeCheckResult(
value_result.get().get_type()->get_parameter_proxy(0));
}
nodes::TypeCheckResult type_check_tuple_access(const nodes::Access &expression,
SourcesManager &sources_manager,
State &state) {
auto value_result =
type_check_expression(*expression.get_value(), sources_manager, state);
if (value_result.is_invalid()) {
return value_result;
}
size_t index = *expression.get_index()
->get<nodes::Literal>()
.value()
->get<long long>() // TODO: replace with size_t
.value();
if (value_result.get().get_type()->to_builtin() !=
builtin::types::Type::TUPLE) {
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
expression, "Can apply tuple access only to Tuple",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
// TODO: modifier checks ??
return nodes::TypeCheckResult(
value_result.get().get_type()->get_parameter_proxy(index));
}
nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
SourcesManager &sources_manager,
State &state) {
switch (expression.get_type()) {
case nodes::Access::ARRAY:
return type_check_array_access(expression, sources_manager, state);
case nodes::Access::TUPLE:
return type_check_tuple_access(expression, sources_manager, state);
}
}
nodes::TypeCheckResult type_check_loop_control(const nodes::LoopControl &,
SourcesManager &sources_manager,
State &) {
return nodes::TypeCheckResult(
sources_manager.get_type_storage()->primitive_type(
builtin::types::Type::UNIT));
}
nodes::TypeCheckResult
type_check_modifier_expression(const nodes::ModifierExpression &expression,
SourcesManager &sources_manager, State &state) {
auto modified_result = type_check_expression(*expression.get_expression(),
sources_manager, state);
if (nodes::utils::is_suffix_modifier(
expression.get_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_type()->to_builtin()) {
case builtin::types::Type::OPTIONAL:
case builtin::types::Type::RESULT:
modified_result.set(nodes::ModifiedTypeProxy(
modified_result.get().get_type()->get_parameter_proxy(0),
modified_result.get().get_modifier()));
break;
default:
sources_manager.get_error_log()->add_error(
error_handling::ErrorLog::ErrorMessage(
expression, "Can unwrap only Optional or Result",
error_handling::ErrorType::TYPE_CHECK));
return nodes::TypeCheckResult::construct_invalid_result();
}
} else {
// TODO: check that modifier can be applied
modified_result.get().set_modifier(expression.get_modifier());
}
return modified_result;
} // IN PROGRESS
// --- other
void type_check_name_expression(const nodes::NameExpression &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
// TODO
nodes::TypeCheckResult
type_check_name_expression(const nodes::NameExpression &expression,
SourcesManager &sources_manager, State &state) {
} // IN PROGRESS
void type_check_constructor(const nodes::Constructor &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
// TODO
nodes::TypeCheckResult
type_check_constructor(const nodes::Constructor &expression,
SourcesManager &sources_manager, State &state) {
} // IN PROGRESS
void type_check_lambda(const nodes::Lambda &expression,
nodes::TypeStorage &type_storage,
names::NameTree &name_tree) {}
// TODO
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
SourcesManager &sources_manager,
State &state) {} // IN PROGRESS
} // namespace type_check