mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
part of type checker, type heck result type
This commit is contained in:
parent
48c9e200be
commit
17ff590048
13 changed files with 1022 additions and 321 deletions
|
|
@ -5,15 +5,6 @@
|
|||
|
||||
namespace builders {
|
||||
|
||||
namespace utils {
|
||||
|
||||
inline bool is_suffix_modifier(nodes::Modifier modifier) {
|
||||
return modifier == nodes::Modifier::OPTIONAL ||
|
||||
modifier == nodes::Modifier::RESULT;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
// returns Modifier::NONE for incorrecnt input
|
||||
nodes::Modifier build_modifier(parser::ParseTree::Node parser_node);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
|
||||
namespace builtin {
|
||||
namespace builtin::types {
|
||||
|
||||
// -- containers
|
||||
|
||||
const static std::string TUPLE_IDENTIFIER = "Tuple";
|
||||
|
||||
|
|
@ -16,24 +19,172 @@ const static std::string OPTIONAL_IDENTIFIER = "Optional";
|
|||
|
||||
const static std::string RESULT_IDENTIFIER = "Result";
|
||||
|
||||
enum class BuiltinType {
|
||||
// -- basic types
|
||||
|
||||
const static std::string FLOAT_IDENTIFIER = "Float";
|
||||
|
||||
const static std::string DOUBLE_IDENTIFIER = "Double";
|
||||
|
||||
const static std::string INT_IDENTIFIER = "Int";
|
||||
|
||||
const static std::string LONG_IDENTIFIER = "Long";
|
||||
|
||||
const static std::string INDEX_IDENTIFIER = "Index";
|
||||
|
||||
const static std::string CHAR_IDENTIFIER = "Char";
|
||||
|
||||
const static std::string UNICODE_IDENTIFIER = "Unicode";
|
||||
|
||||
const static std::string BOOL_IDENTIFIER = "Bool";
|
||||
|
||||
const static std::string UNIT_IDENTIFIER = "Unit";
|
||||
|
||||
const static std::string NULL_OPTION_IDENTIFIER = "Null";
|
||||
|
||||
// const static std::string STRING_IDENTIFIER = "String"; // String is
|
||||
// Array[Char]
|
||||
|
||||
//
|
||||
|
||||
enum class Type {
|
||||
// -- containers
|
||||
TUPLE,
|
||||
VARIANT,
|
||||
ARRAY,
|
||||
OPTIONAL,
|
||||
RESULT,
|
||||
// -- basic types
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
INT,
|
||||
LONG,
|
||||
INDEX,
|
||||
CHAR,
|
||||
UNICODE,
|
||||
BOOL,
|
||||
UNIT,
|
||||
NULL_OPTION,
|
||||
// -- none
|
||||
NONE,
|
||||
};
|
||||
|
||||
inline nodes::Modifier builtin_to_modifier(BuiltinType type) {
|
||||
inline std::string to_string(Type type) {
|
||||
switch (type) {
|
||||
case BuiltinType::OPTIONAL:
|
||||
// -- containers
|
||||
case Type::TUPLE:
|
||||
return TUPLE_IDENTIFIER;
|
||||
case Type::VARIANT:
|
||||
return VARIANT_IDENTIFIER;
|
||||
case Type::ARRAY:
|
||||
return ARRAY_IDENTIFIER;
|
||||
case Type::OPTIONAL:
|
||||
return OPTIONAL_IDENTIFIER;
|
||||
case Type::RESULT:
|
||||
return RESULT_IDENTIFIER;
|
||||
// -- basic types
|
||||
case Type::FLOAT:
|
||||
return FLOAT_IDENTIFIER;
|
||||
case Type::DOUBLE:
|
||||
return DOUBLE_IDENTIFIER;
|
||||
case Type::INT:
|
||||
return INT_IDENTIFIER;
|
||||
case Type::LONG:
|
||||
return LONG_IDENTIFIER;
|
||||
case Type::INDEX:
|
||||
return INDEX_IDENTIFIER;
|
||||
case Type::CHAR:
|
||||
return CHAR_IDENTIFIER;
|
||||
case Type::UNICODE:
|
||||
return UNICODE_IDENTIFIER;
|
||||
case Type::BOOL:
|
||||
return BOOL_IDENTIFIER;
|
||||
case Type::UNIT:
|
||||
return UNIT_IDENTIFIER;
|
||||
case Type::NULL_OPTION:
|
||||
return NULL_OPTION_IDENTIFIER;
|
||||
// -- none
|
||||
case Type::NONE:
|
||||
return TUPLE_IDENTIFIER;
|
||||
}
|
||||
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
exit(1); // unreachable
|
||||
}
|
||||
|
||||
inline Type to_type(const std::string &str) {
|
||||
static std::map<std::string, Type> builtin_types;
|
||||
if (!builtin_types.empty()) { // if not initialized, initialize
|
||||
|
||||
// -- containers
|
||||
builtin_types[TUPLE_IDENTIFIER] = Type::TUPLE;
|
||||
builtin_types[VARIANT_IDENTIFIER] = Type::VARIANT;
|
||||
builtin_types[ARRAY_IDENTIFIER] = Type::ARRAY;
|
||||
builtin_types[OPTIONAL_IDENTIFIER] = Type::OPTIONAL;
|
||||
builtin_types[RESULT_IDENTIFIER] = Type::RESULT;
|
||||
|
||||
// -- basic types
|
||||
builtin_types[FLOAT_IDENTIFIER] = Type::FLOAT;
|
||||
builtin_types[DOUBLE_IDENTIFIER] = Type::DOUBLE;
|
||||
builtin_types[INT_IDENTIFIER] = Type::INT;
|
||||
builtin_types[LONG_IDENTIFIER] = Type::LONG;
|
||||
builtin_types[INDEX_IDENTIFIER] = Type::INDEX;
|
||||
builtin_types[CHAR_IDENTIFIER] = Type::CHAR;
|
||||
builtin_types[UNICODE_IDENTIFIER] = Type::UNICODE;
|
||||
builtin_types[BOOL_IDENTIFIER] = Type::BOOL;
|
||||
builtin_types[UNIT_IDENTIFIER] = Type::UNIT;
|
||||
builtin_types[NULL_OPTION_IDENTIFIER] = Type::NULL_OPTION;
|
||||
}
|
||||
|
||||
auto iter = builtin_types.find(str);
|
||||
|
||||
if (iter == builtin_types.end()) {
|
||||
return Type::NONE;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
inline nodes::Modifier get_modifier(Type type) {
|
||||
switch (type) {
|
||||
case Type::OPTIONAL:
|
||||
return nodes::Modifier::OPTIONAL;
|
||||
case BuiltinType::RESULT:
|
||||
case Type::RESULT:
|
||||
return nodes::Modifier::RESULT;
|
||||
default:
|
||||
return nodes::Modifier::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace builtin
|
||||
// std::nullopt for any parameters count
|
||||
inline std::optional<size_t> get_parameters_count(Type type) {
|
||||
switch (type) {
|
||||
// -- containers
|
||||
case Type::TUPLE:
|
||||
case Type::VARIANT:
|
||||
return std::nullopt;
|
||||
case Type::ARRAY:
|
||||
case Type::OPTIONAL:
|
||||
case Type::RESULT:
|
||||
return 1;
|
||||
// -- basic types
|
||||
case Type::FLOAT:
|
||||
case Type::DOUBLE:
|
||||
case Type::INT:
|
||||
case Type::LONG:
|
||||
case Type::INDEX:
|
||||
case Type::CHAR:
|
||||
case Type::UNICODE:
|
||||
case Type::BOOL:
|
||||
case Type::UNIT:
|
||||
case Type::NULL_OPTION:
|
||||
return 0;
|
||||
// -- none
|
||||
case Type::NONE:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
error_handling::handle_general_error("Unreachable");
|
||||
exit(1); // unreachable
|
||||
}
|
||||
|
||||
} // namespace builtin::types
|
||||
|
|
|
|||
74
include/error_log.hpp
Normal file
74
include/error_log.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
#include "basic_nodes.hpp"
|
||||
#include "basic_printers.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace error_handling {
|
||||
|
||||
enum class ErrorType {
|
||||
GENERAL,
|
||||
TYPE_CHECK,
|
||||
};
|
||||
|
||||
inline std::string to_string(ErrorType error_type) {
|
||||
switch (error_type) {
|
||||
case ErrorType::GENERAL:
|
||||
return "general error";
|
||||
case ErrorType::TYPE_CHECK:
|
||||
return "type check error";
|
||||
}
|
||||
}
|
||||
|
||||
class ErrorLog {
|
||||
public:
|
||||
struct ErrorMessage {
|
||||
public:
|
||||
ErrorMessage(nodes::Node node, const std::string &message,
|
||||
ErrorType error_type = ErrorType::GENERAL)
|
||||
: node_(node), message_(message), error_type_(error_type) {}
|
||||
|
||||
void print(printers::Printer &printer) {
|
||||
printer.print("Error at ");
|
||||
print_position(printer, node_.get_start_position(),
|
||||
node_.get_start_position());
|
||||
printer.print(" : ");
|
||||
printer.print(message_);
|
||||
printer.print(" (" + to_string(error_type_) + ").");
|
||||
}
|
||||
|
||||
private:
|
||||
inline void print_position(printers::Printer &printer,
|
||||
std::pair<size_t, size_t> start_position,
|
||||
std::pair<size_t, size_t> end_position) {
|
||||
printer.print("[" + std::to_string(start_position.first + 1) + ", " +
|
||||
std::to_string(start_position.second + 1) + "] - [" +
|
||||
std::to_string(end_position.first + 1) + ", " +
|
||||
std::to_string(end_position.second + 1) + "]");
|
||||
}
|
||||
|
||||
public:
|
||||
nodes::Node node_;
|
||||
std::string message_;
|
||||
ErrorType error_type_ = ErrorType::GENERAL;
|
||||
};
|
||||
|
||||
void add_error(ErrorMessage &&error) {
|
||||
messages_.push_back(std::move(error));
|
||||
}
|
||||
|
||||
void add_error(const ErrorMessage &error) { messages_.push_back(error); }
|
||||
|
||||
void print_all_errors(printers::Printer &printer) {
|
||||
for (auto &message : messages_) {
|
||||
message.print(printer);
|
||||
printer.new_indent_line();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<ErrorMessage> messages_;
|
||||
};
|
||||
|
||||
} // namespace error_handling
|
||||
|
|
@ -1,75 +1,78 @@
|
|||
#pragma once
|
||||
|
||||
#include "expression_nodes.hpp"
|
||||
#include "name_tree.hpp"
|
||||
#include "sources_manager.hpp"
|
||||
#include "type_nodes.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
// IN PROGRESS
|
||||
|
||||
namespace type_check {
|
||||
|
||||
void type_check_expression(const nodes::Expression &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
struct State {
|
||||
std::optional<nodes::ModifiedTypeProxy> brought_type;
|
||||
std::optional<nodes::ModifiedTypeProxy> returned_type;
|
||||
};
|
||||
|
||||
nodes::TypeCheckResult
|
||||
type_check_expression(const nodes::Expression &expression,
|
||||
SourcesManager &sources_manager, State &state);
|
||||
|
||||
// --- flow control
|
||||
|
||||
void type_check_case(const nodes::Match::Case &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult type_check_match(const nodes::Match &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state);
|
||||
|
||||
void type_check_match(const nodes::Match &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state);
|
||||
|
||||
void type_check_condition(const nodes::Condition &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
|
||||
void type_check_loop(const nodes::Loop &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state);
|
||||
|
||||
// --- containers
|
||||
|
||||
void type_check_container(const nodes::Container &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state);
|
||||
|
||||
// --- 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);
|
||||
|
||||
void type_check_name_definition(const nodes::NameDefinition &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult
|
||||
type_check_name_definition(const nodes::NameDefinition &expression,
|
||||
SourcesManager &sources_manager, State &state);
|
||||
|
||||
void type_check_access(const nodes::Access &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult type_check_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state);
|
||||
|
||||
void type_check_loop_control(const nodes::LoopControl &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult
|
||||
type_check_loop_control(const nodes::LoopControl &expression,
|
||||
SourcesManager &sources_manager, State &state);
|
||||
|
||||
void type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult
|
||||
type_check_modifier_expression(const nodes::ModifierExpression &expression,
|
||||
SourcesManager &sources_manager, State &state);
|
||||
|
||||
// --- other
|
||||
|
||||
void type_check_name_expression(const nodes::NameExpression &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult
|
||||
type_check_name_expression(const nodes::NameExpression &expression,
|
||||
SourcesManager &sources_manager, State &state);
|
||||
|
||||
void type_check_constructor(const nodes::Constructor &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult
|
||||
type_check_constructor(const nodes::Constructor &expression,
|
||||
SourcesManager &sources_manager, State &state);
|
||||
|
||||
void type_check_lambda(const nodes::Lambda &expression,
|
||||
nodes::TypeStorage &type_storage,
|
||||
names::NameTree &name_tree);
|
||||
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state);
|
||||
|
||||
} // namespace type_check
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "utils.hpp"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
|
@ -24,29 +25,55 @@ enum class Modifier {
|
|||
IN_OR_REF_OR_OUT, // <-|<>|-> x
|
||||
IN_OR_CONST_OR_OUT, // <-|--|-> x
|
||||
IN_OR_REF_OR_CONST, // <-|<>|-- x
|
||||
REF_OR_CONST_OR_OUT, //<>|--|-> x
|
||||
REF_OR_CONST_OR_OUT, // <>|--|-> x
|
||||
//
|
||||
IN_OR_REF_OR_CONST_OR_OUT, // <-|<>|--|-> x
|
||||
//
|
||||
OPTIONAL, // x?
|
||||
RESULT, // x!
|
||||
//
|
||||
IN_OR_REF_OR_CONST_OR_OUT, //<-|<>|--|-> x
|
||||
OPTIONAL, // x?
|
||||
RESULT, // x!
|
||||
NONE,
|
||||
};
|
||||
|
||||
namespace utils {
|
||||
|
||||
inline bool is_suffix_modifier(nodes::Modifier modifier) {
|
||||
return modifier == nodes::Modifier::OPTIONAL ||
|
||||
modifier == nodes::Modifier::RESULT;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
class Node {
|
||||
public:
|
||||
Node() : undefined_(true) {}
|
||||
|
||||
Node(std::pair<size_t, size_t> start_position,
|
||||
std::pair<size_t, size_t> end_position)
|
||||
: start_position_(start_position), end_position_(end_position) {}
|
||||
: undefined_(false), start_position_(start_position),
|
||||
end_position_(end_position) {}
|
||||
|
||||
std::pair<size_t, size_t> get_start_position() const {
|
||||
if (undefined_) {
|
||||
error_handling::handle_general_error(
|
||||
"Get start position from undefined node");
|
||||
}
|
||||
return start_position_;
|
||||
}
|
||||
|
||||
std::pair<size_t, size_t> get_end_position() const { return end_position_; }
|
||||
std::pair<size_t, size_t> get_end_position() const {
|
||||
if (undefined_) {
|
||||
error_handling::handle_general_error(
|
||||
"Get end position from undefined node");
|
||||
}
|
||||
return end_position_;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::pair<size_t, size_t> start_position_;
|
||||
std::pair<size_t, size_t> end_position_;
|
||||
bool undefined_ = false;
|
||||
|
||||
std::pair<size_t, size_t> start_position_ = {0, 0};
|
||||
std::pair<size_t, size_t> end_position_ = {0, 0};
|
||||
};
|
||||
|
||||
struct unit {};
|
||||
|
|
@ -125,6 +152,11 @@ public:
|
|||
return !(*this == other_identifier);
|
||||
}
|
||||
|
||||
bool operator<(const Identifier &other_identifier) const {
|
||||
return type_ < other_identifier.type_ || (type_ == other_identifier.type_ &&
|
||||
value_ < other_identifier.value_);
|
||||
}
|
||||
|
||||
private:
|
||||
IdentifierType type_;
|
||||
std::string value_;
|
||||
|
|
|
|||
|
|
@ -529,11 +529,12 @@ private:
|
|||
ExpressionProxy expression_;
|
||||
};
|
||||
|
||||
class Expression {
|
||||
class Expression : public Node {
|
||||
public:
|
||||
template <typename T>
|
||||
Expression(T &&expression, bool is_scoped)
|
||||
: expression_(std::forward<T>(expression)), is_scoped_(is_scoped) {}
|
||||
Expression(Node node, T &&expression, bool is_scoped)
|
||||
: Node(node), expression_(std::forward<T>(expression)),
|
||||
is_scoped_(is_scoped) {}
|
||||
|
||||
template <typename T> std::optional<T *> get() {
|
||||
if (std::holds_alternative<T>(expression_)) {
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public:
|
|||
: annotation_(annotation), type_(type),
|
||||
before_modifier_(before_modifier),
|
||||
after_modifier_(
|
||||
builtin::builtin_to_modifier(type.get()->to_builtin())) {}
|
||||
builtin::types::get_modifier(type.get()->to_builtin())) {}
|
||||
|
||||
//
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ public:
|
|||
}
|
||||
|
||||
auto type_after_modifier =
|
||||
builtin::builtin_to_modifier(type.get()->to_builtin());
|
||||
builtin::types::get_modifier(type.get()->to_builtin());
|
||||
|
||||
if (after_modifier_ != Modifier::NONE &&
|
||||
after_modifier_ != type_after_modifier) {
|
||||
|
|
@ -397,15 +397,16 @@ private:
|
|||
std::optional<TypeProxy> type_;
|
||||
};
|
||||
|
||||
class Statement {
|
||||
class Statement : public Node {
|
||||
public:
|
||||
Statement(const Statement &) = default;
|
||||
Statement(Statement &&) = default;
|
||||
Statement &operator=(const Statement &) = default;
|
||||
Statement &operator=(Statement &&) = default;
|
||||
// Statement(const Statement &) = default;
|
||||
// Statement(Statement &&) = default;
|
||||
// Statement &operator=(const Statement &) = default;
|
||||
// Statement &operator=(Statement &&) = default;
|
||||
|
||||
template <typename T>
|
||||
explicit Statement(T &&statement) : expression_(std::forward<T>(statement)) {}
|
||||
Statement(Node node, T &&statement)
|
||||
: Node(node), expression_(std::forward<T>(statement)) {}
|
||||
|
||||
template <typename T> std::optional<T *> get() {
|
||||
if (std::holds_alternative<T>(expression_)) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "basic_nodes.hpp"
|
||||
#include "builtin_types.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
|
@ -33,30 +34,40 @@ private:
|
|||
size_t id_;
|
||||
};
|
||||
|
||||
// can't have both optional and result modifiers ??
|
||||
class Type : public Node {
|
||||
// // not needed ??
|
||||
// class TypeNode : public Node {
|
||||
// public:
|
||||
// TypeNode(Node node, TypeProxy type) : Node(node), type_(type) {}
|
||||
//
|
||||
// Type *get() { return type_.get(); }
|
||||
//
|
||||
// const Type *get() const { return type_.get(); }
|
||||
//
|
||||
// private:
|
||||
// TypeProxy type_;
|
||||
// };
|
||||
|
||||
class Type {
|
||||
public:
|
||||
Type(Node node, Identifier &&identifier, bool is_on_heap = false,
|
||||
Type(Identifier &&identifier, bool is_on_heap = false,
|
||||
const std::optional<std::string> &annotation = std::nullopt)
|
||||
: Node(node), name_(std::move(identifier)), is_on_heap_(is_on_heap),
|
||||
: name_(std::move(identifier)), is_on_heap_(is_on_heap),
|
||||
annotation_(annotation) {}
|
||||
|
||||
Type(Node node, const Identifier &identifier, bool is_on_heap = false,
|
||||
Type(const Identifier &identifier, bool is_on_heap = false,
|
||||
const std::optional<std::string> &annotation = std::nullopt)
|
||||
: Node(node), name_(identifier), is_on_heap_(is_on_heap),
|
||||
annotation_(annotation) {}
|
||||
: name_(identifier), is_on_heap_(is_on_heap), annotation_(annotation) {}
|
||||
|
||||
Type(Node node, Identifier &&identifier, std::vector<TypeProxy> &¶meters,
|
||||
Type(Identifier &&identifier, std::vector<TypeProxy> &¶meters,
|
||||
bool is_on_heap = false,
|
||||
const std::optional<std::string> &annotation = std::nullopt)
|
||||
: Node(node), name_(std::move(identifier)),
|
||||
parameters_(std::move(parameters)), is_on_heap_(is_on_heap),
|
||||
annotation_(annotation) {}
|
||||
: name_(std::move(identifier)), parameters_(std::move(parameters)),
|
||||
is_on_heap_(is_on_heap), annotation_(annotation) {}
|
||||
|
||||
Type(Node node, const Identifier &identifier,
|
||||
std::vector<TypeProxy> &¶meters, bool is_on_heap = false,
|
||||
Type(const Identifier &identifier, std::vector<TypeProxy> &¶meters,
|
||||
bool is_on_heap = false,
|
||||
const std::optional<std::string> &annotation = std::nullopt)
|
||||
: Node(node), name_(identifier), parameters_(std::move(parameters)),
|
||||
: name_(identifier), parameters_(std::move(parameters)),
|
||||
is_on_heap_(is_on_heap), annotation_(annotation) {}
|
||||
|
||||
//
|
||||
|
|
@ -75,6 +86,8 @@ public:
|
|||
return parameters_.at(id).get();
|
||||
}
|
||||
|
||||
TypeProxy get_parameter_proxy(size_t id) const { return parameters_.at(id); }
|
||||
|
||||
//
|
||||
|
||||
bool is_on_heap() const { return is_on_heap_; }
|
||||
|
|
@ -119,36 +132,14 @@ public:
|
|||
|
||||
//
|
||||
|
||||
bool operator<(const Type &other_type) const {
|
||||
if (name_ != other_type.name_) {
|
||||
return *name_.get() < *other_type.name_.get();
|
||||
}
|
||||
|
||||
if (is_on_heap_ != other_type.is_on_heap_) {
|
||||
return is_on_heap_ < other_type.is_on_heap_;
|
||||
}
|
||||
|
||||
if (parameters_.size() != other_type.parameters_.size()) {
|
||||
return parameters_.size() < other_type.parameters_.size();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
||||
if (*parameters_[i].get() != *other_type.parameters_[i].get()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const Type &other_type) const {
|
||||
if (name_ != other_type.name_ || is_on_heap_ != other_type.is_on_heap_ ||
|
||||
parameters_.size() != other_type.parameters_.size()) {
|
||||
bool operator==(const Type &other) const {
|
||||
if (name_ != other.name_ || is_on_heap_ != other.is_on_heap_ ||
|
||||
parameters_.size() != other.parameters_.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
||||
if (*parameters_[i].get() != *other_type.parameters_[i].get()) {
|
||||
if (*parameters_[i].get() != *other.parameters_[i].get()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -156,29 +147,52 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const Type &other_type) const {
|
||||
return !(*this == other_type);
|
||||
bool operator!=(const Type &other) const { return !(*this == other); }
|
||||
|
||||
//
|
||||
|
||||
bool operator<(const Type &other) const {
|
||||
if (name_ != other.name_) {
|
||||
return *name_.get() < *other.name_.get();
|
||||
}
|
||||
|
||||
if (is_on_heap_ != other.is_on_heap_) {
|
||||
return is_on_heap_ < other.is_on_heap_;
|
||||
}
|
||||
|
||||
if (parameters_.size() != other.parameters_.size()) {
|
||||
return parameters_.size() < other.parameters_.size();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
||||
if (*parameters_[i].get() != *other.parameters_[i].get()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator>(const Type &other) const { return other < *this; }
|
||||
|
||||
bool operator<=(const Type &other) const { return !operator>(other); }
|
||||
|
||||
bool operator>=(const Type &other) const { return !operator<(other); }
|
||||
|
||||
// is parameters count check necessary ??
|
||||
builtin::BuiltinType to_builtin() {
|
||||
if (*name_.get() == builtin::TUPLE_IDENTIFIER && parameters_.size() > 0) {
|
||||
return builtin::BuiltinType::TUPLE;
|
||||
} else if (*name_.get() == builtin::VARIANT_IDENTIFIER &&
|
||||
parameters_.size() > 0) {
|
||||
return builtin::BuiltinType::VARIANT;
|
||||
} else if (*name_.get() == builtin::ARRAY_IDENTIFIER &&
|
||||
parameters_.size() == 1) {
|
||||
return builtin::BuiltinType::ARRAY;
|
||||
} else if (*name_.get() == builtin::OPTIONAL_IDENTIFIER &&
|
||||
parameters_.size() == 1) {
|
||||
return builtin::BuiltinType::OPTIONAL;
|
||||
} else if (*name_.get() == builtin::RESULT_IDENTIFIER &&
|
||||
parameters_.size() == 1) {
|
||||
return builtin::BuiltinType::RESULT;
|
||||
} else {
|
||||
return builtin::BuiltinType::NONE;
|
||||
builtin::types::Type to_builtin() {
|
||||
auto builtin_type = builtin::types::to_type(*name_.get());
|
||||
|
||||
auto builtin_type_parameters_count =
|
||||
builtin::types::get_parameters_count(builtin_type);
|
||||
|
||||
// for fixed parameter counts
|
||||
if (builtin_type_parameters_count.has_value() &&
|
||||
builtin_type_parameters_count.value() != parameters_.size()) {
|
||||
return builtin::types::Type::NONE;
|
||||
}
|
||||
|
||||
return builtin_type;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -193,6 +207,34 @@ class TypeStorage {
|
|||
friend TypeProxy;
|
||||
|
||||
public:
|
||||
TypeProxy primitive_type(builtin::types::Type type, Node node = Node()) {
|
||||
if (unit_type_id.has_value()) {
|
||||
return TypeProxy(*this, unit_type_id.value());
|
||||
} else {
|
||||
unit_type_id = storage_.size();
|
||||
return add_type(Type(Identifier(node, Identifier::SIMPLE_TYPE,
|
||||
builtin::types::to_string(type))));
|
||||
}
|
||||
}
|
||||
|
||||
TypeProxy add_array_of(TypeProxy type, Node node = Node()) {
|
||||
std::vector<nodes::TypeProxy> parameters;
|
||||
parameters.push_back(type);
|
||||
|
||||
return add_type(Type(Identifier(node, Identifier::SIMPLE_TYPE,
|
||||
builtin::types::ARRAY_IDENTIFIER),
|
||||
std::move(parameters)));
|
||||
}
|
||||
|
||||
nodes::TypeProxy add_container_of(std::vector<TypeProxy> &¶meters,
|
||||
builtin::types::Type container,
|
||||
Node node = Node()) {
|
||||
return add_type(
|
||||
nodes::Type(nodes::Identifier(node, nodes::Identifier::SIMPLE_TYPE,
|
||||
builtin::types::to_string(container)),
|
||||
std::move(parameters)));
|
||||
}
|
||||
|
||||
TypeProxy add_type(const Type &type) {
|
||||
storage_.push_back(type);
|
||||
return TypeProxy(*this, storage_.size() - 1);
|
||||
|
|
@ -209,89 +251,104 @@ private:
|
|||
const Type *get_type(size_t id) const { return &storage_.at(id); }
|
||||
|
||||
private:
|
||||
std::optional<size_t> unit_type_id;
|
||||
|
||||
std::vector<Type> storage_;
|
||||
};
|
||||
|
||||
// class TupleType : public Node {
|
||||
// public:
|
||||
// TupleType(Node node,
|
||||
// const std::vector<std::pair<std::optional<std::string>,
|
||||
// TypeProxy>>
|
||||
// &fields)
|
||||
// : Node(node) {
|
||||
// annotations_.reserve(fields.size());
|
||||
// fields_.reserve(fields.size());
|
||||
// for (auto &field : fields) {
|
||||
// if (field.first.has_value()) {
|
||||
// annotation_fields_[field.first.value()] = fields_.size();
|
||||
// }
|
||||
// annotations_.push_back(field.first);
|
||||
// fields_.push_back(field.second);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// size_t size() const { return fields_.size(); }
|
||||
//
|
||||
// std::optional<std::string *> get_annotation(size_t id) {
|
||||
// if (annotations_.at(id).has_value()) {
|
||||
// return &annotations_[id].value();
|
||||
// }
|
||||
// return std::nullopt;
|
||||
// }
|
||||
//
|
||||
// std::optional<const std::string *> get_annotation(size_t id) const {
|
||||
// if (annotations_.at(id).has_value()) {
|
||||
// return &annotations_[id].value();
|
||||
// }
|
||||
// return std::nullopt;
|
||||
// }
|
||||
//
|
||||
// Type *get(size_t id) { return fields_.at(id).get(); }
|
||||
//
|
||||
// const Type *get(size_t id) const { return fields_.at(id).get(); }
|
||||
//
|
||||
// Type *get(const std::string &annotation) {
|
||||
// return fields_.at(annotation_fields_.at(annotation)).get();
|
||||
// }
|
||||
//
|
||||
// const Type *get(const std::string &annotation) const {
|
||||
// return fields_.at(annotation_fields_.at(annotation)).get();
|
||||
// }
|
||||
//
|
||||
// std::vector<std::string> get_all_annotations() {
|
||||
// std::vector<std::string> annotations;
|
||||
//
|
||||
// annotations.reserve(annotation_fields_.size());
|
||||
// for (auto &annotation_with_field : annotation_fields_) {
|
||||
// annotations.push_back(annotation_with_field.first);
|
||||
// }
|
||||
//
|
||||
// return annotations;
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// std::unordered_map<std::string, size_t> annotation_fields_;
|
||||
// std::vector<TypeProxy> fields_;
|
||||
// std::vector<std::optional<std::string>> annotations_;
|
||||
// };
|
||||
//
|
||||
// class VariantType : public Node {
|
||||
// public:
|
||||
// VariantType(Node node, std::vector<TupleType> &&constructors_)
|
||||
// : Node(node), constructors_(std::move(constructors_)) {}
|
||||
//
|
||||
// VariantType(Node node, const std::vector<TupleType> &constructors_)
|
||||
// : Node(node), constructors_(constructors_) {}
|
||||
//
|
||||
// size_t size() const { return constructors_.size(); }
|
||||
//
|
||||
// TupleType *get(size_t id) { return &constructors_.at(id); }
|
||||
//
|
||||
// const TupleType *get(size_t id) const { return &constructors_.at(id); }
|
||||
//
|
||||
// private:
|
||||
// // named constructors ??
|
||||
// std::vector<TupleType> constructors_;
|
||||
// };
|
||||
class ModifiedTypeProxy {
|
||||
public:
|
||||
ModifiedTypeProxy(nodes::TypeProxy type,
|
||||
nodes::Modifier modifier = nodes::Modifier::NONE)
|
||||
: type_(type), modifier_(modifier) {}
|
||||
|
||||
//
|
||||
|
||||
nodes::Modifier get_modifier() const { return modifier_; }
|
||||
|
||||
void set_modifier(nodes::Modifier modifier) { modifier_ = modifier; }
|
||||
|
||||
//
|
||||
|
||||
nodes::Type *get_type() { return type_.get(); }
|
||||
|
||||
const nodes::Type *get_type() const { return type_.get(); }
|
||||
|
||||
const nodes::TypeProxy get_type_proxy() const { return type_; }
|
||||
|
||||
//
|
||||
|
||||
bool operator==(const ModifiedTypeProxy &other) const {
|
||||
return *type_.get() == *other.type_.get() && modifier_ == other.modifier_;
|
||||
}
|
||||
|
||||
bool operator!=(const ModifiedTypeProxy &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
bool operator<(const ModifiedTypeProxy &other) const {
|
||||
return *type_.get() < *other.type_.get() ||
|
||||
(*type_.get() == *other.type_.get() && modifier_ < other.modifier_);
|
||||
}
|
||||
|
||||
bool operator>(const ModifiedTypeProxy &other) const { return other < *this; }
|
||||
|
||||
bool operator<=(const ModifiedTypeProxy &other) const {
|
||||
return !operator>(other);
|
||||
}
|
||||
|
||||
bool operator>=(const ModifiedTypeProxy &other) const {
|
||||
return !operator<(other);
|
||||
}
|
||||
|
||||
private:
|
||||
nodes::TypeProxy type_;
|
||||
nodes::Modifier modifier_;
|
||||
};
|
||||
|
||||
class TypeCheckResult {
|
||||
public:
|
||||
// for invalid type
|
||||
static TypeCheckResult construct_invalid_result() {
|
||||
return TypeCheckResult();
|
||||
}
|
||||
|
||||
explicit TypeCheckResult(std::optional<ModifiedTypeProxy> type)
|
||||
: type_(type) {}
|
||||
|
||||
//
|
||||
|
||||
ModifiedTypeProxy &get() {
|
||||
if (!type_.has_value()) {
|
||||
error_handling::handle_general_error(
|
||||
"Access to invalid type in TypeCheckResult");
|
||||
}
|
||||
|
||||
return type_.value();
|
||||
}
|
||||
|
||||
const ModifiedTypeProxy &get() const {
|
||||
if (!type_.has_value()) {
|
||||
error_handling::handle_general_error(
|
||||
"Access to invalid type in TypeCheckResult");
|
||||
}
|
||||
|
||||
return type_.value();
|
||||
}
|
||||
|
||||
void set(ModifiedTypeProxy type) { type_ = type; }
|
||||
|
||||
//
|
||||
|
||||
bool is_invalid() const { return !type_.has_value(); }
|
||||
|
||||
private:
|
||||
TypeCheckResult() = default;
|
||||
|
||||
private:
|
||||
std::optional<ModifiedTypeProxy> type_;
|
||||
};
|
||||
|
||||
} // namespace nodes
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "basic_printers.hpp"
|
||||
#include "error_handling.hpp"
|
||||
#include "error_log.hpp"
|
||||
#include "expression_nodes.hpp"
|
||||
#include "name_tree.hpp"
|
||||
#include "statement_builders.hpp"
|
||||
|
|
@ -69,6 +70,18 @@ public:
|
|||
|
||||
//
|
||||
|
||||
names::NameTree *get_name_tree() { return &name_tree_; }
|
||||
|
||||
const names::NameTree *get_name_tree() const { return &name_tree_; }
|
||||
|
||||
//
|
||||
|
||||
error_handling::ErrorLog *get_error_log() { return &error_log_; }
|
||||
|
||||
const error_handling::ErrorLog *get_error_log() const { return &error_log_; }
|
||||
|
||||
//
|
||||
|
||||
size_t get_statements_size() const { return statements_.size(); }
|
||||
|
||||
nodes::Statement *get_statement(size_t id) { return &statements_.at(id); }
|
||||
|
|
@ -81,5 +94,6 @@ private:
|
|||
nodes::ExpressionStorage expression_storage_;
|
||||
nodes::TypeStorage type_storage_;
|
||||
names::NameTree name_tree_;
|
||||
error_handling::ErrorLog error_log_;
|
||||
std::vector<nodes::Statement> statements_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue