mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
type node refactoring
This commit is contained in:
parent
361a267054
commit
662a846d2d
11 changed files with 564 additions and 415 deletions
|
|
@ -246,7 +246,7 @@ BuilderTask<nodes::TypeDefinition>::operator()(const ParserNode &parser_node,
|
||||||
std::unordered_set<std::string> annotations;
|
std::unordered_set<std::string> annotations;
|
||||||
|
|
||||||
if (type.has_value()) {
|
if (type.has_value()) {
|
||||||
type.value().get()->collect_annotations_recursively(
|
type.value().get().CollectAnnotationsRecursively(
|
||||||
std::insert_iterator<std::unordered_set<std::string>>(
|
std::insert_iterator<std::unordered_set<std::string>>(
|
||||||
annotations, annotations.begin()));
|
annotations, annotations.begin()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ std::vector<nodes::Type> collect_parameters(parser::ParseTree::Node first_node,
|
||||||
parameters.push_back(
|
parameters.push_back(
|
||||||
BuilderTask<nodes::Type>{executor}(current_node, {}));
|
BuilderTask<nodes::Type>{executor}(current_node, {}));
|
||||||
if (current_annotation.has_value()) {
|
if (current_annotation.has_value()) {
|
||||||
parameters.back().get()->set_annotation(current_annotation.value());
|
parameters.back().get().annotation = current_annotation.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_node = current_node.next_named_sibling();
|
current_node = current_node.next_named_sibling();
|
||||||
|
|
@ -77,8 +77,8 @@ nodes::Type build_container_type(parser::ParseTree::Node parser_node,
|
||||||
std::vector<nodes::Type> parameters =
|
std::vector<nodes::Type> parameters =
|
||||||
collect_parameters(parser_node.nth_named_child(0), executor);
|
collect_parameters(parser_node.nth_named_child(0), executor);
|
||||||
|
|
||||||
return executor.state<Types>().add_container_of(std::move(parameters),
|
return executor.state<Types>().AddContainerOf(std::move(parameters),
|
||||||
container);
|
container);
|
||||||
}
|
}
|
||||||
|
|
||||||
// '|'? annotation? type ('|' annotation? type)+
|
// '|'? annotation? type ('|' annotation? type)+
|
||||||
|
|
@ -103,7 +103,7 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::REFERENCE_TYPE>>::operator()(
|
||||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
nodes::Type type = Run<nodes::Type>(parser_node.nth_named_child(0));
|
nodes::Type type = Run<nodes::Type>(parser_node.nth_named_child(0));
|
||||||
type.get()->set_modifier(RunOther<nodes::Modifier>(parser_node.nth_child(0)));
|
type.get().modifier = RunOther<nodes::Modifier>(parser_node.nth_child(0));
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,8 +112,8 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>::operator()(
|
||||||
const ParserNode &parser_node, const Args &) {
|
const ParserNode &parser_node, const Args &) {
|
||||||
Log::Context logc(executor.log(), Log::Area::kParse);
|
Log::Context logc(executor.log(), Log::Area::kParse);
|
||||||
|
|
||||||
std::vector<nodes::Type> parameters;
|
std::vector<nodes::Type> params;
|
||||||
parameters.push_back(Run<nodes::Type>(parser_node.nth_named_child(0)));
|
params.push_back(Run<nodes::Type>(parser_node.nth_named_child(0)));
|
||||||
|
|
||||||
nodes::Modifier modifier = RunOther<nodes::Modifier>(
|
nodes::Modifier modifier = RunOther<nodes::Modifier>(
|
||||||
parser_node.nth_child(parser_node.child_count() - 1));
|
parser_node.nth_child(parser_node.child_count() - 1));
|
||||||
|
|
@ -133,10 +133,11 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::MODIFIED_TYPE>>::operator()(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return executor.state<Types>().add_type(
|
return executor.state<Types>().AddType(nodes::TypeData{
|
||||||
nodes::TypeData(nodes::Identifier{.kind = nodes::Identifier::kSimpleType,
|
.name = nodes::Identifier{.kind = nodes::Identifier::kSimpleType,
|
||||||
.value = identifier},
|
.value = identifier},
|
||||||
std::move(parameters)));
|
.params = std::move(params),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// type_identifier ('[' (annotation? type)+ ']')?
|
// type_identifier ('[' (annotation? type)+ ']')?
|
||||||
|
|
@ -146,11 +147,13 @@ nodes::Type BuilderTask<nodes::Type, TypeTag<Tp::SIMPLE_TYPE>>::operator()(
|
||||||
|
|
||||||
auto name_node = parser_node.child_by_field_name("name");
|
auto name_node = parser_node.child_by_field_name("name");
|
||||||
|
|
||||||
std::vector<nodes::Type> parameters =
|
std::vector<nodes::Type> params =
|
||||||
collect_parameters(name_node.next_named_sibling(), executor);
|
collect_parameters(name_node.next_named_sibling(), executor);
|
||||||
|
|
||||||
return executor.state<Types>().add_type(nodes::TypeData(
|
return executor.state<Types>().AddType(nodes::TypeData{
|
||||||
RunOther<nodes::Identifier>(name_node), std::move(parameters)));
|
.name = RunOther<nodes::Identifier>(name_node),
|
||||||
|
.params = std::move(params),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace builders
|
} // namespace builders
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ struct FunctionDefinition {
|
||||||
Argument(const std::optional<std::string> &annotation, Type type,
|
Argument(const std::optional<std::string> &annotation, Type type,
|
||||||
Modifier before_modifier = Modifier::NONE)
|
Modifier before_modifier = Modifier::NONE)
|
||||||
: annotation(annotation), type(type), before_modifier(before_modifier),
|
: annotation(annotation), type(type), before_modifier(before_modifier),
|
||||||
after_modifier(
|
after_modifier(builtin::types::get_modifier(type.get().ToBuiltin())) {
|
||||||
builtin::types::get_modifier(type.get()->to_builtin())) {}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ struct FunctionDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto type_after_modifier =
|
auto type_after_modifier =
|
||||||
builtin::types::get_modifier(new_type.get()->to_builtin());
|
builtin::types::get_modifier(new_type.get().ToBuiltin());
|
||||||
|
|
||||||
if (after_modifier != Modifier::NONE &&
|
if (after_modifier != Modifier::NONE &&
|
||||||
after_modifier != type_after_modifier) {
|
after_modifier != type_after_modifier) {
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,16 @@ class Type {
|
||||||
friend TypeStorage;
|
friend TypeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TypeData *get();
|
TypeData &get();
|
||||||
|
|
||||||
const TypeData *get() const;
|
const TypeData &get() const;
|
||||||
|
|
||||||
bool operator==(const Type &other) const;
|
std::strong_ordering operator<=>(const Type &other) const;
|
||||||
|
|
||||||
bool operator!=(const Type &) const = default;
|
// TODO: FIXME: should be automatic
|
||||||
|
bool operator==(const Type &other) const {
|
||||||
|
return (*this <=> other) == std::strong_ordering::equal;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type(TypeStorage &type_storage, size_t id)
|
Type(TypeStorage &type_storage, size_t id)
|
||||||
|
|
@ -45,297 +48,193 @@ using Types = std::vector<Type>;
|
||||||
|
|
||||||
class TypeData {
|
class TypeData {
|
||||||
public:
|
public:
|
||||||
TypeData(Identifier &&identifier, Modifier modifier = nodes::Modifier::CONST,
|
|
||||||
const std::optional<std::string> &annotation = std::nullopt)
|
|
||||||
: name_(std::move(identifier)), modifier_(modifier),
|
|
||||||
annotation_(annotation) {}
|
|
||||||
|
|
||||||
TypeData(const Identifier &identifier,
|
|
||||||
Modifier modifier = nodes::Modifier::CONST,
|
|
||||||
const std::optional<std::string> &annotation = std::nullopt)
|
|
||||||
: name_(identifier), modifier_(modifier), annotation_(annotation) {}
|
|
||||||
|
|
||||||
TypeData(Identifier &&identifier, std::vector<Type> &¶meters,
|
|
||||||
Modifier modifier = nodes::Modifier::CONST,
|
|
||||||
const std::optional<std::string> &annotation = std::nullopt)
|
|
||||||
: name_(std::move(identifier)), parameters_(std::move(parameters)),
|
|
||||||
modifier_(modifier), annotation_(annotation) {}
|
|
||||||
|
|
||||||
TypeData(const Identifier &identifier, std::vector<Type> &¶meters,
|
|
||||||
Modifier modifier = nodes::Modifier::CONST,
|
|
||||||
const std::optional<std::string> &annotation = std::nullopt)
|
|
||||||
: name_(identifier), parameters_(std::move(parameters)),
|
|
||||||
modifier_(modifier), annotation_(annotation) {}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
Identifier *get_name() { return &name_; }
|
|
||||||
|
|
||||||
const Identifier *get_name() const { return &name_; }
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
size_t parameters_size() const { return parameters_.size(); }
|
|
||||||
|
|
||||||
Type get_parameter_proxy(size_t id) const { return parameters_.at(id); }
|
|
||||||
|
|
||||||
TypeData *get_parameter(size_t id) { return get_parameter_proxy(id).get(); }
|
|
||||||
|
|
||||||
const TypeData *get_parameter(size_t id) const {
|
|
||||||
return get_parameter_proxy(id).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: cache with map ??
|
// TODO: cache with map ??
|
||||||
std::optional<Type>
|
std::optional<Type> ParamByName(const std::string &name) const {
|
||||||
get_parameter_proxy_by_name(const std::string &name) const {
|
|
||||||
const auto it = std::find_if(
|
const auto it = std::find_if(
|
||||||
parameters_.begin(), parameters_.end(), [&name](const auto ¶meter) {
|
params.begin(), params.end(), [&name](const auto ¶meter) {
|
||||||
return parameter.get()->has_annotation() &&
|
return parameter.get().HasAnnotation() &&
|
||||||
*parameter.get()->get_annotation().value() == name;
|
parameter.get().annotation.value() == name;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (it != parameters_.end()) {
|
if (it != params.end()) {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<const TypeData *>
|
//
|
||||||
get_parameter_by_name(const std::string &name) const {
|
|
||||||
const auto proxy = get_parameter_proxy_by_name(name);
|
|
||||||
return proxy.has_value() ? proxy.value().get()
|
|
||||||
: std::optional<const TypeData *>{};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<TypeData *> get_parameter_by_name(const std::string &name) {
|
bool IsModifier(Modifier other_modifier) const {
|
||||||
auto proxy = get_parameter_proxy_by_name(name);
|
return modifier == other_modifier;
|
||||||
return proxy.has_value() ? proxy.value().get()
|
|
||||||
: std::optional<TypeData *>{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
Modifier get_modifier() const { return modifier_; }
|
bool HasAnnotation() const { return annotation.has_value(); }
|
||||||
|
|
||||||
void set_modifier(Modifier modifier) { modifier_ = modifier; }
|
bool IsAnnotation(const std::string &other_annotation) const {
|
||||||
|
return annotation.has_value() and annotation.value() == other_annotation;
|
||||||
bool is_modifier(Modifier modifier) const { return modifier_ == modifier; }
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
bool has_annotation() const { return annotation_.has_value(); }
|
|
||||||
|
|
||||||
std::optional<std::string *> get_annotation() {
|
|
||||||
if (annotation_.has_value()) {
|
|
||||||
return &annotation_.value();
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<const std::string *> get_annotation() const {
|
|
||||||
if (annotation_.has_value()) {
|
|
||||||
return &annotation_.value();
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_no_annotation() const { return !annotation_.has_value(); }
|
|
||||||
|
|
||||||
bool is_annotation(const std::string &annotation) const {
|
|
||||||
return annotation_.has_value() && annotation_.value() == annotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_annotation(std::string &&annotation) {
|
|
||||||
annotation_ = std::move(annotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_annotation(const std::string &annotation) {
|
|
||||||
annotation_ = annotation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void collect_annotations_recursively(
|
void
|
||||||
std::insert_iterator<T> insert_iterator) const {
|
CollectAnnotationsRecursively(std::insert_iterator<T> insert_iterator) const {
|
||||||
if (annotation_.has_value()) {
|
if (annotation.has_value()) {
|
||||||
insert_iterator = annotation_.value();
|
insert_iterator = annotation.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto ¶meter : parameters_) {
|
for (auto ¶meter : params) {
|
||||||
parameter.get()->collect_annotations_recursively(insert_iterator);
|
parameter.get().CollectAnnotationsRecursively(insert_iterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
bool is_generic() { return name_.kind == Identifier::kGenericType; }
|
bool IsGeneric() const { return name.kind == Identifier::kGenericType; }
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
bool operator==(const TypeData &other) const {
|
std::strong_ordering operator<=>(const TypeData &other) const {
|
||||||
if (name_ != other.name_ || modifier_ != other.modifier_ ||
|
if (name != other.name) {
|
||||||
parameters_.size() != other.parameters_.size()) {
|
return name.value <=> other.name.value;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
if (modifier != other.modifier) {
|
||||||
if (parameters_[i] != other.parameters_[i]) {
|
return modifier <=> other.modifier;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
if (params.size() != other.params.size()) {
|
||||||
|
return params.size() <=> other.params.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < params.size(); ++i) {
|
||||||
|
if ((params[i].get() <=> other.params[i].get()) !=
|
||||||
|
std::strong_ordering::equal) {
|
||||||
|
return params[i].get() <=> other.params[i].get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return std::strong_ordering::equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const TypeData &other) const { return !(*this == other); }
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
bool operator<(const TypeData &other) const {
|
|
||||||
if (name_ != other.name_) {
|
|
||||||
return name_.value < other.name_.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modifier_ != other.modifier_) {
|
|
||||||
return modifier_ < other.modifier_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameters_.size() != other.parameters_.size()) {
|
|
||||||
return parameters_.size() < other.parameters_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < parameters_.size(); ++i) {
|
|
||||||
if (parameters_[i] != other.parameters_[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>(const TypeData &other) const { return other < *this; }
|
|
||||||
|
|
||||||
bool operator<=(const TypeData &other) const { return !operator>(other); }
|
|
||||||
|
|
||||||
bool operator>=(const TypeData &other) const { return !operator<(other); }
|
|
||||||
|
|
||||||
// is parameters count check necessary ??
|
// is parameters count check necessary ??
|
||||||
builtin::Type to_builtin() const {
|
builtin::Type ToBuiltin() const {
|
||||||
auto builtin_type = builtin::types::to_type(name_.value);
|
auto builtin_type = builtin::types::to_type(name.value);
|
||||||
|
|
||||||
auto builtin_type_parameters_count =
|
auto builtin_type_parameters_count =
|
||||||
builtin::types::get_parameters_count(builtin_type);
|
builtin::types::get_parameters_count(builtin_type);
|
||||||
|
|
||||||
// for fixed parameter counts
|
// for fixed parameter counts
|
||||||
if (builtin_type_parameters_count.has_value() &&
|
if (builtin_type_parameters_count.has_value() &&
|
||||||
builtin_type_parameters_count.value() != parameters_.size()) {
|
builtin_type_parameters_count.value() != params.size()) {
|
||||||
return builtin::Type::NONE;
|
return builtin::Type::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return builtin_type;
|
return builtin_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_builtin(builtin::Type type) const { return to_builtin() == type; }
|
bool IsBuiltin(builtin::Type type) const { return ToBuiltin() == type; }
|
||||||
|
|
||||||
private:
|
public:
|
||||||
Identifier name_;
|
Identifier name;
|
||||||
std::vector<Type> parameters_;
|
std::vector<Type> params = {};
|
||||||
Modifier modifier_ = Modifier::NONE;
|
Modifier modifier = Modifier::NONE;
|
||||||
std::optional<std::string> annotation_;
|
std::optional<std::string> annotation = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class TypeStorage {
|
class TypeStorage {
|
||||||
friend Type;
|
friend Type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Type primitive(builtin::Type type);
|
Type Primitive(builtin::Type type);
|
||||||
|
|
||||||
Type add_array_of(Type type);
|
Type AddArrayOf(Type type);
|
||||||
|
|
||||||
Type add_error_of(Type type);
|
Type AddErrorOf(Type type);
|
||||||
|
|
||||||
nodes::Type add_container_of(std::vector<Type> &¶meters,
|
nodes::Type AddContainerOf(std::vector<Type> &¶meters,
|
||||||
builtin::Type container);
|
builtin::Type container);
|
||||||
|
|
||||||
nodes::Type add_modification_of(Type type, Modifier modifier);
|
nodes::Type AddModificationOf(Type type, Modifier modifier);
|
||||||
|
|
||||||
Type add_type(const TypeData &type) {
|
Type AddType(TypeData type) {
|
||||||
storage_.push_back(type);
|
|
||||||
return Type(*this, storage_.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Type add_type(TypeData &&type) {
|
|
||||||
storage_.push_back(std::move(type));
|
storage_.push_back(std::move(type));
|
||||||
return Type(*this, storage_.size() - 1);
|
return Type(*this, storage_.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- deal with generic types (variable types in this case)
|
// -- deal with generic types (variable types in this case)
|
||||||
|
|
||||||
bool resolve_all_generic_types();
|
Type AddGenericType() {
|
||||||
|
return AddType(TypeData{.name = GenerateGenericTypeId()});
|
||||||
Type add_generic_type() {
|
|
||||||
return add_type(TypeData(generate_generic_type_identifier()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool resolve_generic_name(const std::string &name, const Type &actulal_type);
|
|
||||||
|
|
||||||
void clear_resolved_generic_names() { resolved_generic_names_.clear(); }
|
|
||||||
|
|
||||||
// -- deal with local types // not needed ??
|
|
||||||
|
|
||||||
bool add_local_type(const std::string &name);
|
|
||||||
|
|
||||||
bool add_local_type_requirement(const std::string &name,
|
|
||||||
const Identifier &typeclass);
|
|
||||||
|
|
||||||
bool add_local_type_requirement(const std::string &name,
|
|
||||||
Identifier &&typeclass);
|
|
||||||
|
|
||||||
std::optional<std::set<Identifier> *>
|
|
||||||
get_local_type_requirements(const std::string &name);
|
|
||||||
|
|
||||||
std::optional<const std::set<Identifier> *>
|
|
||||||
get_local_type_requirements(const std::string &name) const;
|
|
||||||
|
|
||||||
void clear_local_name_typeclasses() {
|
|
||||||
local_name_ids_.clear();
|
|
||||||
local_name_typeclasses_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
enum class UnifyModePolicy { // TODO: proper modes for modifier
|
enum class UnifyModePolicy { // TODO: proper modes for modifier
|
||||||
Ignore, // all mode differences ignored
|
kIgnore, // all mode differences ignored
|
||||||
ApplyStrongest, // unique > shared, modes changed
|
kApplyStrongest, // unique > shared, modes changed
|
||||||
CheckLeftIsSubmode, // only check is performed
|
kCheckLeftIsSubmode, // only check is performed
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: next iteration of type check
|
// TODO: next iteration of type check
|
||||||
bool unify(Type left_proxy, Type right_proxy, UnifyModePolicy policy);
|
bool Unify(Type left, Type right, UnifyModePolicy policy);
|
||||||
|
|
||||||
bool resolve(Type generic,
|
bool Resolve(Type generic,
|
||||||
const TypeData &replacement /* TODO , Mode mode = {}*/);
|
const TypeData &replacement /* TODO , Mode mode = {}*/);
|
||||||
|
|
||||||
|
// TODO: needed ??
|
||||||
|
|
||||||
|
// bool resolve_all_generic_types();
|
||||||
|
|
||||||
|
// bool resolve_generic_name(const std::string &name, const Type
|
||||||
|
// &actulal_type);
|
||||||
|
|
||||||
|
// void clear_resolved_generic_names() { resolved_generic_names_.clear(); }
|
||||||
|
|
||||||
|
// -- deal with local types // not needed ??
|
||||||
|
|
||||||
|
// bool add_local_type(const std::string &name);
|
||||||
|
|
||||||
|
// bool add_local_type_requirement(const std::string &name,
|
||||||
|
// const Identifier &typeclass);
|
||||||
|
|
||||||
|
// bool add_local_type_requirement(const std::string &name,
|
||||||
|
// Identifier &&typeclass);
|
||||||
|
|
||||||
|
// std::optional<std::set<Identifier> *>
|
||||||
|
// get_local_type_requirements(const std::string &name);
|
||||||
|
|
||||||
|
// std::optional<const std::set<Identifier> *>
|
||||||
|
// get_local_type_requirements(const std::string &name) const;
|
||||||
|
|
||||||
|
// void clear_local_name_typeclasses() {
|
||||||
|
// local_name_ids_.clear();
|
||||||
|
// local_name_typeclasses_.clear();
|
||||||
|
// }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TypeData *get_type(size_t id) { return &storage_.at(id); }
|
TypeData &operator[](size_t id) { return storage_.at(id); }
|
||||||
|
|
||||||
const TypeData *get_type(size_t id) const { return &storage_.at(id); }
|
const TypeData &operator[](size_t id) const { return storage_.at(id); }
|
||||||
|
|
||||||
Identifier generate_generic_type_identifier();
|
Identifier GenerateGenericTypeId();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// check is builtin type instaniated
|
// check is builtin type instaniated
|
||||||
std::unordered_map<builtin::Type, size_t> primitive_type_ids_;
|
std::unordered_map<builtin::Type, size_t> primitive_type_ids_;
|
||||||
|
|
||||||
// deal with generic types and generic names
|
// deal with generic types and generic names
|
||||||
std::unordered_map<std::string, size_t> resolved_generic_names_;
|
// std::unordered_map<std::string, size_t> resolved_generic_names_; // TODO:
|
||||||
|
// needed ??
|
||||||
size_t last_generic_type_id_ = 0;
|
size_t last_generic_type_id_ = 0;
|
||||||
|
|
||||||
|
// TODO: needed ??
|
||||||
// deal with local types
|
// deal with local types
|
||||||
std::unordered_map<std::string, size_t> local_name_ids_;
|
// std::unordered_map<std::string, size_t> local_name_ids_;
|
||||||
std::vector<std::set<Identifier>> local_name_typeclasses_;
|
// std::vector<std::set<Identifier>> local_name_typeclasses_;
|
||||||
|
|
||||||
// storage for all types
|
// storage for all types
|
||||||
std::vector<TypeData> storage_;
|
std::vector<TypeData> storage_; // TODO: map ??
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace nodes
|
} // namespace nodes
|
||||||
|
|
|
||||||
|
|
@ -4,69 +4,76 @@
|
||||||
|
|
||||||
namespace nodes {
|
namespace nodes {
|
||||||
|
|
||||||
TypeData *Type::get() { return type_storage_->get_type(id_); }
|
TypeData &Type::get() { return (*type_storage_)[id_]; }
|
||||||
|
|
||||||
const TypeData *Type::get() const { return type_storage_->get_type(id_); }
|
const TypeData &Type::get() const { return (*type_storage_)[id_]; }
|
||||||
|
|
||||||
bool Type::operator==(const Type &other) const {
|
std::strong_ordering Type::operator<=>(const Type &other) const {
|
||||||
return *get() == *other.get();
|
return get() <=> other.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
Type TypeStorage::primitive(builtin::Type type) {
|
Type TypeStorage::Primitive(builtin::Type type) {
|
||||||
auto iter = primitive_type_ids_.find(type);
|
auto iter = primitive_type_ids_.find(type);
|
||||||
if (iter != primitive_type_ids_.end()) {
|
if (iter != primitive_type_ids_.end()) {
|
||||||
return Type(*this, iter->second);
|
return Type(*this, iter->second);
|
||||||
} else {
|
} else {
|
||||||
primitive_type_ids_[type] = storage_.size();
|
primitive_type_ids_[type] = storage_.size();
|
||||||
return add_type(TypeData(Identifier{
|
return AddType(TypeData{
|
||||||
.kind = Identifier::kSimpleType,
|
.name =
|
||||||
.value = builtin::types::to_string(type),
|
Identifier{
|
||||||
}));
|
.kind = Identifier::kSimpleType,
|
||||||
|
.value = builtin::types::to_string(type),
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type TypeStorage::add_array_of(Type type) {
|
Type TypeStorage::AddArrayOf(Type type) {
|
||||||
if (type.type_storage_ != this) {
|
if (type.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
error_handling::handle_general_error(
|
||||||
"TypeStorage: Can't add array of type from another type "
|
"TypeStorage: Can't add array of type from another type "
|
||||||
"storage");
|
"storage");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<nodes::Type> parameters;
|
std::vector<nodes::Type> params;
|
||||||
parameters.push_back(type);
|
params.push_back(type);
|
||||||
|
|
||||||
return add_type(TypeData(
|
return AddType(TypeData{
|
||||||
Identifier{
|
.name =
|
||||||
.kind = Identifier::kSimpleType,
|
Identifier{
|
||||||
.value = builtin::types::ARRAY_IDENTIFIER,
|
.kind = Identifier::kSimpleType,
|
||||||
},
|
.value = builtin::types::ARRAY_IDENTIFIER,
|
||||||
std::move(parameters)));
|
},
|
||||||
|
.params = std::move(params),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Type TypeStorage::add_error_of(Type type) {
|
Type TypeStorage::AddErrorOf(Type type) {
|
||||||
if (type.type_storage_ != this) {
|
if (type.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
error_handling::handle_general_error(
|
||||||
"TypeStorage: Can't add error of type from another type "
|
"TypeStorage: Can't add error of type from another type "
|
||||||
"storage");
|
"storage");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<nodes::Type> parameters;
|
std::vector<nodes::Type> params;
|
||||||
parameters.push_back(type);
|
params.push_back(type);
|
||||||
|
|
||||||
return add_type(TypeData(
|
return AddType(TypeData{
|
||||||
Identifier{
|
.name =
|
||||||
.kind = Identifier::kSimpleType,
|
Identifier{
|
||||||
.value = builtin::types::ERROR_IDENTIFIER,
|
.kind = Identifier::kSimpleType,
|
||||||
},
|
.value = builtin::types::ERROR_IDENTIFIER,
|
||||||
std::move(parameters)));
|
},
|
||||||
|
.params = std::move(params),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Type TypeStorage::add_container_of(std::vector<Type> &¶meters,
|
nodes::Type TypeStorage::AddContainerOf(std::vector<Type> &¶ms,
|
||||||
builtin::Type container) {
|
builtin::Type container) {
|
||||||
for (auto ¶meter : parameters) {
|
for (auto ¶m : params) {
|
||||||
if (parameter.type_storage_ != this) {
|
if (param.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
error_handling::handle_general_error(
|
||||||
"TypeStorage: Can't add container with parameter of type from "
|
"TypeStorage: Can't add container with parameter of type from "
|
||||||
"another type "
|
"another type "
|
||||||
|
|
@ -74,146 +81,148 @@ nodes::Type TypeStorage::add_container_of(std::vector<Type> &¶meters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return add_type(nodes::TypeData(
|
return AddType(nodes::TypeData{
|
||||||
nodes::Identifier{
|
.name =
|
||||||
.kind = nodes::Identifier::kSimpleType,
|
nodes::Identifier{
|
||||||
.value = builtin::types::to_string(container),
|
.kind = nodes::Identifier::kSimpleType,
|
||||||
},
|
.value = builtin::types::to_string(container),
|
||||||
std::move(parameters)));
|
},
|
||||||
|
.params = std::move(params),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes::Type TypeStorage::add_modification_of(Type type, Modifier modifier) {
|
nodes::Type TypeStorage::AddModificationOf(Type type, Modifier modifier) {
|
||||||
if (type.type_storage_ != this) {
|
if (type.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
error_handling::handle_general_error(
|
||||||
"TypeStorage: Can't add modification of type from another type "
|
"TypeStorage: Can't add modification of type from another type "
|
||||||
"storage");
|
"storage");
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeData type_copy = *type.get();
|
TypeData type_copy = type.get();
|
||||||
type_copy.set_modifier(modifier);
|
type_copy.modifier = modifier;
|
||||||
|
|
||||||
return add_type(std::move(type_copy));
|
return AddType(std::move(type_copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- deal with generic types (variable types in this case)
|
// -- deal with generic types (variable types in this case)
|
||||||
|
|
||||||
bool TypeStorage::resolve_all_generic_types() {
|
// bool TypeStorage::ResolveAllGenericTypes() {
|
||||||
bool are_all_resolved = true;
|
// bool are_all_resolved = true;
|
||||||
|
|
||||||
bool new_types_resolved = true;
|
// bool new_types_resolved = true;
|
||||||
|
|
||||||
while (new_types_resolved) {
|
// while (new_types_resolved) {
|
||||||
new_types_resolved = false;
|
// new_types_resolved = false;
|
||||||
|
|
||||||
for (auto &type : storage_) {
|
// for (auto &type : storage_) {
|
||||||
if (type.is_generic()) {
|
// if (type.is_generic()) {
|
||||||
auto iter = resolved_generic_names_.find(type.get_name()->value);
|
// auto iter = resolved_generic_names_.find(type.get_name()->value);
|
||||||
|
|
||||||
// because of undefined order some types can became resolved earlir
|
// // because of undefined order some types can became resolved earlir
|
||||||
// wirking correctly because each generic type has <= 1 successor, no
|
// // wirking correctly because each generic type has <= 1 successor, no
|
||||||
// cyclic deps allowed (do check ??)
|
// // cyclic deps allowed (do check ??)
|
||||||
if (iter != resolved_generic_names_.end()) {
|
// if (iter != resolved_generic_names_.end()) {
|
||||||
new_types_resolved = true;
|
// new_types_resolved = true;
|
||||||
type = storage_[iter->second];
|
// type = storage_[iter->second];
|
||||||
} else {
|
// } else {
|
||||||
are_all_resolved = false;
|
// are_all_resolved = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// this check is not required ??
|
// // this check is not required ??
|
||||||
for (auto &type : storage_) {
|
// for (auto &type : storage_) {
|
||||||
if (!type.is_generic()) {
|
// if (!type.is_generic()) {
|
||||||
are_all_resolved = false;
|
// are_all_resolved = false;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return are_all_resolved;
|
// return are_all_resolved;
|
||||||
}
|
// }
|
||||||
|
|
||||||
bool TypeStorage::resolve_generic_name(const std::string &name,
|
// bool TypeStorage::ResolveGenericName(const std::string &name,
|
||||||
const Type &actulal_type) {
|
// const Type &actulal_type) {
|
||||||
if (actulal_type.type_storage_ != this) {
|
// if (actulal_type.type_storage_ != this) {
|
||||||
error_handling::handle_general_error(
|
// error_handling::handle_general_error(
|
||||||
"TypeStorage: Can't resolve generic type to type from another type "
|
// "TypeStorage: Can't resolve generic type to type from another type "
|
||||||
"storage");
|
// "storage");
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (resolved_generic_names_.count(name) != 0) {
|
// if (resolved_generic_names_.count(name) != 0) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
resolved_generic_names_[name] = actulal_type.id_;
|
// resolved_generic_names_[name] = actulal_type.id_;
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// -- deal with local types
|
// -- deal with local types
|
||||||
|
|
||||||
bool TypeStorage::add_local_type(const std::string &name) {
|
// bool TypeStorage::AddLocalType(const std::string &name) {
|
||||||
if (local_name_ids_.count(name) != 0) {
|
// if (local_name_ids_.count(name) != 0) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
local_name_ids_[name] = local_name_typeclasses_.size();
|
// local_name_ids_[name] = local_name_typeclasses_.size();
|
||||||
local_name_typeclasses_.emplace_back();
|
// local_name_typeclasses_.emplace_back();
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
bool TypeStorage::add_local_type_requirement(const std::string &name,
|
// bool TypeStorage::add_local_type_requirement(const std::string &name,
|
||||||
const Identifier &typeclass) {
|
// const Identifier &typeclass) {
|
||||||
auto iter = local_name_ids_.find(name);
|
// auto iter = local_name_ids_.find(name);
|
||||||
|
|
||||||
if (iter == local_name_ids_.end()) {
|
// if (iter == local_name_ids_.end()) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
local_name_typeclasses_[iter->second].insert(typeclass);
|
// local_name_typeclasses_[iter->second].insert(typeclass);
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
bool TypeStorage::add_local_type_requirement(const std::string &name,
|
// bool TypeStorage::add_local_type_requirement(const std::string &name,
|
||||||
Identifier &&typeclass) {
|
// Identifier &&typeclass) {
|
||||||
auto iter = local_name_ids_.find(name);
|
// auto iter = local_name_ids_.find(name);
|
||||||
|
|
||||||
if (iter == local_name_ids_.end()) {
|
// if (iter == local_name_ids_.end()) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
local_name_typeclasses_[iter->second].insert(std::move(typeclass));
|
// local_name_typeclasses_[iter->second].insert(std::move(typeclass));
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
std::optional<std::set<Identifier> *>
|
// std::optional<std::set<Identifier> *>
|
||||||
TypeStorage::get_local_type_requirements(const std::string &name) {
|
// TypeStorage::get_local_type_requirements(const std::string &name) {
|
||||||
auto iter = local_name_ids_.find(name);
|
// auto iter = local_name_ids_.find(name);
|
||||||
|
|
||||||
if (iter == local_name_ids_.end()) {
|
// if (iter == local_name_ids_.end()) {
|
||||||
return std::nullopt;
|
// return std::nullopt;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return &local_name_typeclasses_[iter->second];
|
// return &local_name_typeclasses_[iter->second];
|
||||||
}
|
// }
|
||||||
|
|
||||||
std::optional<const std::set<Identifier> *>
|
// std::optional<const std::set<Identifier> *>
|
||||||
TypeStorage::get_local_type_requirements(const std::string &name) const {
|
// TypeStorage::get_local_type_requirements(const std::string &name) const {
|
||||||
auto iter = local_name_ids_.find(name);
|
// auto iter = local_name_ids_.find(name);
|
||||||
|
|
||||||
if (iter == local_name_ids_.end()) {
|
// if (iter == local_name_ids_.end()) {
|
||||||
return std::nullopt;
|
// return std::nullopt;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return &local_name_typeclasses_[iter->second];
|
// return &local_name_typeclasses_[iter->second];
|
||||||
}
|
// }
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
bool TypeStorage::unify(Type /*left_proxy*/, Type /*right_proxy*/,
|
bool TypeStorage::Unify(Type /*left*/, Type /*right*/,
|
||||||
UnifyModePolicy /*policy*/) {
|
UnifyModePolicy /*policy*/) {
|
||||||
// Type &left = left_id.get();
|
// Type &left = left_id.get();
|
||||||
// Type &right = right_id.get();
|
// Type &right = right_id.get();
|
||||||
|
|
@ -275,12 +284,12 @@ bool TypeStorage::unify(Type /*left_proxy*/, Type /*right_proxy*/,
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeStorage::resolve(
|
bool TypeStorage::Resolve(
|
||||||
Type generic, const TypeData &replacement /* TODO , Mode mode = {}*/) {
|
Type generic, const TypeData &replacement /* TODO , Mode mode = {}*/) {
|
||||||
error_handling::ensure(generic.get()->is_generic(), "Type should be generic");
|
error_handling::ensure(generic.get().IsGeneric(), "Type should be generic");
|
||||||
error_handling::ensure(generic.get()->is_generic(), "Type should be generic");
|
error_handling::ensure(generic.get().IsGeneric(), "Type should be generic");
|
||||||
for (auto &type : storage_) {
|
for (auto &type : storage_) {
|
||||||
if (type.is_generic() && type.get_name() == generic.get()->get_name()) {
|
if (type.IsGeneric() && type.name == generic.get().name) {
|
||||||
type = replacement;
|
type = replacement;
|
||||||
// type.mode = mode;
|
// type.mode = mode;
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +300,7 @@ bool TypeStorage::resolve(
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
Identifier TypeStorage::generate_generic_type_identifier() {
|
Identifier TypeStorage::GenerateGenericTypeId() {
|
||||||
Identifier identifier = Identifier{
|
Identifier identifier = Identifier{
|
||||||
.kind = Identifier::kGenericType,
|
.kind = Identifier::kGenericType,
|
||||||
.value = "G_" + std::to_string(last_generic_type_id_),
|
.value = "G_" + std::to_string(last_generic_type_id_),
|
||||||
|
|
|
||||||
|
|
@ -7,27 +7,27 @@ namespace printers {
|
||||||
|
|
||||||
Result PrintTask<nodes::Type>::operator()(const nodes::Type &type,
|
Result PrintTask<nodes::Type>::operator()(const nodes::Type &type,
|
||||||
const Args &args) {
|
const Args &args) {
|
||||||
return Run(*type.get(), args);
|
return Run(type.get(), args);
|
||||||
}
|
}
|
||||||
// TODO: better printing format for builtin types
|
// TODO: better printing format for builtin types
|
||||||
Result PrintTask<nodes::TypeData>::operator()(const nodes::TypeData &type,
|
Result PrintTask<nodes::TypeData>::operator()(const nodes::TypeData &type,
|
||||||
const Args &) {
|
const Args &) {
|
||||||
if (type.has_annotation()) {
|
if (type.HasAnnotation()) {
|
||||||
Run(nodes::Annotation{.value = *type.get_annotation().value()});
|
Run(nodes::Annotation{.value = type.annotation.value()});
|
||||||
Space();
|
Space();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.get_modifier() != nodes::Modifier::CONST) {
|
if (type.modifier != nodes::Modifier::CONST) {
|
||||||
Run(type.get_modifier());
|
Run(type.modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
Run(*type.get_name());
|
Run(type.name);
|
||||||
|
|
||||||
if (type.parameters_size() > 0) {
|
if (type.params.size() > 0) {
|
||||||
Print("[");
|
Print("[");
|
||||||
for (size_t i = 0; i < type.parameters_size(); ++i) {
|
for (size_t i = 0; i < type.params.size(); ++i) {
|
||||||
Run(*type.get_parameter(i));
|
Run(type.params.at(i));
|
||||||
if (i + 1 < type.parameters_size()) {
|
if (i + 1 < type.params.size()) {
|
||||||
Space();
|
Space();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,13 +189,13 @@ public:
|
||||||
|
|
||||||
Args ExpectBuiltin(builtin::Type type, Executor &executor) const {
|
Args ExpectBuiltin(builtin::Type type, Executor &executor) const {
|
||||||
Args copy(*this);
|
Args copy(*this);
|
||||||
copy.expected_types_ = {executor.state<Types>().primitive(type)};
|
copy.expected_types_ = {executor.state<Types>().Primitive(type)};
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
Args PassBuiltin(builtin::Type type, Executor &executor) const {
|
Args PassBuiltin(builtin::Type type, Executor &executor) const {
|
||||||
Args copy(*this);
|
Args copy(*this);
|
||||||
copy.passed_type_ = executor.state<Types>().primitive(type);
|
copy.passed_type_ = executor.state<Types>().Primitive(type);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,31 +8,31 @@ nodes::Type get_literal_type(const nodes::Literal &literal,
|
||||||
|
|
||||||
switch (literal.value.index()) {
|
switch (literal.value.index()) {
|
||||||
case 0: // float
|
case 0: // float
|
||||||
return executor.state<Types>().primitive(builtin::Type::FLOAT);
|
return executor.state<Types>().Primitive(builtin::Type::FLOAT);
|
||||||
case 1: // double
|
case 1: // double
|
||||||
return executor.state<Types>().primitive(builtin::Type::DOUBLE);
|
return executor.state<Types>().Primitive(builtin::Type::DOUBLE);
|
||||||
case 2: // int32_t
|
case 2: // int32_t
|
||||||
return executor.state<Types>().primitive(builtin::Type::INT);
|
return executor.state<Types>().Primitive(builtin::Type::INT);
|
||||||
case 3: // int64_t
|
case 3: // int64_t
|
||||||
return executor.state<Types>().primitive(builtin::Type::LONG);
|
return executor.state<Types>().Primitive(builtin::Type::LONG);
|
||||||
case 4: // size_t
|
case 4: // size_t
|
||||||
return executor.state<Types>().primitive(builtin::Type::INDEX);
|
return executor.state<Types>().Primitive(builtin::Type::INDEX);
|
||||||
case 5: // std::string
|
case 5: // std::string
|
||||||
return executor.state<Types>().add_array_of(
|
return executor.state<Types>().AddArrayOf(
|
||||||
executor.state<Types>().primitive(builtin::Type::CHAR));
|
executor.state<Types>().Primitive(builtin::Type::CHAR));
|
||||||
case 6: // unicode_string
|
case 6: // unicode_string
|
||||||
return executor.state<Types>().add_array_of(
|
return executor.state<Types>().AddArrayOf(
|
||||||
executor.state<Types>().primitive(builtin::Type::UNICODE));
|
executor.state<Types>().Primitive(builtin::Type::UNICODE));
|
||||||
case 7: // char
|
case 7: // char
|
||||||
return executor.state<Types>().primitive(builtin::Type::CHAR);
|
return executor.state<Types>().Primitive(builtin::Type::CHAR);
|
||||||
case 8: // unicode
|
case 8: // unicode
|
||||||
return executor.state<Types>().primitive(builtin::Type::UNICODE);
|
return executor.state<Types>().Primitive(builtin::Type::UNICODE);
|
||||||
case 9: // bool
|
case 9: // bool
|
||||||
return executor.state<Types>().primitive(builtin::Type::BOOL);
|
return executor.state<Types>().Primitive(builtin::Type::BOOL);
|
||||||
case 10: // unit
|
case 10: // unit
|
||||||
return executor.state<Types>().primitive(builtin::Type::UNIT);
|
return executor.state<Types>().Primitive(builtin::Type::UNIT);
|
||||||
case 11: // null
|
case 11: // null
|
||||||
return executor.state<Types>().primitive(builtin::Type::NULL_OPTION);
|
return executor.state<Types>().Primitive(builtin::Type::NULL_OPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::Assert(true, "Unreachable");
|
utils::Assert(true, "Unreachable");
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,245 @@
|
||||||
|
|
||||||
#include "expression_type_check.hpp"
|
#include "expression_type_check.hpp"
|
||||||
|
|
||||||
namespace type_check {} // namespace type_check
|
namespace type_check {
|
||||||
|
|
||||||
|
// <------ NOTE: CHECK ENDED THERE
|
||||||
|
|
||||||
|
// TODO: add constraints evaluation
|
||||||
|
Result CheckTask<nodes::Constructor>::operator()(const nodes::Constructor &expr,
|
||||||
|
const Args &args) {
|
||||||
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
|
const auto current_pos = PosOf(args.current_id);
|
||||||
|
|
||||||
|
// TODO: constraints ??
|
||||||
|
|
||||||
|
// TODO: use pass type
|
||||||
|
const auto maybe_type_definition =
|
||||||
|
FindTypeDefinition(expr.type.get().name.value, current_pos, executor);
|
||||||
|
if (!maybe_type_definition.has_value()) {
|
||||||
|
return Result::invalid();
|
||||||
|
}
|
||||||
|
const nodes::TypeDefinition *type_definition = maybe_type_definition.value();
|
||||||
|
|
||||||
|
if (!type_definition->type.has_value()) {
|
||||||
|
TypeCheckError(
|
||||||
|
"Type defenition for constructor type not found (declaration only)",
|
||||||
|
current_pos);
|
||||||
|
return Result::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: deal with anniotations, recursive annotations
|
||||||
|
|
||||||
|
// TODO: check that is not typeclass ??
|
||||||
|
|
||||||
|
nodes::Type type = type_definition->type.value();
|
||||||
|
|
||||||
|
// TODO: work with different parametric types: tuple, variant, ...
|
||||||
|
|
||||||
|
if (expr.args.size() == 0) {
|
||||||
|
TypeCheckError("Number of type constructor arguments should be > 0",
|
||||||
|
current_pos);
|
||||||
|
return Result::invalid();
|
||||||
|
// TODO: try return correct type (constructor's type), when possible (not
|
||||||
|
// generic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: work with generics (type_definition->args, ...)
|
||||||
|
|
||||||
|
const auto builtin_type = type.get().ToBuiltin();
|
||||||
|
|
||||||
|
{ // check args size, ets.
|
||||||
|
switch (builtin_type) {
|
||||||
|
case builtin::Type::TUPLE:
|
||||||
|
if (expr.args.size() != type.get().params.size()) {
|
||||||
|
TypeCheckError(
|
||||||
|
"Number of type constructor arguments is different from expected "
|
||||||
|
"(" +
|
||||||
|
std::to_string(expr.args.size()) + " instead of " +
|
||||||
|
std::to_string(type.get().params.size()) + ")",
|
||||||
|
current_pos);
|
||||||
|
return Result::invalid();
|
||||||
|
// TODO: try return correct type (constructor's type), when possible
|
||||||
|
// (not generic)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case builtin::Type::VARIANT:
|
||||||
|
case builtin::Type::OPTIONAL:
|
||||||
|
case builtin::Type::RESULT:
|
||||||
|
case builtin::Type::ERROR:
|
||||||
|
case builtin::Type::FUNCTION:
|
||||||
|
case builtin::Type::NONE:
|
||||||
|
if (expr.args.size() != 1) { // TODO: better to_string
|
||||||
|
TypeCheckError(std::format("Number of type constructor arguments "
|
||||||
|
"should be = 1 (builtin type {})",
|
||||||
|
uint(builtin_type)),
|
||||||
|
current_pos);
|
||||||
|
return Result::invalid();
|
||||||
|
// TODO: try return correct type (constructor's type), when possible
|
||||||
|
// (not generic)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // array, basic types
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builtin::types::get_parameters_count(builtin_type).has_value() &&
|
||||||
|
type.get().params.size() !=
|
||||||
|
builtin::types::get_parameters_count(builtin_type).value()) {
|
||||||
|
TypeCheckError("Wrong amount of parametars for builtin type",
|
||||||
|
current_pos);
|
||||||
|
|
||||||
|
return Result::invalid();
|
||||||
|
// TODO: try return correct type (constructor's type), when possible (not
|
||||||
|
// generic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<size_t> chosen_variant_option; // for VARIANT
|
||||||
|
|
||||||
|
{ // check annotations
|
||||||
|
const auto check_same_annotation =
|
||||||
|
[&expr, this](size_t i,
|
||||||
|
std::optional<const std::string_view> expected_annotation,
|
||||||
|
bool log_errors) {
|
||||||
|
bool is_same = true;
|
||||||
|
|
||||||
|
const auto annotation = expr.args.at(i).first;
|
||||||
|
|
||||||
|
if (annotation.has_value() != expected_annotation.has_value()) {
|
||||||
|
if (log_errors) {
|
||||||
|
TypeCheckError(
|
||||||
|
"Wrong type constructor argument annotation: should be " +
|
||||||
|
std::string{expected_annotation.has_value()
|
||||||
|
? expected_annotation.value()
|
||||||
|
: "[none]"},
|
||||||
|
PosOf(expr.args.at(i).second));
|
||||||
|
}
|
||||||
|
is_same = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotation.has_value() &&
|
||||||
|
annotation.value() != expected_annotation.value()) {
|
||||||
|
if (log_errors) {
|
||||||
|
TypeCheckError("Wrong function argument type annotation: " +
|
||||||
|
annotation.value() + " instead of " +
|
||||||
|
std::string{expected_annotation.value()},
|
||||||
|
PosOf(expr.args.at(i).second));
|
||||||
|
}
|
||||||
|
|
||||||
|
is_same = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_same;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto check_no_annotation = [&expr, this](size_t i, bool log_errors) {
|
||||||
|
if (expr.args.at(i).first.has_value()) {
|
||||||
|
if (log_errors) {
|
||||||
|
TypeCheckError(
|
||||||
|
"Type constructor argument annotation not expected there",
|
||||||
|
PosOf(expr.args.at(i).second));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (builtin_type) {
|
||||||
|
case builtin::Type::TUPLE:
|
||||||
|
for (size_t i = 0; i < expr.args.size(); ++i) {
|
||||||
|
check_same_annotation(i, type.get().params.at(i).get().annotation,
|
||||||
|
true /*log errors*/);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case builtin::Type::VARIANT:
|
||||||
|
// more then one same annotation ??
|
||||||
|
for (size_t i = 0; i < type.get().params.size(); ++i) {
|
||||||
|
if (check_same_annotation(0, type.get().params.at(i).get().annotation,
|
||||||
|
false /*do not log errors*/)) {
|
||||||
|
chosen_variant_option = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chosen_variant_option.has_value() &&
|
||||||
|
!check_no_annotation(0, false /*do not log errors*/)) {
|
||||||
|
TypeCheckError("Wrong type constructor argument annotation in "
|
||||||
|
"constructor of variant type",
|
||||||
|
PosOf(expr.args.front().second));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case builtin::Type::ERROR: // no anotations ??
|
||||||
|
check_same_annotation(0, type.get().params.front().get().annotation,
|
||||||
|
true /*log errors*/);
|
||||||
|
break;
|
||||||
|
case builtin::Type::OPTIONAL:
|
||||||
|
case builtin::Type::RESULT:
|
||||||
|
case builtin::Type::FUNCTION:
|
||||||
|
case builtin::Type::NONE:
|
||||||
|
check_no_annotation(0, true /*log errors*/);
|
||||||
|
break;
|
||||||
|
default: // array, basic types
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // type check args
|
||||||
|
switch (builtin_type) {
|
||||||
|
case builtin::Type::TUPLE:
|
||||||
|
for (size_t i = 0; i < expr.args.size(); ++i) {
|
||||||
|
Run(expr.args.at(i).second,
|
||||||
|
Args{expr.args.at(i).second}.Expect(type.get().params.at(i)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case builtin::Type::VARIANT:
|
||||||
|
if (chosen_variant_option.has_value()) {
|
||||||
|
Run(expr.args.front().second,
|
||||||
|
Args{expr.args.front().second}.Expect(
|
||||||
|
type.get().params.at(chosen_variant_option.value())));
|
||||||
|
} else { // TODO: error, if there is more then one possible variant in
|
||||||
|
// answer
|
||||||
|
nodes::Types possible_options = type.get().params;
|
||||||
|
Run(expr.args.front().second,
|
||||||
|
Args{expr.args.front().second}.Expect(possible_options));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case builtin::Type::OPTIONAL:
|
||||||
|
// first parameter or NULL
|
||||||
|
Run(expr.args.front().second,
|
||||||
|
Args{expr.args.front().second}.Expect(
|
||||||
|
{type.get().params.front(),
|
||||||
|
state<Types>().Primitive(builtin::Type::NULL_OPTION)}));
|
||||||
|
break;
|
||||||
|
case builtin::Type::RESULT:
|
||||||
|
// first parameter or ERROR[second parameter]
|
||||||
|
Run(expr.args.front().second,
|
||||||
|
Args{expr.args.front().second}.Expect(
|
||||||
|
{type.get().params.front(),
|
||||||
|
state<Types>().AddErrorOf(type.get().params.at(1))}));
|
||||||
|
break;
|
||||||
|
case builtin::Type::ERROR:
|
||||||
|
// first parameter
|
||||||
|
Run(expr.args.front().second,
|
||||||
|
Args{expr.args.front().second}.Expect(type.get().params.front()));
|
||||||
|
break;
|
||||||
|
case builtin::Type::FUNCTION:
|
||||||
|
case builtin::Type::NONE:
|
||||||
|
// type itself
|
||||||
|
Run(expr.args.front().second,
|
||||||
|
Args{expr.args.front().second}.Expect(type));
|
||||||
|
break;
|
||||||
|
default: // array, basic types
|
||||||
|
TypeCheckError("Type can't be constructed", current_pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: deduce generic parts in type
|
||||||
|
return TypeCheckFromArgs(expr.type, args, current_pos);
|
||||||
|
// TODO: add <- modifiier to type ??
|
||||||
|
|
||||||
|
} // IN PROGRESS
|
||||||
|
|
||||||
|
} // namespace type_check
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ Result CheckTask<nodes::Match>::operator()(const nodes::Match &expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not expr_result.has_value()) {
|
if (not expr_result.has_value()) {
|
||||||
expr_result = Result{state<Types>().primitive(builtin::Type::UNIT)};
|
expr_result = Result{state<Types>().Primitive(builtin::Type::UNIT)};
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeCheckFromArgs(expr_result.value().Get(), args, current_pos);
|
return TypeCheckFromArgs(expr_result.value().Get(), args, current_pos);
|
||||||
|
|
@ -179,7 +179,7 @@ Result CheckTask<nodes::Loop>::operator()(const nodes::Loop &expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto range_elem_type =
|
const auto range_elem_type =
|
||||||
interval_result.value().Get().get()->get_parameter_proxy(0);
|
interval_result.value().Get().get().params.at(0);
|
||||||
|
|
||||||
variable_result = Run(expr.variable.value(),
|
variable_result = Run(expr.variable.value(),
|
||||||
Args{expr.variable.value()}.Expect(
|
Args{expr.variable.value()}.Expect(
|
||||||
|
|
@ -192,7 +192,7 @@ Result CheckTask<nodes::Loop>::operator()(const nodes::Loop &expr,
|
||||||
return Result::invalid();
|
return Result::invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeCheckFromArgs(state<Types>().add_array_of(expression_result.Get()),
|
return TypeCheckFromArgs(state<Types>().AddArrayOf(expression_result.Get()),
|
||||||
args, current_pos);
|
args, current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,7 +233,7 @@ Result CheckTask<nodes::Container>::CheckArray(const nodes::Container &expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeCheckFromArgs(
|
return TypeCheckFromArgs(
|
||||||
state<Types>().add_array_of(last_expr_result.value().Get()), args,
|
state<Types>().AddArrayOf(last_expr_result.value().Get()), args,
|
||||||
current_pos);
|
current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,7 +260,7 @@ Result CheckTask<nodes::Container>::CheckBlock(const nodes::Container &expr,
|
||||||
Result block_brought_type =
|
Result block_brought_type =
|
||||||
context_exit_type.has_value()
|
context_exit_type.has_value()
|
||||||
? Result(context_exit_type.value())
|
? Result(context_exit_type.value())
|
||||||
: Result(state<Types>().primitive(builtin::Type::UNIT));
|
: Result(state<Types>().Primitive(builtin::Type::UNIT));
|
||||||
|
|
||||||
return TypeCheckFromArgs(block_brought_type.Get(), args, current_pos);
|
return TypeCheckFromArgs(block_brought_type.Get(), args, current_pos);
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +305,7 @@ Result CheckTask<nodes::Return>::operator()(const nodes::Return &expr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeCheckFromArgs(state<Types>().primitive(builtin::Type::UNIT), args,
|
return TypeCheckFromArgs(state<Types>().Primitive(builtin::Type::UNIT), args,
|
||||||
current_pos);
|
current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,15 +324,14 @@ CheckTask<nodes::NameDefinition>::operator()(const nodes::NameDefinition &expr,
|
||||||
|
|
||||||
// assigned type shold be one of <-, <>, -- (can't be ->)
|
// assigned type shold be one of <-, <>, -- (can't be ->)
|
||||||
const auto variable_type = args.passed().value();
|
const auto variable_type = args.passed().value();
|
||||||
if (nodes::utils::modifier_contains_OUT(
|
if (nodes::utils::modifier_contains_OUT(variable_type.get().modifier)) {
|
||||||
variable_type.get()->get_modifier())) {
|
|
||||||
// TODO: modifiers are nto fully implemented yet
|
// TODO: modifiers are nto fully implemented yet
|
||||||
TypeCheckError("Variable can't be assigned from out (->) value",
|
TypeCheckError("Variable can't be assigned from out (->) value",
|
||||||
current_pos);
|
current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// variable is accessible by reference by default
|
// variable is accessible by reference by default
|
||||||
state<Types>().add_modification_of(variable_type, nodes::Modifier::REF);
|
state<Types>().AddModificationOf(variable_type, nodes::Modifier::REF);
|
||||||
|
|
||||||
// TODO: warning if name is same to package prefix, function prefix, etc. ??
|
// TODO: warning if name is same to package prefix, function prefix, etc. ??
|
||||||
if (not state<State>().InsertVariable(expr.name.value, variable_type,
|
if (not state<State>().InsertVariable(expr.name.value, variable_type,
|
||||||
|
|
@ -341,7 +340,7 @@ CheckTask<nodes::NameDefinition>::operator()(const nodes::NameDefinition &expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return BOOL (as any := / =: expression) == true
|
// Return BOOL (as any := / =: expression) == true
|
||||||
return TypeCheckFromArgs(state<Types>().primitive(builtin::Type::BOOL), args,
|
return TypeCheckFromArgs(state<Types>().Primitive(builtin::Type::BOOL), args,
|
||||||
current_pos);
|
current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,8 +369,8 @@ Result CheckTask<nodes::Access>::CheckArrayAccess(const nodes::Access &expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: 0 - type of array
|
// NOTE: 0 - type of array
|
||||||
return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(0),
|
return TypeCheckFromArgs(value_result.Get().get().params.front(), args,
|
||||||
args, current_pos);
|
current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckTask<nodes::Access>::CheckTupleAccess(const nodes::Access &expr,
|
Result CheckTask<nodes::Access>::CheckTupleAccess(const nodes::Access &expr,
|
||||||
|
|
@ -395,8 +394,8 @@ Result CheckTask<nodes::Access>::CheckTupleAccess(const nodes::Access &expr,
|
||||||
.get<size_t>() // Index type
|
.get<size_t>() // Index type
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
return TypeCheckFromArgs(value_result.Get().get()->get_parameter_proxy(index),
|
return TypeCheckFromArgs(value_result.Get().get().params.at(index), args,
|
||||||
args, current_pos);
|
current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckTask<nodes::Access>::operator()(const nodes::Access &expr,
|
Result CheckTask<nodes::Access>::operator()(const nodes::Access &expr,
|
||||||
|
|
@ -418,7 +417,7 @@ Result CheckTask<nodes::LoopControl>::operator()(const nodes::LoopControl &expr,
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
return TypeCheckFromArgs(state<Types>().primitive(builtin::Type::UNIT), args,
|
return TypeCheckFromArgs(state<Types>().Primitive(builtin::Type::UNIT), args,
|
||||||
current_pos);
|
current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -432,8 +431,8 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
|
||||||
// TODO: check expect for parametrized type without parameters
|
// TODO: check expect for parametrized type without parameters
|
||||||
auto given_args = nodes::utils::is_suffix_modifier(expr.modifier)
|
auto given_args = nodes::utils::is_suffix_modifier(expr.modifier)
|
||||||
? Args{expr.expr}.Expect({
|
? Args{expr.expr}.Expect({
|
||||||
state<Types>().primitive(builtin::Type::OPTIONAL),
|
state<Types>().Primitive(builtin::Type::OPTIONAL),
|
||||||
state<Types>().primitive(builtin::Type::RESULT),
|
state<Types>().Primitive(builtin::Type::RESULT),
|
||||||
})
|
})
|
||||||
: Args{expr.expr};
|
: Args{expr.expr};
|
||||||
|
|
||||||
|
|
@ -444,14 +443,13 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodes::utils::is_suffix_modifier(expr.modifier)) { // optional, result
|
if (nodes::utils::is_suffix_modifier(expr.modifier)) { // optional, result
|
||||||
switch (modified_result.Get().get()->to_builtin()) {
|
switch (modified_result.Get().get().ToBuiltin()) {
|
||||||
case builtin::Type::OPTIONAL: { // '?' - open optional / result in ->
|
case builtin::Type::OPTIONAL: { // '?' - open optional / result in ->
|
||||||
// (execute
|
// (execute
|
||||||
// or not execute pattern matching expression)
|
// or not execute pattern matching expression)
|
||||||
// / (value / return)
|
// / (value / return)
|
||||||
|
|
||||||
const auto underlying_type =
|
const auto underlying_type = modified_result.Get().get().params.front();
|
||||||
modified_result.Get().get()->get_parameter_proxy(0);
|
|
||||||
|
|
||||||
// TODO: alternative for bring in future
|
// TODO: alternative for bring in future
|
||||||
if (not state<State>().ReturnType(underlying_type)) {
|
if (not state<State>().ReturnType(underlying_type)) {
|
||||||
|
|
@ -463,8 +461,7 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
|
||||||
}
|
}
|
||||||
case builtin::Type::RESULT: { // '!' - open optional / result -> value /
|
case builtin::Type::RESULT: { // '!' - open optional / result -> value /
|
||||||
// panic
|
// panic
|
||||||
const auto underlying_type =
|
const auto underlying_type = modified_result.Get().get().params.front();
|
||||||
modified_result.Get().get()->get_parameter_proxy(0);
|
|
||||||
|
|
||||||
modified_result.Set(underlying_type);
|
modified_result.Set(underlying_type);
|
||||||
break;
|
break;
|
||||||
|
|
@ -477,8 +474,8 @@ Result CheckTask<nodes::ModifierExpression>::operator()(
|
||||||
// NOTE: other modifiers applied instead of current one
|
// NOTE: other modifiers applied instead of current one
|
||||||
|
|
||||||
// TODO: check that modification is possible (not all casts are possible)
|
// TODO: check that modification is possible (not all casts are possible)
|
||||||
modified_result.Set(state<Types>().add_modification_of(
|
modified_result.Set(
|
||||||
modified_result.Get(), expr.modifier));
|
state<Types>().AddModificationOf(modified_result.Get(), expr.modifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeCheckFromArgs(modified_result.Get(), args, current_pos);
|
return TypeCheckFromArgs(modified_result.Get(), args, current_pos);
|
||||||
|
|
@ -510,7 +507,7 @@ Result CheckTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto expected_type = args.expected().front();
|
const auto expected_type = args.expected().front();
|
||||||
if (!expected_type.get()->is_builtin(builtin::Type::FUNCTION)) {
|
if (!expected_type.get().IsBuiltin(builtin::Type::FUNCTION)) {
|
||||||
TypeCheckError("Type of lambda function should be function", current_pos);
|
TypeCheckError("Type of lambda function should be function", current_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -539,7 +536,7 @@ Result CheckTask<nodes::Lambda>::operator()(const nodes::Lambda &expr,
|
||||||
|
|
||||||
for (size_t i = 0; i < expr.args.size(); ++i) {
|
for (size_t i = 0; i < expr.args.size(); ++i) {
|
||||||
if (not state<State>().InsertVariable(expr.args.at(i).value,
|
if (not state<State>().InsertVariable(expr.args.at(i).value,
|
||||||
state<Types>().add_generic_type(),
|
state<Types>().AddGenericType(),
|
||||||
nodes::NameDefinition::Kind::LET)) {
|
nodes::NameDefinition::Kind::LET)) {
|
||||||
// TODO: choose LET / CONST
|
// TODO: choose LET / CONST
|
||||||
TypeCheckError("Variable is already defined in this context",
|
TypeCheckError("Variable is already defined in this context",
|
||||||
|
|
@ -580,7 +577,7 @@ Result CheckTask<nodes::Extra>::operator()(const nodes::Extra &, const Args &) {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
return Result(state<Types>().primitive(builtin::Type::UNIT));
|
return Result(state<Types>().Primitive(builtin::Type::UNIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: CHECKED
|
// NOTE: CHECKED
|
||||||
|
|
@ -590,7 +587,7 @@ Result CheckTask<nodes::EmptyLines>::operator()(const nodes::EmptyLines &,
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
return Result(state<Types>().primitive(builtin::Type::UNIT));
|
return Result(state<Types>().Primitive(builtin::Type::UNIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace type_check
|
} // namespace type_check
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ nodes::Type CheckSameToPassTypeInArgs(nodes::Type type, const Args &args,
|
||||||
logc.Error<Log::kProc>({{message}} /* TODO: node */);
|
logc.Error<Log::kProc>({{message}} /* TODO: node */);
|
||||||
}
|
}
|
||||||
|
|
||||||
return executor.state<Types>().primitive(builtin::Type::BOOL);
|
return executor.state<Types>().Primitive(builtin::Type::BOOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckTypeSameToExpected(nodes::Type type, const Args &args,
|
Result CheckTypeSameToExpected(nodes::Type type, const Args &args,
|
||||||
|
|
@ -99,8 +99,8 @@ std::optional<nodes::Type> UnfoldUserDefinedType(nodes::Type type,
|
||||||
bool handle_errors) {
|
bool handle_errors) {
|
||||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
const auto maybe_type_definition = FindTypeDefinition(
|
const auto maybe_type_definition =
|
||||||
type.get()->get_name()->value, pos, executor, handle_errors);
|
FindTypeDefinition(type.get().name.value, pos, executor, handle_errors);
|
||||||
|
|
||||||
if (!maybe_type_definition.has_value()) {
|
if (!maybe_type_definition.has_value()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
@ -110,13 +110,13 @@ std::optional<nodes::Type> UnfoldUserDefinedType(nodes::Type type,
|
||||||
if (handle_errors) {
|
if (handle_errors) {
|
||||||
logc.Error<Log::kProc>({{std::format(
|
logc.Error<Log::kProc>({{std::format(
|
||||||
"Only type declaration found for type {} (type is not defined)",
|
"Only type declaration found for type {} (type is not defined)",
|
||||||
type.get()->get_name()->value)}} /* TODO: node*/);
|
type.get().name.value)}} /* TODO: node*/);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: perform type args substitution
|
// TODO: perform type args substitution
|
||||||
logc.Require<Log::kProc>(type.get()->parameters_size() == 0,
|
logc.Require<Log::kProc>(type.get().params.size() == 0,
|
||||||
{{"Unfold of generic type is not supported (yet)"}});
|
{{"Unfold of generic type is not supported (yet)"}});
|
||||||
//
|
//
|
||||||
return maybe_type_definition.value()->type.value();
|
return maybe_type_definition.value()->type.value();
|
||||||
|
|
@ -127,10 +127,10 @@ FieldTypeByName(nodes::Type type, const std::string &field,
|
||||||
const utils::Pos &pos, Executor &executor, bool handle_errors) {
|
const utils::Pos &pos, Executor &executor, bool handle_errors) {
|
||||||
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
Log::Context logc(executor.log(), Log::Area::kTypeCheck);
|
||||||
|
|
||||||
switch (type.get()->to_builtin()) {
|
switch (type.get().ToBuiltin()) {
|
||||||
case builtin::Type::TUPLE: { // access field
|
case builtin::Type::TUPLE: { // access field
|
||||||
|
|
||||||
const auto maybe_field = type.get()->get_parameter_proxy_by_name(field);
|
const auto maybe_field = type.get().ParamByName(field);
|
||||||
|
|
||||||
if (not maybe_field.has_value() and handle_errors) {
|
if (not maybe_field.has_value() and handle_errors) {
|
||||||
// TODO: pass unfolded type name to log it ??
|
// TODO: pass unfolded type name to log it ??
|
||||||
|
|
@ -159,7 +159,7 @@ FieldTypeByName(nodes::Type type, const std::string &field,
|
||||||
logc.Error<Log::kProc>(
|
logc.Error<Log::kProc>(
|
||||||
{{std::format("Type {} has no accessible fields by definition",
|
{{std::format("Type {} has no accessible fields by definition",
|
||||||
builtin::types::to_string(
|
builtin::types::to_string(
|
||||||
type.get()->to_builtin()))}} /* TODO: node */);
|
type.get().ToBuiltin()))}} /* TODO: node */);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue