type_check_visitor part

This commit is contained in:
ProgramSnail 2023-05-03 15:03:57 +03:00
parent d13faf104d
commit 94ef8702fb
11 changed files with 496 additions and 288 deletions

View file

@ -23,7 +23,7 @@ struct TypeUsage {
struct Parameter {
std::string type;
std::vector<interpreter::tokens::TypeclassExpression*> typeclass_nodes;
std::vector<interpreter::tokens::ParametrizedTypeclass*> typeclass_nodes;
};
struct AbstractType {

View file

@ -102,7 +102,6 @@ private:
// Typeclass
// // void Visit(TypeclassExpression* node) override;
// // void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
@ -124,7 +123,7 @@ private:
private:
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
bool is_in_statement = false;
bool is_in_statement_ = false;
std::any current_info_;
};

View file

@ -101,8 +101,7 @@ private:
// Typeclass
void Visit(TypeclassExpression* node) override;
// // void Visit(ParametrizedTypeclass* node) override;
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type

View file

@ -101,7 +101,6 @@ private:
// Typeclass
void Visit(TypeclassExpression* node) override;
void Visit(ParametrizedTypeclass* node) override;
// Typeclass & Type
@ -126,6 +125,9 @@ private:
utils::IdType current_type_;
std::optional<utils::IdType> returned_type_;
std::optional<bool> is_const_definition_;
bool is_in_statement_ = false;
};
} // namespace interpreter

View file

@ -1,7 +1,7 @@
#pragma once
#include <cstddef>
#include <string>
#include <utility>
#include <vector>
#include <unordered_map>
@ -14,6 +14,28 @@ namespace info {
// TODO: remember about typespointers
class TypeInfoContextManager {
public:
template<typename T>
utils::IdType AddType(const T&& type) {
return type_manager_.AddType(std::forward(type));
}
template<typename T>
std::optional<T*> GetType(utils::IdType type_id) {
return type_manager_.GetType<T>(type_id);
}
type::Type* GetAnyType(utils::IdType type_id) {
return type_manager_.GetAnyType(type_id);
}
bool AddTypeRequirement(utils::IdType type, utils::IdType requrement) {
return type_manager_.AddTypeRequirement(type, requrement);
}
bool EqualTypes(utils::IdType first_type, utils::IdType second_type) {
return type_manager_.EqualTypes(first_type, second_type);
}
type::TypeManager* GetTypeManager() {
return &type_manager_;
}
@ -35,9 +57,9 @@ public:
}
// TODO: variable modifiers
bool DefineVariable(const std::string& name, utils::IdType type_id) {
bool DefineVariable(const std::string& name, utils::IdType type_id, bool is_const) {
// check in previous contexts ??
return contexts_.back().DefineVariable(name, type_id);
return contexts_.back().DefineVariable(name, type_id, is_const);
}
bool DefineLocalAbstractType(const std::string& name, utils::IdType type_id) {
@ -59,15 +81,15 @@ public:
}
void EnterVariableContext(const std::string& name,
utils::IdType type_id) { // for variable namespaces, for loops
utils::IdType type_id, bool is_const) { // for variable namespaces, for loops
contexts_.push_back(false);
DefineVariable(name, type_id);
DefineVariable(name, type_id, is_const);
}
std::optional<utils::IdType> GetVariableType(const std::string& name) {
std::optional<std::pair<utils::IdType, bool>> GetVariableInfo(const std::string& name) {
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
auto maybe_type = contexts_[i].GetVariableType(name);
auto maybe_type = contexts_[i].GetVariableInfo(name);
if (maybe_type.has_value()) {
return maybe_type.value();
}
@ -90,11 +112,11 @@ private:
public:
Context(bool hide_previous) : hide_previous_(hide_previous) {}
bool DefineVariable(const std::string& name, utils::IdType type_id) {
if (local_abstract_types_.count(name) > 0) {
bool DefineVariable(const std::string& name, utils::IdType type_id, bool is_const) {
if (variables_.count(name) > 0) {
return false;
}
local_abstract_types_[name] = type_id;
variables_[name] = {type_id, is_const};
return true;
}
@ -110,7 +132,7 @@ private:
return variables_.erase(name);
}
std::optional<utils::IdType> GetVariableType(const std::string& name) {
std::optional<std::pair<utils::IdType, bool>> GetVariableInfo(const std::string& name) {
auto variable_iter = variables_.find(name);
if (variable_iter == variables_.end()) {
@ -133,7 +155,7 @@ private:
bool IsFirst() { return hide_previous_; }
private:
bool hide_previous_;
std::unordered_map<std::string, utils::IdType> variables_;
std::unordered_map<std::string, std::pair<utils::IdType, bool>> variables_;
std::unordered_map<std::string, utils::IdType> local_abstract_types_;
};

View file

@ -5,6 +5,7 @@
#include <variant>
#include <memory>
#include <unordered_set>
#include <unordered_map>
// for clangd
#include "utils.hpp"
@ -25,6 +26,7 @@ public:
}
}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const AbstractType& type) const;
bool operator<(const AbstractType& type) const;
bool operator>(const AbstractType& type) const;
@ -41,9 +43,14 @@ public:
TypeManager* type_manager)
: type_id_(type_id), type_(type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const DefinedType& type) const;
bool operator<(const DefinedType& type) const;
bool operator>(const DefinedType& type) const;
utils::IdType GetTypeId() {
return type_id_;
}
private:
utils::IdType type_id_; // in defined types
utils::IdType type_; // in types manager, created using context types (if specific type)
@ -67,9 +74,14 @@ public:
TypeManager* type_manager)
: name_(name), fields_(fields), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const TupleType& type) const;
bool operator<(const TupleType& type) const;
bool operator>(const TupleType& type) const;
const std::vector<std::pair<std::optional<std::string>, utils::IdType>>& GetFields() const {
return fields_;
}
private:
std::optional<std::string> name_;
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields_;
@ -83,9 +95,14 @@ public:
const std::vector<TupleType>& constructors)
: name_(name), constructors_(constructors){}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const VariantType& type) const;
bool operator<(const VariantType& type) const;
bool operator>(const VariantType& type) const;
const std::vector<TupleType>& GetConstructors() const {
return constructors_;
}
private:
std::optional<std::string> name_;
std::vector<TupleType> constructors_;
@ -98,6 +115,7 @@ public:
TypeManager* type_manager)
: type_(type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const OptionalType& type) const;
bool operator<(const OptionalType& type) const;
bool operator>(const OptionalType& type) const;
@ -114,6 +132,7 @@ public:
TypeManager* type_manager)
: references_(references), type_(type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const ReferenceToType& type) const;
bool operator<(const ReferenceToType& type) const;
bool operator>(const ReferenceToType& type) const;
@ -133,6 +152,7 @@ public:
TypeManager* type_manager)
: argument_types_(argument_types), return_type_(return_type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const FunctionType& type) const;
bool operator<(const FunctionType& type) const;
bool operator>(const FunctionType& type) const;
@ -150,9 +170,14 @@ public:
TypeManager* type_manager)
: size_(size), elements_type_(elements_type), type_manager_(type_manager) {}
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const ArrayType& type) const;
bool operator<(const ArrayType& type) const;
bool operator>(const ArrayType& type) const;
utils::IdType GetElementsType() {
return elements_type_;
}
private:
size_t size_; // = 0 for dynamic
utils::IdType elements_type_;
@ -164,8 +189,9 @@ public:
template<typename T>
explicit Type(T&& type) : type_(std::forward(type)) {}
bool Same(const Type& type) const; // some rule exceptions ??
bool operator<(const Type& type) const; // TODO: some rule exceptions ??
std::optional<utils::IdType> InContext(const std::unordered_map<std::string, utils::IdType>& context);
bool Same(const Type& type) const;
bool operator<(const Type& type) const; // TODO: rule exceptions
bool operator>(const Type& type) const;
private:
std::variant<AbstractType,
@ -186,10 +212,10 @@ public:
template<typename T>
std::optional<T*> GetType(utils::IdType type_id);
std::optional<Type*> GetAnyType(utils::IdType type_id);
Type* GetAnyType(utils::IdType type_id);
void AddTypeRequirement(utils::IdType type, utils::IdType requrement); // TODO
void EqualTypes(utils::IdType first_type, utils::IdType second_type); // TODO
bool AddTypeRequirement(utils::IdType type, utils::IdType requrement);
bool EqualTypes(utils::IdType first_type, utils::IdType second_type);
private:
std::vector<info::type::Type> types_;
};

View file

@ -34,18 +34,18 @@ void FindSymbolsVisitor::Visit(Namespace* node) {
// TODO: add imported symbols to symbol table (global info)
void FindSymbolsVisitor::Visit(ImportStatement* node) {
is_in_statement = true;
is_in_statement_ = true;
info::definition::Import info;
info.module_name = node->module_name;
info.symbols = node->symbols;
namespace_visitor_.AddImport(std::move(info), node->name);
is_in_statement = false;
is_in_statement_ = false;
}
void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) {
is_in_statement = true;
is_in_statement_ = true;
info::definition::Type info;
@ -73,12 +73,12 @@ void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) {
node->type_id_ = namespace_visitor_.AddType(node->type, std::move(info));
is_in_statement = false;
is_in_statement_ = false;
}
void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
bool was_in_statement = is_in_statement;
is_in_statement = true;
bool was_in_statement = is_in_statement_;
is_in_statement_ = true;
info::definition::FunctionDeclaration info;
@ -100,12 +100,12 @@ void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
current_info_ = std::move(info);
} else {
node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name.name, std::move(info));
is_in_statement = false;
is_in_statement_ = false;
}
}
void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) {
is_in_statement = true;
is_in_statement_ = true;
info::definition::FunctionDefinition info;
@ -120,11 +120,11 @@ void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) {
node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name.name, std::move(info));
is_in_statement = false;
is_in_statement_ = false;
}
void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
is_in_statement = true;
is_in_statement_ = true;
info::definition::Type info;
@ -151,11 +151,11 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
node->type_id_ = namespace_visitor_.AddType(type, std::move(info));
is_in_statement = false;
is_in_statement_ = false;
}
void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
is_in_statement = true;
is_in_statement_ = true;
info::definition::AbstractType info;
@ -176,11 +176,11 @@ void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
node->type_id_ = namespace_visitor_.AddAbstractType(type, std::move(info));
is_in_statement = false;
is_in_statement_ = false;
}
void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
is_in_statement = true;
is_in_statement_ = true;
info::definition::Typeclass info;
@ -202,7 +202,7 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
node->typeclass_id_ = namespace_visitor_.AddTypeclass(definition->type.get()->type, std::move(info));
is_in_statement = false;
is_in_statement_ = false;
}
// Definition parts

View file

@ -5,17 +5,6 @@
namespace interpreter {
const std::string& NameFromTypeSubExpression(const TypeSubExpression& type) {
if (std::holds_alternative<std::unique_ptr<std::string>>(type)) {
return *std::get<std::unique_ptr<std::string>>(type);
} else if (std::holds_alternative<std::unique_ptr<ParametrizedType>>(type)) {
return std::get<std::unique_ptr<ParametrizedType>>(type)->type;
}
error_handling::HandleInternalError("Empty variant", "NameFromTypeSubExpression");
exit(1); // TODO: better decision ??
}
// Namespaces, partitions -----------------
void LinkSymbolsVisitor::Visit(Namespace* node) {
@ -49,23 +38,25 @@ void LinkSymbolsVisitor::Visit(Namespace* node) {
// Type
// TODO: link internal stages
// TODO: find constructors ?
void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
std::vector<std::string> path;
path.reserve(node->path.size());
for (auto& path_type : node->path) {
path.push_back(NameFromTypeSubExpression(path_type));
path.push_back(path_type.type);
}
node->type_id_ = namespace_visitor_.FindType(path, NameFromTypeSubExpression(node->type));
node->type_id_ = namespace_visitor_.FindType(path, NameFromTypeSubExpression(node->type));
node->type_id_ = namespace_visitor_.FindType(path, node->type.type);
node->constructor_id_ = namespace_visitor_.FindConstructor(path, node->type.type);
if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) {
error_handling::HandleTypecheckError("Type or constructor not found");
}
if (node->type_id_.has_value()) {
node->type.type_id_ = node->type_id_.value();
}
std::optional<info::definition::Namespace*> maybe_type_namespace = namespace_visitor_.FindNamespace(path);
if (maybe_type_namespace.has_value()) {
info::definition::Namespace* type_namespace = maybe_type_namespace.value();
@ -73,9 +64,9 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
for (ssize_t i = (ssize_t)node->path.size(); i >= 0; --i) {
info::definition::Namespace* parent_namespace = type_namespace->parent_namespace;
auto maybe_type = parent_namespace->types.find(type_namespace->type_name); // TODO: make method ??
if (maybe_type.has_value()) {
node->path[i]->
auto type_iter = parent_namespace->types.find(type_namespace->type_name);
if (type_iter != parent_namespace->types.end()) {
node->path[i].type_id_ = type_iter->second;
}
if (parent_namespace == nullptr) {
@ -89,18 +80,8 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
// Typeclass
void LinkSymbolsVisitor::Visit(TypeclassExpression* node) { // TODO: check
std::string typeclass;
if (std::holds_alternative<std::unique_ptr<std::string>>(node->typeclass)) {
typeclass = *std::get<std::unique_ptr<std::string>>(node->typeclass);
} else if (std::holds_alternative<std::unique_ptr<ParametrizedTypeclass>>(node->typeclass)) {
typeclass = std::get<std::unique_ptr<ParametrizedTypeclass>>(node->typeclass)->typeclass;
} else {
// error
}
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclass(typeclass);
void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) { // TODO: check
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclass(node->typeclass);
if (maybe_typeclass.has_value()) {
node->typeclass_id_ = maybe_typeclass.value();

View file

@ -63,33 +63,55 @@ void TypeCheckVisitor::Visit(Namespace* node) {
void TypeCheckVisitor::Visit(ImportStatement* node) {}
// TODO
// + TODO: let bindings for abstract types
void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) {
// check, that all paramaters used ??
utils::IdType type = context_manager_.AddType(info::type::DefinedType {node->type_id_}); // ??
Visit(node->value.get());
context_manager_.EqualTypes(type, current_type_);
if (!is_in_statement_) { // do nothing if alias is not applied
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
return;
}
// TODO: parameter requirments
for (auto& parameter : node->parameters) {
current_type_ = context_manager_.AddType(info::type::AbstractType(parameter, /*TODO*/{}));
context_manager_.DefineLocalAbstractType(parameter, current_type_);
}
Visit(node->value.get());
}
// TODO: remove variable on move, etc.
void TypeCheckVisitor::Visit(VariableDefinitionStatement* node) {
// TODO: remove variable on move
// TODO: add modifiers
is_in_statement_ = true;
Visitor::Visit(node->value);
// current_type from value automatically passed to name definitions
is_const_definition_ = (node->assignment_modifier == VariableDefinitionStatement::Const);
Visitor::Visit(node->name);
is_const_definition_ = std::nullopt;
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
is_in_statement_ = false;
}
void TypeCheckVisitor::Visit(FunctionDeclaration* node) {
// check later that function definition requirements are satisfied
bool was_in_statement = is_in_statement_;
is_in_statement_ = true;
// check declaration correctness ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
if (!was_in_statement) {
is_in_statement_ = false;
}
}
// TODO
void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
// check, that all paramaters used ??
is_in_statement_ = true;
context_manager_.EnterContext();
info::definition::Function* function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_);
@ -100,70 +122,114 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
info::definition::FunctionDeclaration& declaration = function_info->declaration.value();
declaration.parameters
for (auto parameter : declaration.parameters) {
std::vector<utils::IdType> requirements;
requirements.reserve(parameter.typeclass_nodes.size());
for (ParametrizedTypeclass* typeclass : parameter.typeclass_nodes) {
requirements.push_back(typeclass->typeclass_id_);
}
// TODO: add recursive typeclasses from typeclass tree
current_type_ = context_manager_.AddType(info::type::AbstractType(parameter.type, requirements)); // TODO: move requirements
if (!context_manager_.DefineLocalAbstractType(parameter.type, current_type_)) {
error_handling::HandleTypecheckError("Can't define function parameter type: type redefinition");
}
}
// Visit(node->definition.get()); // ??
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
context_manager_.DefineVariable(node->definition->arguments[i].name,
declaration.argument_types[i]);
current_type_ = ConstructAnyType(declaration.argument_types[i]); // TODO
if (!context_manager_.DefineVariable(node->definition->arguments[i].name, current_type_)) {
error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition");
}
}
Visitor::Visit(node->value);
context_manager_.EqualTypes(declaration.argument_types.back(), current_type_); // return type ??
if (!context_manager_.EqualTypes(ConstructAnyType(declaration.argument_types.back()), current_type_)) {
error_handling::HandleTypecheckError("Wrong function return type");
}
context_manager_.ExitContext();
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
is_in_statement_ = false;
}
// TODO ??
void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
// TODO: add modifiers
// check, that all paramaters used ??
// TODO: defined type typeclasses
is_in_statement_ = true;
// check definition correctness ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
is_in_statement_ = false;
}
void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
utils::IdType type = context_manager_.AddType(info::type::DefinedType );
is_in_statement_ = true;
// Visit(node->type.get()); ??
for (auto& typeclass : node->type->typeclasses) { // TODO
Visitor::Visit(typeclass);
context_manager_.AddTypeRequirement(type, current_type_);
// TODO: basic types ??
std::vector<utils::IdType> requirements;
requirements.reserve(node->type->typeclasses.size());
for (auto& typeclass : node->type->typeclasses) {
requirements.push_back(typeclass->typeclass_id_);
}
// TODO: add recursive typeclasses from typeclass tree
current_type_ = context_manager_.AddType(info::type::AbstractType(node->type->type, requirements));
if (!context_manager_.DefineLocalAbstractType(node->type->type, current_type_)) {
error_handling::HandleTypecheckError("Can't define basic/bastract type: type redefinition");
}
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
is_in_statement_ = false;
}
void TypeCheckVisitor::Visit(TypeclassDefinitionStatement* node) {
// check, that all paramaters used ??
// TODO: needed ??
is_in_statement_ = true;
// check definition correctness ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
is_in_statement_ = false;
}
// Definition parts
void TypeCheckVisitor::Visit(FunctionDefinition* node) {
// TODO: needed ??
// check definition correctness ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
void TypeCheckVisitor::Visit(TypeDefinition* node) {
// TODO: needed ??
// check definition correctness ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// used on upper levels
void TypeCheckVisitor::Visit(AnyAnnotatedType* node) {
// check definition correctness ??
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
}
// Flow control -----------------
// TODO
void Visitor::Visit(TypeConstructorPatternParameter* node) {
if (node->name.has_value()) {
Visit(&node->name.value());
}
Visit(node->value);
}
// TODO
void Visitor::Visit(TypeConstructorPattern* node) {
Visit(node->constructor.get());
for (auto& parameter : node->parameters) {
Visit(&parameter);
}
}
void TypeCheckVisitor::Visit(MatchCase* node) {
Visitor::Visit(node->value); // TODO: literal & name instead of expression
if (node->condition.has_value()) {
@ -215,7 +281,8 @@ void TypeCheckVisitor::Visit(Condition* node) { // TODO return variant type ?? (
context_manager_.EqualTypes(type, current_type_);
current_type_ = type;
} else {
current_type_ = context_manager_.AddType(info::type::OptionalType {type});
current_type_ = context_manager_.AddType(
info::type::OptionalType(type, context_manager_.GetTypeManager()));
}
}
@ -225,10 +292,8 @@ void TypeCheckVisitor::Visit(DoWhileLoop* node) {
Visitor::Visit(node->statement);
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
current_type_ = context_manager_.AddType(
info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()));
}
void TypeCheckVisitor::Visit(WhileLoop* node) {
@ -237,40 +302,32 @@ void TypeCheckVisitor::Visit(WhileLoop* node) {
Visitor::Visit(node->statement);
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
current_type_ = context_manager_.AddType(
info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()));
}
void TypeCheckVisitor::Visit(ForLoop* node) {
Visitor::Visit(node->interval);
std::optional<info::type::ArrayType*> maybe_interval_type = context_manager_.GetType<info::type::ArrayType>(current_type_);
if (!std::holds_alternative<info::type::ArrayType>(context_manager_.GetType(current_type_))) {
if (!maybe_interval_type.has_value()) {
error_handling::HandleTypecheckError("For loop interval type mismatch");
}
info::type::ArrayType type_value =
std::get<info::type::ArrayType>(context_manager_.GetType(current_type_));
current_type_ = context_manager_.AddType(type_value.elements_type);
Visitor::Visit(node->variable);
current_type_ = context_manager_.AddType(maybe_interval_type.value()->GetElementsType());
Visitor::Visit(node->variable); // type passed to variable definition
Visitor::Visit(node->statement);
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
current_type_ = context_manager_.AddType(
info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()));
}
void TypeCheckVisitor::Visit(LoopLoop* node) {
Visitor::Visit(node->statement);
info::type::ArrayType type;
type.size = 0;
type.elements_type = current_type_;
current_type_ = context_manager_.AddType(type);
current_type_ = context_manager_.AddType(
info::type::ArrayType(0, current_type_, context_manager_.GetTypeManager()));
}
// Statements, expressions, blocks, etc. -----------------
@ -288,7 +345,9 @@ void TypeCheckVisitor::Visit(Block* node) { // TODO return variant type ?? (prob
type = returned_type_.value();
is_first_returned_type = false;
} else {
context_manager_.EqualTypes(type, returned_type_.value());
if (!context_manager_.EqualTypes(type, returned_type_.value())) {
error_handling::HandleTypecheckError("Different return types in block");
}
}
}
}
@ -325,19 +384,17 @@ void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) {
error_handling::HandleTypecheckError("Operator wrong argument count");
}
if (operator_info->definition.has_value()) {
if (!operator_info->declaration.has_value() || !operator_info->definition.has_value()) {
error_handling::HandleTypecheckError("Operator declaration or definition not found");
}
Visitor::Visit(node->left_expression);
context_manager_.AddTypeRequirement(current_type_,
context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[0]}));
ConstructAnyType(operator_info->declaration.value().argument_types[0])); // TODO
Visitor::Visit(node->right_expression);
context_manager_.AddTypeRequirement(current_type_,
context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[1]}));
} else if (operator_info->declaration.has_value()) {
// TODO: get argument types
} else {
error_handling::HandleInternalError("Operator definition and declaration both not found", "TypeCheckVisitor");
}
ConstructAnyType(operator_info->declaration.value().argument_types[1])); // TODO
}
@ -355,24 +412,20 @@ void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) {
error_handling::HandleTypecheckError("Operator wrong argument count");
}
if (operator_info->definition.has_value()) {
if (!operator_info->declaration.has_value() || !operator_info->definition.has_value()) {
error_handling::HandleTypecheckError("Operator declaration or definition not found");
}
Visitor::Visit(node->expression);
context_manager_.AddTypeRequirement(current_type_,
context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[0]}));
} else if (operator_info->declaration.has_value()) {
// TODO: get argument type
} else {
error_handling::HandleInternalError("Operator definition and declaration both not found", "TypeCheckVisitor");
}
ConstructAnyType(operator_info->declaration.value().argument_types[0])); // TODO
}
void TypeCheckVisitor::Visit(ReferenceExpression* node) {
Visit(node->expression.get());
info::type::ReferenceToType type;
type.references = node->references;
type.type = current_type_;
current_type_ = context_manager_.AddType(type);
current_type_ = context_manager_.AddType(
info::type::ReferenceToType(node->references, current_type_, context_manager_.GetTypeManager()));
}
void TypeCheckVisitor::Visit(AccessExpression* node) {
@ -381,22 +434,34 @@ void TypeCheckVisitor::Visit(AccessExpression* node) {
// TODO: separate type for counting ?
Visitor::Visit(node->name.get());
if (!std::holds_alternative<info::type::ArrayType>(context_manager_.GetType(current_type_))) {
std::optional<info::type::ArrayType*> maybe_type_value = context_manager_.GetType<info::type::ArrayType>(current_type_);
if (!maybe_type_value.has_value()) {
error_handling::HandleTypecheckError("Access type mismatch");
}
info::type::ArrayType type_value =
std::get<info::type::ArrayType>(context_manager_.GetType(current_type_));
current_type_ = context_manager_.AddType(type_value.elements_type);
current_type_ = maybe_type_value.value()->GetElementsType();
}
// Other Expressions
// -------------------------- TODO --------------------------
// TODO
void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
// TODO: add function paramaters
Visit(node->name.get());
if (node->prefix.has_value()) {
if (std::holds_alternative<std::unique_ptr<SubExpressionToken>>(node->prefix.value())) {
Visitor::Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->prefix.value()));
// TODO
} else if (std::holds_alternative<std::unique_ptr<TypeExpression>>(node->prefix.value())) {
Visit(std::get<std::unique_ptr<TypeExpression>>(node->prefix.value()).get());
// TODO
} else {
// error
}
current_type_ = /*...*/; // TODO
}
if (!std::holds_alternative<info::type::FunctionType>(context_manager_.GetType(current_type_))) {
error_handling::HandleTypecheckError("Mismatched types in function call expression");
@ -432,92 +497,92 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
}
void TypeCheckVisitor::Visit(TupleExpression* node) {
info::type::TupleType type;
type.fields.reserve(node->expressions.size());
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
fields.reserve(node->expressions.size());
for (auto& expression : node->expressions) {
Visitor::Visit(expression);
type.fields.push_back({std::nullopt, current_type_});
fields.push_back({std::nullopt, current_type_});
}
current_type_ = context_manager_.AddType(std::move(type));
current_type_ = context_manager_.AddType(
info::type::TupleType(std::nullopt, fields, context_manager_.GetTypeManager()));
}
// TODO
void TypeCheckVisitor::Visit(VariantExpression* node) {
info::type::VariantType type;
std::vector<info::type::TupleType> constructors;
for (auto& expression : node->expressions) {
info::type::TupleType constructor;
Visitor::Visit(expression);
constructor.fields.push_back({std::nullopt, current_type_}); // ??
type.constructors.push_back(constructor);
// TODO: deal with expression tuple types, etc, ??
std::vector<std::pair<std::optional<std::string>, utils::IdType>> constructor_fields {{std::nullopt, current_type_}};
constructors.emplace_back(std::nullopt, constructor_fields, context_manager_.GetTypeManager());
}
current_type_ = context_manager_.AddType(std::move(type));
current_type_ = context_manager_.AddType(info::type::VariantType(std::nullopt, constructors));
}
void TypeCheckVisitor::Visit(ReturnExpression* node) {
Visitor::Visit(node->expression);
returned_type_ = current_type_;
}
// -------------------------- TODO --------------------------
// TODO
void Visitor::Visit(TypeConstructorParameter* node) {
if (node->name.has_value()) {
Visit(&node->name.value());
}
Visit(node->value);
}
// TODO
void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor names, etc.
utils::IdType type;
// Visit(node->constructor.get());
if (!node->constructor->constructor_id_.has_value()) {
error_handling::HandleTypecheckError("Type constructor name not found");
}
Visit(node->type.get());
type = current_type_;
utils::IdType type = node->constructor->constructor_id_.value();
info::AnyTypeInfo* type_info = &std::get<info::AnyTypeInfo>(
namespace_visitor_.GetGlobalInfo()->GetTypeInfo(
std::get<info::type::DefinedType>(context_manager_.GetType(type)).type_id)->type);
// TODO: check if exist
info::definition::AnyType* type_info = &std::get<info::definition::AnyType>(
namespace_visitor_.GetGlobalInfo()->GetTypeInfo(context_manager_.GetType<info::type::DefinedType>(type).value()->GetTypeId())->type);
for (size_t i = 0; i < node->parameters.size(); ++i) {
//Visit(&std::get<0>(parameter));
// TODO: remove variable on move
Visitor::Visit(std::get<2>(node->parameters[i]));
//context_manager_.EqualTypes(/* TODO type_info->get_field(paramater).type */, current_type_);
Visitor::Visit(node->parameters[i].value);
// TODO: type in context of parameters
// TODO: require ??
context_manager_.EqualTypes(ConstructAnyType(type_info), current_type_); // TODO
}
current_type_ = type;
}
// TODO
void TypeCheckVisitor::Visit(LambdaFunction* node) {
info::type::FunctionType type;
// for (auto& parameter : node->parameters) {
// Visit(parameter.get());
// }
type.argument_types.reserve(node->argument_graph_ids_.size());
for (auto& argument_graph_id : node->argument_graph_ids_) {
type.argument_types.push_back(context_manager_.AddType(info::type::AbstractType {argument_graph_id}));
}
type.return_type = context_manager_.AddType(info::type::AbstractType {node->return_type_graph_id_});
Visitor::Visit(node->expression);
context_manager_.AddTypeRequirement(type.return_type, current_type_); // right order ??
current_type_ = context_manager_.AddType(std::move(type));
error_handling::HandleInternalError("Unimplemented", "TypeCheckVisitor.LambdaFunction");
}
void TypeCheckVisitor::Visit(ArrayExpression* node) {
info::type::ArrayType type;
type.size = node->elements.size();
utils::IdType elements_type = 0;
for (size_t i = 0; i < node->elements.size(); ++i) {
Visitor::Visit(node->elements[i]);
if (i == 0) {
type.elements_type = current_type_;
elements_type = current_type_;
} else {
context_manager_.EqualTypes(type.elements_type.value(), current_type_);
if (!context_manager_.EqualTypes(elements_type, current_type_)) {
error_handling::HandleTypecheckError("Different element types in array expression");
}
}
}
current_type_ = context_manager_.AddType(std::move(type));
current_type_ = context_manager_.AddType(
info::type::ArrayType(node->elements.size(), elements_type, context_manager_.GetTypeManager()));
}
// Name
@ -527,16 +592,10 @@ void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: ?? functions witho
std::vector<std::string> path;
std::string type_name;
path.reserve(node->namespaces.size());
for (size_t i = 0; i < node->namespaces.size(); ++i) {
std::string current_name;
if (std::holds_alternative<std::unique_ptr<std::string>>(node->namespaces[i])) {
current_name = *std::get<std::unique_ptr<std::string>>(node->namespaces[i]);
} else if (std::holds_alternative<std::unique_ptr<ParametrizedType>>(node->namespaces[i])) {
Visit(std::get<std::unique_ptr<ParametrizedType>>(node->namespaces[i]).get());
// TODO: use current_type_
}
if (i + 1 == node->namespaces.size()) {
path.reserve(node->names.size());
for (size_t i = 0; i < node->names.size(); ++i) {
std::string current_name = node->names[i].name;
if (i + 1 == node->names.size()) {
type_name = std::move(current_name);
} else {
path.push_back(std::move(current_name));
@ -547,27 +606,26 @@ void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: ?? functions witho
path.push_back(type_name);
auto name_namespace = namespace_visitor_.FindNamespace(path);
for (size_t i = 0; i < node->expressions.size(); ++i) {
for (size_t i = 0; i < node->names.size(); ++i) {
// Visitor::Visit(node->expressions[i]);
}
}
void TypeCheckVisitor::Visit(TupleName* node) {
utils::IdType type = current_type_;
if (!std::holds_alternative<info::type::TupleType>(context_manager_.GetType(type))) {
std::optional<info::type::TupleType*> maybe_type_value = context_manager_.GetType<info::type::TupleType>(type);
if (maybe_type_value.has_value()) {
error_handling::HandleTypecheckError("Mismatched types in tuple variable definition");
}
info::type::TupleType type_value = std::get<info::type::TupleType>(context_manager_.GetType(type));
if (type_value.fields.size() != node->names.size()) {
if (maybe_type_value.value()->GetFields().size() != node->names.size()) {
error_handling::HandleTypecheckError("Mismatched field count in tuple variable definition");
}
for (size_t i = 0; i < node->names.size(); ++i) {
current_type_ = type_value.fields[i].second;
current_type_ = maybe_type_value.value()->GetFields()[i].second;
Visitor::Visit(node->names[i]);
}
@ -577,23 +635,24 @@ void TypeCheckVisitor::Visit(TupleName* node) {
void TypeCheckVisitor::Visit(VariantName* node) {
utils::IdType type = current_type_;
if (!std::holds_alternative<info::type::VariantType>(context_manager_.GetType(type))) {
std::optional<info::type::VariantType*> maybe_type_value = context_manager_.GetType<info::type::VariantType>(type);
if (!maybe_type_value.has_value()) {
error_handling::HandleTypecheckError("Mismatched types in variant variable definition");
}
info::type::VariantType type_value = std::get<info::type::VariantType>(context_manager_.GetType(type));
if (type_value.constructors.size() != node->names.size()) {
if (maybe_type_value.value()->GetConstructors().size() != node->names.size()) {
error_handling::HandleTypecheckError("Mismatched variant count in variant variable definition");
}
for (size_t i = 0; i < node->names.size(); ++i) {
if (std::holds_alternative<std::string>(type_value.constructors[i])) {
current_type_ = context_manager_.AddType(info::type::OptionalType {});
} else if (std::holds_alternative<info::type::TupleType>(type_value.constructors[i])) {
// TODO: optimize
current_type_ = context_manager_.AddType(info::type::OptionalType { context_manager_.AddType(std::get<info::type::TupleType>(type_value.constructors[i])) });
if (maybe_type_value.value()->GetConstructors()[i].GetFields().size() == 0) {
current_type_ = context_manager_.AddType(
info::type::OptionalType(context_manager_.AddType(info::type::InternalType::Unit), context_manager_.GetTypeManager()));
} else {
// error
info::type::TupleType constructor_type = maybe_type_value.value()->GetConstructors()[i];
current_type_ = context_manager_.AddType(
info::type::OptionalType(context_manager_.AddType(std::move(constructor_type)), context_manager_.GetTypeManager()));
}
Visitor::Visit(node->names[i]);
@ -605,7 +664,11 @@ void TypeCheckVisitor::Visit(VariantName* node) {
void TypeCheckVisitor::Visit(AnnotatedName* node) {
utils::IdType type = current_type_;
context_manager_.DefineVariable(node->name, type);
if (!is_const_definition_.has_value()) {
error_handling::HandleInternalError("No value in is_const_definition_", "TypeCheckVisitor.AnnotatedName");
}
context_manager_.DefineVariable(node->name, type, is_const_definition_.value());
if (node->type.has_value()) {
Visitor::Visit(node->type.value());
context_manager_.EqualTypes(type, current_type_);
@ -617,85 +680,76 @@ void TypeCheckVisitor::Visit(AnnotatedName* node) {
// Type
void TypeCheckVisitor::Visit(FunctionType* node) {
info::type::FunctionType type;
std::vector<utils::IdType> argument_types(node->types.size());
type.argument_types.reserve(node->types.size());
for (auto& argument_type : node->types) {
Visitor::Visit(argument_type);
type.argument_types.push_back(current_type_);
argument_types.push_back(current_type_);
}
current_type_ = context_manager_.AddType(std::move(type));
utils::IdType return_type = argument_types.back();
argument_types.pop_back();
current_type_ = context_manager_.AddType(
info::type::FunctionType(argument_types, return_type, context_manager_.GetTypeManager()));
}
void TypeCheckVisitor::Visit(TupleType* node) {
info::type::TupleType type;
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
type.type = node->type;
type.fields.reserve(node->entities.size());
fields.reserve(node->entities.size());
for (auto& entity : node->entities) {
Visit(entity.second.get());
type.fields.emplace_back(entity.first, current_type_);
fields.emplace_back(entity.first, current_type_);
}
current_type_ = context_manager_.AddType(std::move(type));
current_type_ = context_manager_.AddType(
info::type::TupleType(node->type, fields, context_manager_.GetTypeManager()));
}
void TypeCheckVisitor::Visit(VariantType* node) {
info::type::VariantType type;
std::vector<info::type::TupleType> constructors;
type.type = node->type;
type.constructors.reserve(node->constructors.size());
constructors.reserve(node->constructors.size());
for (auto& constructor : node->constructors) {
if (std::holds_alternative<Constructor>(constructor)) {
type.constructors.emplace_back(std::get<Constructor>(constructor));
std::vector<std::pair<std::optional<std::string>, utils::IdType>> constructor_fields;
constructors.emplace_back(std::get<Constructor>(constructor), constructor_fields, context_manager_.GetTypeManager());
} else if (std::holds_alternative<std::unique_ptr<TupleType>>(constructor)) {
Visit(std::get<std::unique_ptr<TupleType>>(constructor).get());
type.constructors.emplace_back(context_manager_.GetType(current_type_));
std::optional<TupleType*> maybe_constructor = context_manager_.GetType<TupleType>(current_type_);
if (!maybe_constructor.has_value()) {
error_handling::HandleInternalError("Entity of VariantType is not TupleType", "TypeCheckVisitor.VariantType");
}
constructors.emplace_back(maybe_constructor.value());
} else {
// error
}
}
current_type_ = context_manager_.AddType(std::move(type));
}
void TypeCheckVisitor::Visit(ParametrizedType* node) {
info::type::DefinedType type;
type.type_id = node->type_expression->type_id_;
type.paramaters.reserve(node->parameters.size());
for (auto& paramater : node->parameters) {
Visitor::Visit(paramater);
type.paramaters.push_back(current_type_);
}
current_type_ = context_manager_.AddType(std::move(type));
current_type_ = context_manager_.AddType(info::type::VariantType(node->type, constructors));
}
// TODO, different for constructors
void TypeCheckVisitor::Visit(TypeExpression* node) {
current_type_ = context_manager_.AddType(info::type::DefinedType {node->type_id_, {}});
// TODO: type in context of parameters
utils::IdType type = ConstructAnyType(/*...*/); // TODO
current_type_ = context_manager_.AddType(
info::type::DefinedType(node->type_id_, type, context_manager_.GetTypeManager()));
}
void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) {
info::type::ReferenceToType type;
type.references = node->references;
Visitor::Visit(node->type);
type.type = current_type_;
current_type_ = context_manager_.AddType(std::move(type));
current_type_ = context_manager_.AddType(
info::type::ReferenceToType(node->references, current_type_, context_manager_.GetTypeManager()));
}
// Typeclass
void Visitor::Visit(TypeclassExpression* node) {
Visit(node->typeclass);
}
// TODO
void Visitor::Visit(ParametrizedTypeclass* node) {
Visit(&node->typeclass);
for (auto& parameter : node->parameters) {
@ -705,11 +759,19 @@ void Visitor::Visit(ParametrizedTypeclass* node) {
// Typeclass & Type -----------------
void Visitor::Visit(ParametrizedType* node) {
Visit(&node->type);
for (auto& parameter : node->parameters) {
Visit(parameter.get());
}
void TypeCheckVisitor::Visit(ParametrizedType* node) { // TODO: always used in TypeExpression ??
utils::IdType type;
// type.paramaters.reserve(node->parameters.size());
// for (auto& paramater : node->parameters) {
// Visitor::Visit(paramater);
// type.paramaters.push_back(current_type_);
// }
// TODO: type in context of parameters
ConstructAnyType(/*any type from node*/); // TODO. ??
current_type_ = context_manager_.AddType(info::type::DefinedType(node->type_expression->type_id_, type, context_manager_.GetTypeManager()));
}
// Identifiers, constants, etc. -----------------

View file

@ -1,8 +1,18 @@
// for clangd
#include "../include/types.hpp"
#include <cstddef>
namespace info::type {
std::optional<utils::IdType> AbstractType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
auto type_iter = context.find(name_);
if (type_iter != context.end()) {
return type_iter->second;
}
return std::nullopt;
}
bool AbstractType::Same(const AbstractType& type) const {
return name_ == type.name_;
}
@ -22,14 +32,24 @@ bool AbstractType::operator>(const AbstractType& type) const {
//
std::optional<utils::IdType> DefinedType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyType(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool DefinedType::Same(const DefinedType& type) const {
return type_id_ == type.type_id_
&& type_manager_->GetAnyType(type_).value()->Same(*type_manager_->GetAnyType(type.type_).value());
&& type_manager_->GetAnyType(type_)->Same(*type_manager_->GetAnyType(type.type_));
}
bool DefinedType::operator<(const DefinedType& type) const {
return type_id_ == type.type_id_
&& *type_manager_->GetAnyType(type_).value() < *type_manager_->GetAnyType(type.type_).value();
&& *type_manager_->GetAnyType(type_) < *type_manager_->GetAnyType(type.type_);
}
bool DefinedType::operator>(const DefinedType& type) const {
@ -38,13 +58,25 @@ bool DefinedType::operator>(const DefinedType& type) const {
//
std::optional<utils::IdType> TupleType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < fields_.size(); ++i) {
std::optional<utils::IdType> maybe_field_replacement = type_manager_->GetAnyType(fields_[i].second)->InContext(context);
if (maybe_field_replacement.has_value()) {
fields_[i].second = maybe_field_replacement.value();
}
}
return std::nullopt;
}
bool TupleType::Same(const TupleType& type) const {
if (fields_.size() != type.fields_.size()) {
return false;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (!type_manager_->GetAnyType(fields_[i].second).value()->Same(*type_manager_->GetAnyType(type.fields_[i].second).value())) {
if (!type_manager_->GetAnyType(fields_[i].second)->Same(*type_manager_->GetAnyType(type.fields_[i].second))) {
return false;
}
}
@ -58,7 +90,7 @@ bool TupleType::operator<(const TupleType& type) const {
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (!(*type_manager_->GetAnyType(fields_[i].second).value() < *type_manager_->GetAnyType(type.fields_[i].second).value())) {
if (!(*type_manager_->GetAnyType(fields_[i].second) < *type_manager_->GetAnyType(type.fields_[i].second))) {
return false;
}
}
@ -72,6 +104,14 @@ bool TupleType::operator>(const TupleType& type) const {
//
std::optional<utils::IdType> VariantType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < constructors_.size(); ++i) {
constructors_[i].InContext(context);
}
return std::nullopt;
}
bool VariantType::Same(const VariantType& type) const {
if (constructors_.size() != type.constructors_.size()) {
return false;
@ -106,12 +146,22 @@ bool VariantType::operator>(const VariantType& type) const {
//
std::optional<utils::IdType> OptionalType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyType(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool OptionalType::Same(const OptionalType& type) const {
return type_manager_->GetAnyType(type_).value()->Same(*type_manager_->GetAnyType(type.type_).value());
return type_manager_->GetAnyType(type_)->Same(*type_manager_->GetAnyType(type.type_));
}
bool OptionalType::operator<(const OptionalType& type) const {
return *type_manager_->GetAnyType(type_).value() < *type_manager_->GetAnyType(type.type_).value();
return *type_manager_->GetAnyType(type_) < *type_manager_->GetAnyType(type.type_);
}
bool OptionalType::operator>(const OptionalType& type) const {
@ -120,12 +170,22 @@ bool OptionalType::operator>(const OptionalType& type) const {
//
std::optional<utils::IdType> ReferenceToType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_type_replacement = type_manager_->GetAnyType(type_)->InContext(context);
if (maybe_type_replacement.has_value()) {
type_ = maybe_type_replacement.value();
}
return std::nullopt;
}
bool ReferenceToType::Same(const ReferenceToType& type) const {
return references_ == type.references_ && type_manager_->GetAnyType(type_).value()->Same(*type_manager_->GetAnyType(type.type_).value());
return references_ == type.references_ && type_manager_->GetAnyType(type_)->Same(*type_manager_->GetAnyType(type.type_));
}
bool ReferenceToType::operator<(const ReferenceToType& type) const {
return references_ == type.references_ && *type_manager_->GetAnyType(type_).value() < *type_manager_->GetAnyType(type.type_).value();
return references_ == type.references_ && *type_manager_->GetAnyType(type_) < *type_manager_->GetAnyType(type.type_);
}
bool ReferenceToType::operator>(const ReferenceToType& type) const {
@ -134,13 +194,26 @@ bool ReferenceToType::operator>(const ReferenceToType& type) const {
//
std::optional<utils::IdType> FunctionType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
for (size_t i = 0; i < argument_types_.size(); ++i) {
std::optional<utils::IdType> maybe_argument_type_replacement =
type_manager_->GetAnyType(argument_types_[i])->InContext(context);
if (maybe_argument_type_replacement.has_value()) {
argument_types_[i] = maybe_argument_type_replacement.value();
}
}
return std::nullopt;
}
bool FunctionType::Same(const FunctionType& type) const {
if (argument_types_.size() != type.argument_types_.size()) {
return false;
}
for (size_t i = 0; i < argument_types_.size(); ++i) {
if (!type_manager_->GetAnyType(argument_types_[i]).value()->Same(*type_manager_->GetAnyType(type.argument_types_[i]).value())) {
if (!type_manager_->GetAnyType(argument_types_[i])->Same(*type_manager_->GetAnyType(type.argument_types_[i]))) {
return false;
}
}
@ -154,7 +227,7 @@ bool FunctionType::operator<(const FunctionType& type) const {
}
for (size_t i = 0; i < argument_types_.size(); ++i) {
if (!(*type_manager_->GetAnyType(argument_types_[i]).value() < *type_manager_->GetAnyType(type.argument_types_[i]).value())) {
if (!(*type_manager_->GetAnyType(argument_types_[i]) < *type_manager_->GetAnyType(type.argument_types_[i]))) {
return false;
}
}
@ -168,12 +241,23 @@ bool FunctionType::operator>(const FunctionType& type) const {
//
std::optional<utils::IdType> ArrayType::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
std::optional<utils::IdType> maybe_elements_type_replacement =
type_manager_->GetAnyType(elements_type_)->InContext(context);
if (maybe_elements_type_replacement.has_value()) {
elements_type_ = maybe_elements_type_replacement.value();
}
return std::nullopt;
}
bool ArrayType::Same(const ArrayType& type) const {
return size_ == type.size_ && type_manager_->GetAnyType(elements_type_).value()->Same(*type_manager_->GetAnyType(type.elements_type_).value());
return size_ == type.size_ && type_manager_->GetAnyType(elements_type_)->Same(*type_manager_->GetAnyType(type.elements_type_));
}
bool ArrayType::operator<(const ArrayType& type) const {
return size_ == type.size_ && *type_manager_->GetAnyType(elements_type_).value() < *type_manager_->GetAnyType(type.elements_type_).value();
return size_ == type.size_ && *type_manager_->GetAnyType(elements_type_) < *type_manager_->GetAnyType(type.elements_type_);
}
bool ArrayType::operator>(const ArrayType& type) const {
@ -182,6 +266,34 @@ bool ArrayType::operator>(const ArrayType& type) const {
//
std::optional<utils::IdType> Type::InContext(const std::unordered_map<std::string, utils::IdType>& context) {
size_t this_index = type_.index();
switch (this_index) {
case 0:
return std::get<AbstractType>(type_).InContext(context);
case 1:
return std::get<DefinedType>(type_).InContext(context);
case 2:
return std::nullopt;
case 3:
return std::get<TupleType>(type_).InContext(context);
case 4:
return std::get<VariantType>(type_).InContext(context);
case 5:
return std::get<ReferenceToType>(type_).InContext(context);
case 6:
return std::get<FunctionType>(type_).InContext(context);
case 7:
return std::get<ArrayType>(type_).InContext(context);
default:
// error
break;
}
return std::nullopt;
}
bool Type::Same(const Type& type) const {
size_t this_index = type_.index();
size_t type_index = type.type_.index();
@ -211,7 +323,7 @@ bool Type::Same(const Type& type) const {
}
return false;
} // some rule exceptions ??
}
bool Type::operator<(const Type& type) const {
size_t this_index = type_.index();
@ -242,7 +354,7 @@ bool Type::operator<(const Type& type) const {
}
return false;
} // TODO: some rule exceptions ??
}
bool Type::operator>(const Type& type) const {
return type < *this;
@ -264,12 +376,17 @@ std::optional<T*> TypeManager::GetType(utils::IdType type_id) {
return &std::get<T>(types_.at(type_id));
}
std::optional<Type*> TypeManager::GetAnyType(utils::IdType type_id) {
Type* TypeManager::GetAnyType(utils::IdType type_id) {
return &types_.at(type_id);
}
void TypeManager::AddTypeRequirement(utils::IdType type, utils::IdType requrement) {} // TODO
void TypeManager::EqualTypes(utils::IdType first_type, utils::IdType second_type) {} // TODO
bool TypeManager::EqualTypes(utils::IdType first_type, utils::IdType second_type) {
return GetAnyType(first_type)->Same(*GetAnyType(second_type));
}
bool TypeManager::AddTypeRequirement(utils::IdType type, utils::IdType requrement) {
return *GetAnyType(requrement) < *GetAnyType(type);
}
} // namespace info::type