mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-06 15:08:45 +00:00
type structs -> type classes
This commit is contained in:
parent
a512a92f92
commit
648f78afa3
14 changed files with 638 additions and 383 deletions
|
|
@ -45,7 +45,7 @@ struct AnyType {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
std::variant<AbstractType, AliasType, AnyType> type;
|
std::variant<AliasType, AnyType> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Constructor {
|
struct Constructor {
|
||||||
|
|
@ -85,7 +85,6 @@ struct Namespace {
|
||||||
enum Modifier { Const, Var };
|
enum Modifier { Const, Var };
|
||||||
|
|
||||||
std::unordered_map<std::string, utils::IdType> types;
|
std::unordered_map<std::string, utils::IdType> types;
|
||||||
std::unordered_map<std::string, utils::IdType> typeclasses;
|
|
||||||
std::unordered_map<std::string, utils::IdType> functions;
|
std::unordered_map<std::string, utils::IdType> functions;
|
||||||
std::unordered_map<std::string, utils::IdType> constructors;
|
std::unordered_map<std::string, utils::IdType> constructors;
|
||||||
std::unordered_map<std::string, Namespace> namespaces;
|
std::unordered_map<std::string, Namespace> namespaces;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
// for clangd
|
// for clangd
|
||||||
#include "definitions.hpp"
|
#include "definitions.hpp"
|
||||||
#include "type_manager.hpp"
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
namespace info {
|
namespace info {
|
||||||
|
|
@ -38,6 +37,9 @@ public:
|
||||||
|
|
||||||
utils::IdType AddType(const std::string& type, definition::Type&& type_info);
|
utils::IdType AddType(const std::string& type, definition::Type&& type_info);
|
||||||
|
|
||||||
|
utils::IdType AddAbstractType(const std::string& abstract_type,
|
||||||
|
definition::AbstractType&& abstract_type_info);
|
||||||
|
|
||||||
utils::IdType AddTypeclass(const std::string& typeclass, definition::Typeclass&& typeclass_info);
|
utils::IdType AddTypeclass(const std::string& typeclass, definition::Typeclass&& typeclass_info);
|
||||||
|
|
||||||
utils::IdType AddConstructor(const std::string& constructor,
|
utils::IdType AddConstructor(const std::string& constructor,
|
||||||
|
|
@ -55,20 +57,17 @@ public:
|
||||||
std::optional<utils::IdType> FindType(const std::optional<std::vector<std::string>>& path,
|
std::optional<utils::IdType> FindType(const std::optional<std::vector<std::string>>& path,
|
||||||
const std::string& type);
|
const std::string& type);
|
||||||
|
|
||||||
std::optional<utils::IdType> FindTypeclass(const std::optional<std::vector<std::string>>& path,
|
std::optional<utils::IdType> FindAbstractType(const std::string& abstract_type);
|
||||||
const std::string& typeclass);
|
|
||||||
|
std::optional<utils::IdType> FindTypeclass(const std::string& typeclass);
|
||||||
|
|
||||||
std::optional<utils::IdType> FindConstructor(const std::optional<std::vector<std::string>>& path,
|
std::optional<utils::IdType> FindConstructor(const std::optional<std::vector<std::string>>& path,
|
||||||
const std::string& typeclass);
|
const std::string& constructor);
|
||||||
|
|
||||||
NamespaceVisitor CreateVisitor() {
|
NamespaceVisitor CreateVisitor() {
|
||||||
return global_info_.CreateVisitor();
|
return global_info_.CreateVisitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
type::TypeManager* GetTypeManager() {
|
|
||||||
return global_info_.GetTypeManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalInfo* GetGlobalInfo() {
|
GlobalInfo* GetGlobalInfo() {
|
||||||
return &global_info_;
|
return &global_info_;
|
||||||
}
|
}
|
||||||
|
|
@ -97,10 +96,6 @@ public:
|
||||||
return NamespaceVisitor(*this);
|
return NamespaceVisitor(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
type::TypeManager* GetTypeManager() {
|
|
||||||
return &type_manager_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remember about vector realloc
|
// TODO: remember about vector realloc
|
||||||
definition::Function* GetFunctionInfo(utils::IdType id) {
|
definition::Function* GetFunctionInfo(utils::IdType id) {
|
||||||
return &functions_[id];
|
return &functions_[id];
|
||||||
|
|
@ -124,10 +119,12 @@ public:
|
||||||
private:
|
private:
|
||||||
std::vector<definition::Function> functions_;
|
std::vector<definition::Function> functions_;
|
||||||
std::vector<definition::Type> types_;
|
std::vector<definition::Type> types_;
|
||||||
|
std::vector<definition::AbstractType> abstract_types_;
|
||||||
std::vector<definition::Typeclass> typeclasses_;
|
std::vector<definition::Typeclass> typeclasses_;
|
||||||
std::vector<definition::Constructor> constructors_;
|
std::vector<definition::Constructor> constructors_;
|
||||||
|
|
||||||
type::TypeManager type_manager_;
|
std::unordered_map<std::string, utils::IdType> name_to_typeclass_;
|
||||||
|
std::unordered_map<std::string, utils::IdType> name_to_abstract_type_;
|
||||||
|
|
||||||
definition::Namespace global_namespace_;
|
definition::Namespace global_namespace_;
|
||||||
std::vector<definition::Import> imports_;
|
std::vector<definition::Import> imports_;
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,8 @@ struct Namespace {
|
||||||
TypeIdentifier type;
|
TypeIdentifier type;
|
||||||
NamespaceSources scope;
|
NamespaceSources scope;
|
||||||
|
|
||||||
std::optional<utils::IdType> type_id_;
|
std::optional<utils::IdType> link_type_id_;
|
||||||
|
std::optional<utils::IdType> link_typeclass_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------- Definitions -----------------
|
// ----------------- Definitions -----------------
|
||||||
|
|
@ -570,7 +571,7 @@ struct ExtendedScopedAnyType {
|
||||||
struct TypeclassExpression {
|
struct TypeclassExpression {
|
||||||
TypeclassSubExpression typeclass;
|
TypeclassSubExpression typeclass;
|
||||||
|
|
||||||
utils::IdType type_id_;
|
utils::IdType typeclass_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ParametrizedTypeclass {
|
struct ParametrizedTypeclass {
|
||||||
|
|
|
||||||
|
|
@ -17,30 +17,30 @@ public:
|
||||||
private:
|
private:
|
||||||
// Sources -----------------
|
// Sources -----------------
|
||||||
|
|
||||||
void Visit(SourceFile* node) override;
|
// // void Visit(SourceFile* node) override;
|
||||||
|
|
||||||
// Namespaces, partitions -----------------
|
// Namespaces, partitions -----------------
|
||||||
|
|
||||||
void Visit(PartitionSources* node) override;
|
// // void Visit(PartitionSources* node) override;
|
||||||
void Visit(Partition* node) override;
|
// // void Visit(Partition* node) override;
|
||||||
void Visit(NamespaceSources* node) override;
|
// // void Visit(NamespaceSources* node) override;
|
||||||
void Visit(Namespace* node) override;
|
void Visit(Namespace* node) override;
|
||||||
|
|
||||||
// Definitions -----------------
|
// Definitions -----------------
|
||||||
|
|
||||||
void Visit(ImportStatement* node) override;
|
// // void Visit(ImportStatement* node) override;
|
||||||
void Visit(AliasDefinitionStatement* node) override;
|
// // void Visit(AliasDefinitionStatement* node) override;
|
||||||
void Visit(VariableDefinitionStatement* node) override;
|
// // void Visit(VariableDefinitionStatement* node) override;
|
||||||
void Visit(FunctionDeclaration* node) override;
|
// // void Visit(FunctionDeclaration* node) override;
|
||||||
void Visit(FunctionDefinitionStatement* node) override;
|
// // void Visit(FunctionDefinitionStatement* node) override;
|
||||||
void Visit(TypeDefinitionStatement* node) override;
|
// // void Visit(TypeDefinitionStatement* node) override;
|
||||||
void Visit(AbstractTypeDefinitionStatement* node) override;
|
// // void Visit(AbstractTypeDefinitionStatement* node) override;
|
||||||
void Visit(TypeclassDefinitionStatement* node) override;
|
// // void Visit(TypeclassDefinitionStatement* node) override;
|
||||||
|
|
||||||
// Definition parts
|
// Definition parts
|
||||||
|
|
||||||
void Visit(FunctionDefinition* node) override;
|
// // void Visit(FunctionDefinition* node) override;
|
||||||
void Visit(TypeDefinition* node) override;
|
// // void Visit(TypeDefinition* node) override;
|
||||||
// // void Visit(AnyAnnotatedType* node) override;
|
// // void Visit(AnyAnnotatedType* node) override;
|
||||||
|
|
||||||
// Flow control -----------------
|
// Flow control -----------------
|
||||||
|
|
@ -76,7 +76,7 @@ private:
|
||||||
// // void Visit(ReturnExpression* node) override;
|
// // void Visit(ReturnExpression* node) override;
|
||||||
// // void Visit(TypeConstructorParameter* node) override;
|
// // void Visit(TypeConstructorParameter* node) override;
|
||||||
// // void Visit(TypeConstructor* node) override;
|
// // void Visit(TypeConstructor* node) override;
|
||||||
void Visit(LambdaFunction* node) override;
|
// // void Visit(LambdaFunction* node) override;
|
||||||
// // void Visit(ArrayExpression* node) override;
|
// // void Visit(ArrayExpression* node) override;
|
||||||
|
|
||||||
// // void Visit(LoopControlExpression& node) override; // enum
|
// // void Visit(LoopControlExpression& node) override; // enum
|
||||||
|
|
@ -95,13 +95,13 @@ private:
|
||||||
// // void Visit(FunctionType* node) override;
|
// // void Visit(FunctionType* node) override;
|
||||||
// // void Visit(TupleType* node) override;
|
// // void Visit(TupleType* node) override;
|
||||||
// // void Visit(VariantType* node) override;
|
// // void Visit(VariantType* node) override;
|
||||||
void Visit(TypeExpression* node) override; // TODO
|
void Visit(TypeExpression* node) override;
|
||||||
|
|
||||||
// // void Visit(ExtendedScopedAnyType* node) override;
|
// // void Visit(ExtendedScopedAnyType* node) override;
|
||||||
|
|
||||||
// Typeclass
|
// Typeclass
|
||||||
|
|
||||||
void Visit(TypeclassExpression* node) override; // TODO
|
void Visit(TypeclassExpression* node) override;
|
||||||
// // void Visit(ParametrizedTypeclass* node) override;
|
// // void Visit(ParametrizedTypeclass* node) override;
|
||||||
|
|
||||||
// Typeclass & Type
|
// Typeclass & Type
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ namespace interpreter {
|
||||||
|
|
||||||
class TypeCheckVisitor : public Visitor {
|
class TypeCheckVisitor : public Visitor {
|
||||||
public:
|
public:
|
||||||
explicit TypeCheckVisitor(info::GlobalInfo& global_info)
|
explicit TypeCheckVisitor(info::GlobalInfo& global_info, info::TypeInfoContextManager& context_manager)
|
||||||
: namespace_visitor_(global_info.CreateVisitor()) {}
|
: namespace_visitor_(global_info.CreateVisitor()), context_manager_(context_manager) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Sources -----------------
|
// Sources -----------------
|
||||||
|
|
@ -122,7 +122,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
|
info::GlobalInfo::NamespaceVisitor namespace_visitor_;
|
||||||
info::TypeInfoContextManager context_manager_;
|
info::TypeInfoContextManager& context_manager_;
|
||||||
|
|
||||||
utils::IdType current_type_;
|
utils::IdType current_type_;
|
||||||
std::optional<utils::IdType> returned_type_;
|
std::optional<utils::IdType> returned_type_;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
// for clangd
|
// for clangd
|
||||||
#include "types_info.hpp"
|
#include "error_handling.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
namespace info {
|
namespace info {
|
||||||
|
|
@ -13,32 +15,10 @@ namespace info {
|
||||||
// TODO: remember about typespointers
|
// TODO: remember about typespointers
|
||||||
class TypeInfoContextManager {
|
class TypeInfoContextManager {
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
type::TypeManager* GetTypeManager() {
|
||||||
utils::IdType AddType(T&& type) {
|
return &type_manager_;
|
||||||
types_.push_back(std::forward(type));
|
|
||||||
return types_.size() - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const info::type::Type& GetType(utils::IdType type_id) {
|
|
||||||
return types_[type_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddTypeRequirement(utils::IdType type, utils::IdType requrement) {} // TODO
|
|
||||||
void EqualTypes(utils::IdType first_type, utils::IdType second_type) {} // TODO
|
|
||||||
|
|
||||||
// void CallFunction(const std::vector<std::string>& names,
|
|
||||||
// const std::vector<utils::IdType>& argument_types) {
|
|
||||||
// if (names.size() != argument_types.size()) {
|
|
||||||
// // error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// contexts_.emplace_back(true);
|
|
||||||
//
|
|
||||||
// for (size_t i = 0; i < names.size(); ++i) {
|
|
||||||
// DefineVariable(names[i], argument_types[i]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
void EnterContext() {
|
void EnterContext() {
|
||||||
contexts_.emplace_back(false);
|
contexts_.emplace_back(false);
|
||||||
}
|
}
|
||||||
|
|
@ -60,6 +40,10 @@ public:
|
||||||
return contexts_.back().DefineVariable(name, type_id);
|
return contexts_.back().DefineVariable(name, type_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DefineLocalAbstractType() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
bool RemoveVariable(const std::string& name) {
|
bool RemoveVariable(const std::string& name) {
|
||||||
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
|
for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) {
|
||||||
if (contexts_[i].RemoveVariable(name)) {
|
if (contexts_[i].RemoveVariable(name)) {
|
||||||
|
|
@ -120,7 +104,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Context> contexts_;
|
std::vector<Context> contexts_;
|
||||||
std::vector<info::type::Type> types_;
|
type::TypeManager type_manager_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace info
|
} // namespace info
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// for clangd
|
|
||||||
#include "types.hpp"
|
|
||||||
#include "utils.hpp"
|
|
||||||
|
|
||||||
namespace info::type {
|
|
||||||
|
|
||||||
class TypeManager {
|
|
||||||
public:
|
|
||||||
template<typename T>
|
|
||||||
void AddType(const T& type) {
|
|
||||||
types_.emplace(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T GetType(utils::IdType type_id) {
|
|
||||||
return std::get<T>(types_.at(type_id));
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::vector<Type> types_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace info::type
|
|
||||||
|
|
@ -4,68 +4,195 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
// for clangd
|
// for clangd
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
namespace info::type {
|
namespace info::type {
|
||||||
|
|
||||||
// // Temporary frozen, TODO
|
// TODO: move in constructors
|
||||||
// struct AbstractType {
|
|
||||||
// utils::IdType graph_id;
|
|
||||||
// std::vector<utils::IdType> paramaters;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// TODO: check, if defined type is variant, etc.
|
class TypeManager;
|
||||||
struct DefinedType {
|
|
||||||
utils::IdType type_id; // in defined types
|
class AbstractType { // later will be found in context
|
||||||
utils::IdType type; // in types manager, created using context types
|
public:
|
||||||
|
AbstractType() = default;
|
||||||
|
AbstractType(const std::string& name,
|
||||||
|
const std::vector<utils::IdType>& requirements) : name_(name) {
|
||||||
|
for (auto& typeclass : requirements) {
|
||||||
|
requirements_.insert(typeclass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Same(const AbstractType& type) const;
|
||||||
|
bool operator<(const AbstractType& type) const;
|
||||||
|
bool operator>(const AbstractType& type) const;
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
std::unordered_set<utils::IdType> requirements_; // TODO: all typeclasses from tree
|
||||||
|
};
|
||||||
|
|
||||||
|
class DefinedType {
|
||||||
|
public:
|
||||||
|
DefinedType() = default;
|
||||||
|
DefinedType(utils::IdType type_id,
|
||||||
|
utils::IdType type,
|
||||||
|
TypeManager* type_manager)
|
||||||
|
: type_id_(type_id), type_(type), type_manager_(type_manager) {}
|
||||||
|
|
||||||
|
bool Same(const DefinedType& type) const;
|
||||||
|
bool operator<(const DefinedType& type) const;
|
||||||
|
bool operator>(const DefinedType& type) const;
|
||||||
|
private:
|
||||||
|
utils::IdType type_id_; // in defined types
|
||||||
|
utils::IdType type_; // in types manager, created using context types (if specific type)
|
||||||
|
TypeManager* type_manager_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class InternalType {
|
enum class InternalType {
|
||||||
Float,
|
Float = 0,
|
||||||
Int,
|
Int = 1,
|
||||||
String,
|
String = 2,
|
||||||
Char,
|
Char = 3,
|
||||||
Bool,
|
Bool = 4,
|
||||||
Unit,
|
Unit = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TupleType {
|
class TupleType {
|
||||||
std::optional<std::string> type;
|
public:
|
||||||
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
|
TupleType() = default;
|
||||||
|
TupleType(const std::optional<std::string>& name,
|
||||||
|
const std::vector<std::pair<std::optional<std::string>, utils::IdType>>& fields,
|
||||||
|
TypeManager* type_manager)
|
||||||
|
: name_(name), fields_(fields), type_manager_(type_manager) {}
|
||||||
|
|
||||||
|
bool Same(const TupleType& type) const;
|
||||||
|
bool operator<(const TupleType& type) const;
|
||||||
|
bool operator>(const TupleType& type) const;
|
||||||
|
private:
|
||||||
|
std::optional<std::string> name_;
|
||||||
|
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields_;
|
||||||
|
TypeManager* type_manager_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VariantType {
|
class VariantType {
|
||||||
std::optional<std::string> type;
|
public:
|
||||||
std::vector<TupleType> constructors;
|
VariantType() = default;
|
||||||
|
VariantType(const std::optional<std::string>& name,
|
||||||
|
const std::vector<TupleType>& constructors)
|
||||||
|
: name_(name), constructors_(constructors){}
|
||||||
|
|
||||||
|
bool Same(const VariantType& type) const;
|
||||||
|
bool operator<(const VariantType& type) const;
|
||||||
|
bool operator>(const VariantType& type) const;
|
||||||
|
private:
|
||||||
|
std::optional<std::string> name_;
|
||||||
|
std::vector<TupleType> constructors_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OptionalType {
|
class OptionalType {
|
||||||
std::optional<utils::IdType> type; // Can be empty (Some or None)
|
public:
|
||||||
|
OptionalType() = default;
|
||||||
|
OptionalType(utils::IdType type,
|
||||||
|
TypeManager* type_manager)
|
||||||
|
: type_(type), type_manager_(type_manager) {}
|
||||||
|
|
||||||
|
bool Same(const OptionalType& type) const;
|
||||||
|
bool operator<(const OptionalType& type) const;
|
||||||
|
bool operator>(const OptionalType& type) const;
|
||||||
|
private:
|
||||||
|
utils::IdType type_;
|
||||||
|
TypeManager* type_manager_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReferenceToType {
|
class ReferenceToType {
|
||||||
std::vector<utils::ReferenceType> references;
|
public:
|
||||||
utils::IdType type;
|
ReferenceToType() = default;
|
||||||
|
ReferenceToType(const std::vector<utils::ReferenceType>& references,
|
||||||
|
utils::IdType type,
|
||||||
|
TypeManager* type_manager)
|
||||||
|
: references_(references), type_(type), type_manager_(type_manager) {}
|
||||||
|
|
||||||
|
bool Same(const ReferenceToType& type) const;
|
||||||
|
bool operator<(const ReferenceToType& type) const;
|
||||||
|
bool operator>(const ReferenceToType& type) const;
|
||||||
|
private:
|
||||||
|
std::vector<utils::ReferenceType> references_;
|
||||||
|
utils::IdType type_;
|
||||||
|
TypeManager* type_manager_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionType {
|
/////////////////////////////
|
||||||
std::vector<utils::IdType> argument_types;
|
|
||||||
utils::IdType return_type;
|
class FunctionType {
|
||||||
|
public:
|
||||||
|
FunctionType() = default;
|
||||||
|
FunctionType(const std::vector<utils::IdType>& argument_types,
|
||||||
|
utils::IdType return_type,
|
||||||
|
TypeManager* type_manager)
|
||||||
|
: argument_types_(argument_types), return_type_(return_type), type_manager_(type_manager) {}
|
||||||
|
|
||||||
|
bool Same(const FunctionType& type) const;
|
||||||
|
bool operator<(const FunctionType& type) const;
|
||||||
|
bool operator>(const FunctionType& type) const;
|
||||||
|
private:
|
||||||
|
std::vector<utils::IdType> argument_types_;
|
||||||
|
utils::IdType return_type_;
|
||||||
|
TypeManager* type_manager_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArrayType {
|
class ArrayType {
|
||||||
size_t size; // ?? = 0 for dynamic ??
|
public:
|
||||||
std::optional<utils::IdType> elements_type;
|
ArrayType() = default;
|
||||||
|
ArrayType(size_t size,
|
||||||
|
utils::IdType elements_type,
|
||||||
|
TypeManager* type_manager)
|
||||||
|
: size_(size), elements_type_(elements_type), type_manager_(type_manager) {}
|
||||||
|
|
||||||
|
bool Same(const ArrayType& type) const;
|
||||||
|
bool operator<(const ArrayType& type) const;
|
||||||
|
bool operator>(const ArrayType& type) const;
|
||||||
|
private:
|
||||||
|
size_t size_; // = 0 for dynamic
|
||||||
|
utils::IdType elements_type_;
|
||||||
|
TypeManager* type_manager_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Type = std::variant<DefinedType,
|
class Type {
|
||||||
|
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 ??
|
||||||
|
bool operator>(const Type& type) const;
|
||||||
|
private:
|
||||||
|
std::variant<AbstractType,
|
||||||
|
DefinedType,
|
||||||
InternalType,
|
InternalType,
|
||||||
TupleType,
|
TupleType,
|
||||||
VariantType,
|
VariantType,
|
||||||
ReferenceToType,
|
ReferenceToType,
|
||||||
FunctionType,
|
FunctionType,
|
||||||
ArrayType>;
|
ArrayType> type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TypeManager {
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
utils::IdType AddType(const T&& type);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::optional<T*> GetType(utils::IdType type_id);
|
||||||
|
|
||||||
|
std::optional<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
|
||||||
|
private:
|
||||||
|
std::vector<info::type::Type> types_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace info::type
|
} // namespace info::type
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using std::size_t;
|
||||||
|
|
||||||
using IdType = size_t;
|
using IdType = size_t;
|
||||||
|
|
||||||
enum class ReferenceType { Reference, UniqueReference };
|
enum class ReferenceType { Reference = 0, UniqueReference = 1 };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Storage {
|
class Storage {
|
||||||
|
|
|
||||||
|
|
@ -159,28 +159,24 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
|
||||||
void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
||||||
is_in_statement = true;
|
is_in_statement = true;
|
||||||
|
|
||||||
info::definition::Type info;
|
info::definition::AbstractType info;
|
||||||
|
|
||||||
info::definition::AbstractType abstract_type_info;
|
|
||||||
|
|
||||||
Visit(node->type.get());
|
Visit(node->type.get());
|
||||||
abstract_type_info.type = std::move(std::any_cast<info::definition::Parameter>(current_info_));
|
info.type = std::move(std::any_cast<info::definition::Parameter>(current_info_));
|
||||||
current_info_.reset();
|
current_info_.reset();
|
||||||
|
|
||||||
switch (node->modifier) {
|
switch (node->modifier) {
|
||||||
case interpreter::AbstractTypeDefinitionStatement::Basic:
|
case interpreter::AbstractTypeDefinitionStatement::Basic:
|
||||||
abstract_type_info.modifier = info::definition::AbstractType::Basic;
|
info.modifier = info::definition::AbstractType::Basic;
|
||||||
break;
|
break;
|
||||||
case interpreter::AbstractTypeDefinitionStatement::Abstract:
|
case interpreter::AbstractTypeDefinitionStatement::Abstract:
|
||||||
abstract_type_info.modifier = info::definition::AbstractType::Abstract;
|
info.modifier = info::definition::AbstractType::Abstract;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string type = abstract_type_info.type.type;
|
std::string type = info.type.type;
|
||||||
|
|
||||||
info.type = std::move(abstract_type_info);
|
node->type_id_ = namespace_visitor_.AddAbstractType(type, std::move(info));
|
||||||
|
|
||||||
node->type_id_ = namespace_visitor_.AddType(type, std::move(info));
|
|
||||||
|
|
||||||
is_in_statement = false;
|
is_in_statement = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,17 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name,
|
||||||
current_path_.push_back(name);
|
current_path_.push_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name) { // TODO: enter sibling namespace, etc.
|
void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name) {
|
||||||
namespace_stack_.push_back(&namespace_stack_.back()->namespaces[name]);
|
for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) {
|
||||||
|
auto namespace_iter = namespace_stack_[i]->namespaces.find(name);
|
||||||
|
if (namespace_iter != namespace_stack_[i]->namespaces.end()) {
|
||||||
|
namespace_stack_.push_back(&namespace_iter->second);
|
||||||
current_path_.push_back(name);
|
current_path_.push_back(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_handling::HandleInternalError("Can't find namespace", "GlobalInfo.NamespaceVisitor.EnterNamespace");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalInfo::NamespaceVisitor::ExitNamespace() {
|
void GlobalInfo::NamespaceVisitor::ExitNamespace() {
|
||||||
|
|
@ -100,7 +108,7 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::str
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: internal types, etc.
|
// TODO: internal types, etc.
|
||||||
// TODO: extended constructor names
|
// TODO: extended constructor names (point separated names)
|
||||||
utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
||||||
definition::Type&& type_info) {
|
definition::Type&& type_info) {
|
||||||
size_t id = 0;
|
size_t id = 0;
|
||||||
|
|
@ -153,38 +161,44 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass,
|
// TODO: link abstract type with let definitions
|
||||||
definition::Typeclass&& typeclass_info) {
|
utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& abstract_type,
|
||||||
size_t id = 0;
|
definition::AbstractType&& abstract_type_info) {
|
||||||
|
if (!FindAbstractType(abstract_type).has_value()) {
|
||||||
auto typeclass_id_iter = namespace_stack_.back()->typeclasses.find(typeclass);
|
size_t id = global_info_.abstract_types_.size();
|
||||||
|
global_info_.name_to_abstract_type_[abstract_type] = id;
|
||||||
if (typeclass_id_iter == namespace_stack_.back()->typeclasses.end()) {
|
global_info_.abstract_types_.push_b(ack(std::move(abstract_type_info));
|
||||||
id = global_info_.typeclasses_.size();
|
|
||||||
namespace_stack_.back()->typeclasses[typeclass] = id;
|
|
||||||
global_info_.typeclasses_.push_back(std::move(typeclass_info));
|
|
||||||
} else {
|
|
||||||
error_handling::HandleTypecheckError("More then one typeclass with the same name in namespace");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
error_handling::HandleTypecheckError("More then one abstract type with the same name in namespace");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass,
|
||||||
|
definition::Typeclass&& typeclass_info) {
|
||||||
|
if (!FindTypeclass(typeclass).has_value()) {
|
||||||
|
size_t id = global_info_.typeclasses_.size();
|
||||||
|
global_info_.name_to_typeclass_[typeclass] = id;
|
||||||
|
global_info_.typeclasses_.push_back(std::move(typeclass_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
error_handling::HandleTypecheckError("More then one typeclass with the same name in namespace");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor,
|
utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor,
|
||||||
definition::Constructor&& constructor_info) {
|
definition::Constructor&& constructor_info) {
|
||||||
size_t id = 0;
|
|
||||||
|
|
||||||
auto constructor_id_iter = namespace_stack_.back()->constructors.find(constructor);
|
auto constructor_id_iter = namespace_stack_.back()->constructors.find(constructor);
|
||||||
|
|
||||||
if (constructor_id_iter == namespace_stack_.back()->constructors.end()) {
|
if (constructor_id_iter == namespace_stack_.back()->constructors.end()) {
|
||||||
id = global_info_.constructors_.size();
|
size_t id = global_info_.constructors_.size();
|
||||||
namespace_stack_.back()->constructors[constructor] = id;
|
namespace_stack_.back()->constructors[constructor] = id;
|
||||||
global_info_.constructors_.push_back(std::move(constructor_info));
|
global_info_.constructors_.push_back(std::move(constructor_info));
|
||||||
} else {
|
|
||||||
error_handling::HandleTypecheckError("More then one constructor with the same name in namespace");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
error_handling::HandleTypecheckError("More then one constructor with the same name in namespace");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<definition::Namespace*> GlobalInfo::NamespaceVisitor::FindNamespace(const std::optional<std::vector<std::string>>& path) {
|
std::optional<definition::Namespace*> GlobalInfo::NamespaceVisitor::FindNamespace(const std::optional<std::vector<std::string>>& path) {
|
||||||
|
|
@ -247,19 +261,24 @@ std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindType(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindTypeclass(
|
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindAbstractType(const std::string& abstract_type) {
|
||||||
const std::optional<std::vector<std::string>>& path,
|
auto abstract_type_id_iter = global_info_.name_to_abstract_type_.find(abstract_type);
|
||||||
const std::string& typeclass) {
|
|
||||||
return FindSomething<utils::IdType>(path,
|
|
||||||
[typeclass] (definition::Namespace* current_namespace) -> std::optional<utils::IdType> {
|
|
||||||
|
|
||||||
auto typeclass_info_iter = current_namespace->typeclasses.find(typeclass);
|
if (abstract_type_id_iter != global_info_.name_to_abstract_type_.end()) {
|
||||||
if (typeclass_info_iter == current_namespace->typeclasses.end()) {
|
return abstract_type_id_iter->second;
|
||||||
return std::nullopt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeclass_info_iter->second;
|
return std::nullopt;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindTypeclass(const std::string& typeclass) {
|
||||||
|
auto typeclass_id_iter = global_info_.name_to_typeclass_.find(typeclass);
|
||||||
|
|
||||||
|
if (typeclass_id_iter != global_info_.name_to_typeclass_.end()) {
|
||||||
|
return typeclass_id_iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindConstructor(
|
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindConstructor(
|
||||||
|
|
|
||||||
|
|
@ -4,187 +4,57 @@
|
||||||
|
|
||||||
namespace interpreter {
|
namespace interpreter {
|
||||||
|
|
||||||
// Sources -----------------
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(SourceFile* node) {
|
error_handling::HandleInternalError("Empty variant", "NameFromTypeSubExpression");
|
||||||
for (auto& statement : node->statements) {
|
exit(1); // TODO: better decision ??
|
||||||
if (std::holds_alternative<Partition>(statement)) {
|
|
||||||
Visit(&std::get<Partition>(statement));
|
|
||||||
} else if (std::holds_alternative<SourceStatement>(statement)) {
|
|
||||||
Visitor::Visit(std::get<SourceStatement>(statement));
|
|
||||||
} else {
|
|
||||||
// error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(Sources* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
for (auto& statement : node->statements) {
|
|
||||||
Visitor::Visit(statement);
|
|
||||||
}
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespaces, partitions -----------------
|
// Namespaces, partitions -----------------
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(Partition* node) {
|
|
||||||
// TODO
|
|
||||||
Visit(node->scope.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(Namespace* node) {
|
void LinkSymbolsVisitor::Visit(Namespace* node) {
|
||||||
node->type_id_ = namespace_visitor_.FindType({}, node->type);
|
// Visitor::Visit(&node->type); // not needed
|
||||||
|
|
||||||
if (node->name.has_value() && !node->type_id_.has_value()) {
|
auto maybe_type = namespace_visitor_.FindType(std::nullopt, node->type); // TODO: find only in local namespace
|
||||||
error_handling::HandleTypecheckError("Variable namespace type not found");
|
auto maybe_typeclass = namespace_visitor_.FindType(std::nullopt, node->type); // TODO: find only if in global namespace
|
||||||
|
if (maybe_type.has_value() && maybe_typeclass.has_value()) {
|
||||||
|
error_handling::HandleTypecheckError("Ambigious namespace name (typeclass or type)");
|
||||||
|
}
|
||||||
|
if (maybe_type.has_value()) {
|
||||||
|
node->link_type_id_ = maybe_type.value();
|
||||||
|
}
|
||||||
|
if (maybe_typeclass.has_value()) {
|
||||||
|
node->link_typeclass_id_ = maybe_typeclass.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace_visitor_.EnterNamespace(node->type);
|
namespace_visitor_.EnterNamespace(node->type);
|
||||||
Visit(node->scope.get());
|
|
||||||
|
Visitor::Visit(&node->scope);
|
||||||
|
|
||||||
namespace_visitor_.ExitNamespace();
|
namespace_visitor_.ExitNamespace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definitions -----------------
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(ImportStatement* node) {}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(AliasDefinitionStatement* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
for (size_t i = 0; i <node->parameters.size(); ++i) {
|
|
||||||
abstract_types_.DefineType(node->parameters[i], node->parameter_graph_ids_[i]);
|
|
||||||
}
|
|
||||||
Visitor::Visit(node->value.get());
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(VariableDefinitionStatement* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
Visitor::Visit(node->name);
|
|
||||||
Visitor::Visit(node->value);
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(FunctionDeclaration* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
for (auto& parameter : node->parameters) {
|
|
||||||
Visitor::Visit(parameter.get());
|
|
||||||
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
|
|
||||||
}
|
|
||||||
Visitor::Visit(node->type.get());
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(FunctionDefinitionStatement* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
Visit(node->definition.get());
|
|
||||||
Visitor::Visit(node->value);
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
Visit(node->definition.get());
|
|
||||||
Visitor::Visit(node->value);
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
|
||||||
Visitor::Visit(node->type.get());
|
|
||||||
// TODO: can't be used before definition
|
|
||||||
abstract_types_.DefineType(node->type->type, node->type->type_graph_id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
Visit(node->definition.get());
|
|
||||||
for (auto& requirement : node->requirements) {
|
|
||||||
Visit(requirement.get());
|
|
||||||
}
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Definition parts
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(FunctionDefinition* node) {
|
|
||||||
for (auto& parameter : node->parameters) {
|
|
||||||
Visitor::Visit(parameter.get());
|
|
||||||
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(TypeDefinition* node) {
|
|
||||||
Visitor::Visit(node->type.get());
|
|
||||||
for (auto& parameter : node->parameters) {
|
|
||||||
Visitor::Visit(parameter.get());
|
|
||||||
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flow control -----------------
|
|
||||||
|
|
||||||
// Statements, expressions, blocks, etc. -----------------
|
|
||||||
|
|
||||||
// Operators
|
|
||||||
|
|
||||||
// Other Expressions
|
|
||||||
|
|
||||||
// TODO: move to find_symbols_visitor
|
|
||||||
void LinkSymbolsVisitor::Visit(LambdaFunction* node) {
|
|
||||||
abstract_types_.EnterContext();
|
|
||||||
for (auto& parameter : node->parameters) {
|
|
||||||
Visitor::Visit(parameter.get());
|
|
||||||
abstract_types_.DefineType(parameter->type, parameter->type_graph_id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////
|
|
||||||
node->argument_graph_ids_.resize(node->arguments.size());
|
|
||||||
for (size_t i = 0; i < node->arguments.size(); ++i) {
|
|
||||||
node->argument_graph_ids_[i] = namespace_visitor_.GetAbstractTypeGraph()->AddVertex();
|
|
||||||
}
|
|
||||||
|
|
||||||
node->return_type_graph_id_ = namespace_visitor_.GetAbstractTypeGraph()->AddVertex();
|
|
||||||
///////////
|
|
||||||
|
|
||||||
Visitor::Visit(node->expression);
|
|
||||||
abstract_types_.ExitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name
|
|
||||||
|
|
||||||
// Type, typeclass, etc. -----------------
|
// Type, typeclass, etc. -----------------
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(TypeExpression* node) {
|
// TODO: link internal stages
|
||||||
|
void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
|
||||||
std::vector<std::string> path;
|
std::vector<std::string> path;
|
||||||
path.reserve(node->namespaces.size());
|
path.reserve(node->path.size());
|
||||||
|
|
||||||
for (auto& type_namespace : node->namespaces) {
|
for (auto& path_type : node->path) {
|
||||||
Visitor::Visit(type_namespace);
|
path.push_back(NameFromTypeSubExpression(path_type));
|
||||||
if (std::holds_alternative<std::unique_ptr<std::string>>(type_namespace)) {
|
|
||||||
path.push_back(*std::get<std::unique_ptr<std::string>>(type_namespace));
|
|
||||||
} else if (std::holds_alternative<std::unique_ptr<ParametrizedType>>(type_namespace)) {
|
|
||||||
path.push_back(std::get<std::unique_ptr<ParametrizedType>>(type_namespace)->type_expression->type);
|
|
||||||
} else {
|
|
||||||
// error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindType(path, node->type);
|
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindType(path, NameFromTypeSubExpression(node->type));
|
||||||
std::optional<utils::IdType> maybe_abstract_type = std::nullopt;
|
|
||||||
|
|
||||||
if (path.size() == 0) {
|
|
||||||
maybe_abstract_type = abstract_types_.GetTypeId(node->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maybe_abstract_type.has_value()) {
|
|
||||||
if (maybe_type.has_value()) {
|
if (maybe_type.has_value()) {
|
||||||
error_handling::HandleTypecheckError("Ambigious type");
|
|
||||||
} else {
|
|
||||||
node->type_id_ = maybe_abstract_type.value();
|
|
||||||
}
|
|
||||||
} else if (maybe_type.has_value()) {
|
|
||||||
node->type_id_ = maybe_type.value();
|
node->type_id_ = maybe_type.value();
|
||||||
} else {
|
} else {
|
||||||
error_handling::HandleTypecheckError("Type not found");
|
error_handling::HandleTypecheckError("Type not found");
|
||||||
|
|
@ -193,36 +63,21 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) {
|
||||||
|
|
||||||
// Typeclass
|
// Typeclass
|
||||||
|
|
||||||
void LinkSymbolsVisitor::Visit(TypeclassExpression* node) {
|
void LinkSymbolsVisitor::Visit(TypeclassExpression* node) { // TODO: check
|
||||||
std::vector<std::string> path;
|
std::string typeclass;
|
||||||
path.reserve(node->namespaces.size());
|
|
||||||
|
|
||||||
for (auto& typeclass_namespace : node->namespaces) {
|
if (std::holds_alternative<std::unique_ptr<std::string>>(node->typeclass)) {
|
||||||
Visitor::Visit(typeclass_namespace);
|
typeclass = *std::get<std::unique_ptr<std::string>>(node->typeclass);
|
||||||
if (std::holds_alternative<std::unique_ptr<std::string>>(typeclass_namespace)) {
|
} else if (std::holds_alternative<std::unique_ptr<ParametrizedTypeclass>>(node->typeclass)) {
|
||||||
path.push_back(*std::get<std::unique_ptr<std::string>>(typeclass_namespace));
|
typeclass = std::get<std::unique_ptr<ParametrizedTypeclass>>(node->typeclass)->typeclass;
|
||||||
} else if (std::holds_alternative<std::unique_ptr<ParametrizedType>>(typeclass_namespace)) {
|
|
||||||
path.push_back(std::get<std::unique_ptr<ParametrizedType>>(typeclass_namespace)->type_expression->type);
|
|
||||||
} else {
|
} else {
|
||||||
// error
|
// error
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindType(path, node->typeclass);
|
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclass(typeclass);
|
||||||
std::optional<utils::IdType> maybe_abstract_typeclass = std::nullopt;
|
|
||||||
|
|
||||||
if (path.size() == 0) {
|
|
||||||
maybe_abstract_typeclass = abstract_types_.GetTypeId(node->typeclass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maybe_abstract_typeclass.has_value()) {
|
|
||||||
if (maybe_typeclass.has_value()) {
|
if (maybe_typeclass.has_value()) {
|
||||||
error_handling::HandleTypecheckError("Ambigious type");
|
node->typeclass_id_ = maybe_typeclass.value();
|
||||||
} else {
|
|
||||||
node->type_id_ = maybe_abstract_typeclass.value();
|
|
||||||
}
|
|
||||||
} else if (maybe_typeclass.has_value()) {
|
|
||||||
node->type_id_ = maybe_typeclass.value();
|
|
||||||
} else {
|
} else {
|
||||||
error_handling::HandleTypecheckError("Type not found");
|
error_handling::HandleTypecheckError("Type not found");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,44 +12,47 @@ namespace interpreter {
|
||||||
// Sources -----------------
|
// Sources -----------------
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(SourceFile* node) {
|
void TypeCheckVisitor::Visit(SourceFile* node) {
|
||||||
for (auto& statement : node->statements) {
|
|
||||||
if (std::holds_alternative<Partition>(statement)) {
|
|
||||||
Visit(&std::get<Partition>(statement));
|
|
||||||
} else if (std::holds_alternative<SourceStatement>(statement)) {
|
|
||||||
Visitor::Visit(std::get<SourceStatement>(statement));
|
|
||||||
} else {
|
|
||||||
// error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(Sources* node) {
|
|
||||||
for (auto& statement : node->statements) {
|
for (auto& statement : node->statements) {
|
||||||
Visitor::Visit(statement);
|
Visitor::Visit(statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespaces, partitions -----------------
|
// Namespaces, partitions -----------------
|
||||||
|
|
||||||
|
void TypeCheckVisitor::Visit(PartitionSources* node) {
|
||||||
|
for (auto& statement : node->statements) {
|
||||||
|
Visitor::Visit(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
||||||
|
}
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(Partition* node) {
|
void TypeCheckVisitor::Visit(Partition* node) {
|
||||||
Visit(node->scope.get());
|
Visit(&node->scope);
|
||||||
|
|
||||||
|
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeCheckVisitor::Visit(NamespaceSources* node) {
|
||||||
|
for (auto& statement : node->statements) {
|
||||||
|
Visitor::Visit(statement);
|
||||||
|
}
|
||||||
|
|
||||||
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(Namespace* node) {
|
void TypeCheckVisitor::Visit(Namespace* node) {
|
||||||
if (node->name.has_value()) {
|
if (node->modifier.has_value()) {
|
||||||
// TODO: add modifiers
|
// TODO
|
||||||
context_manager_.EnterVariableContext(node->name.value().name,
|
// context_manager_.EnterVariableContext(node->name.value().name,
|
||||||
context_manager_.AddType(info::type::DefinedType {node->type_id_.value()}));
|
// context_manager_.AddType(info::type::DefinedType {node->type_id_.value()}));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace_visitor_.EnterNamespace(node->type);
|
namespace_visitor_.EnterNamespace(node->type);
|
||||||
|
|
||||||
Visit(node->scope.get());
|
Visit(&node->scope);
|
||||||
|
|
||||||
namespace_visitor_.ExitNamespace();
|
namespace_visitor_.ExitNamespace();
|
||||||
|
|
||||||
|
|
@ -89,15 +92,24 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
||||||
// check, that all paramaters used ??
|
// check, that all paramaters used ??
|
||||||
context_manager_.EnterContext();
|
context_manager_.EnterContext();
|
||||||
|
|
||||||
|
info::definition::Function* function_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(node->function_id_);
|
||||||
|
|
||||||
|
if (!function_info->declaration.has_value()) {
|
||||||
|
error_handling::HandleTypecheckError("Function defined, but not declared");
|
||||||
|
}
|
||||||
|
|
||||||
|
info::definition::FunctionDeclaration& declaration = function_info->declaration.value();
|
||||||
|
|
||||||
|
declaration.parameters
|
||||||
|
|
||||||
// Visit(node->definition.get()); // ??
|
// Visit(node->definition.get()); // ??
|
||||||
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
||||||
context_manager_.DefineVariable(node->definition->arguments[i].name,
|
context_manager_.DefineVariable(node->definition->arguments[i].name,
|
||||||
context_manager_.AddType(info::type::AbstractType { node->argument_graph_ids_[i] }));
|
declaration.argument_types[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Visitor::Visit(node->value);
|
Visitor::Visit(node->value);
|
||||||
context_manager_.EqualTypes(
|
context_manager_.EqualTypes(declaration.argument_types.back(), current_type_); // return type ??
|
||||||
context_manager_.AddType(info::type::AbstractType { node->return_type_graph_id_ }), current_type_);
|
|
||||||
|
|
||||||
context_manager_.ExitContext();
|
context_manager_.ExitContext();
|
||||||
|
|
||||||
|
|
@ -113,7 +125,7 @@ void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
||||||
utils::IdType type = context_manager_.AddType(info::type::AbstractType {node->type_graph_id_} );
|
utils::IdType type = context_manager_.AddType(info::type::DefinedType );
|
||||||
|
|
||||||
// Visit(node->type.get()); ??
|
// Visit(node->type.get()); ??
|
||||||
for (auto& typeclass : node->type->typeclasses) { // TODO
|
for (auto& typeclass : node->type->typeclasses) { // TODO
|
||||||
|
|
@ -680,9 +692,25 @@ void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) {
|
||||||
|
|
||||||
// Typeclass
|
// Typeclass
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(ParametrizedTypeclass* node) {}
|
void Visitor::Visit(TypeclassExpression* node) {
|
||||||
|
Visit(node->typeclass);
|
||||||
|
}
|
||||||
|
|
||||||
void TypeCheckVisitor::Visit(TypeclassExpression* node) {}
|
void Visitor::Visit(ParametrizedTypeclass* node) {
|
||||||
|
Visit(&node->typeclass);
|
||||||
|
for (auto& parameter : node->parameters) {
|
||||||
|
Visit(parameter.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typeclass & Type -----------------
|
||||||
|
|
||||||
|
void Visitor::Visit(ParametrizedType* node) {
|
||||||
|
Visit(&node->type);
|
||||||
|
for (auto& parameter : node->parameters) {
|
||||||
|
Visit(parameter.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Identifiers, constants, etc. -----------------
|
// Identifiers, constants, etc. -----------------
|
||||||
|
|
||||||
|
|
|
||||||
275
src/types.cpp
Normal file
275
src/types.cpp
Normal file
|
|
@ -0,0 +1,275 @@
|
||||||
|
// for clangd
|
||||||
|
#include "../include/types.hpp"
|
||||||
|
|
||||||
|
namespace info::type {
|
||||||
|
|
||||||
|
bool AbstractType::Same(const AbstractType& type) const {
|
||||||
|
return name_ == type.name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbstractType::operator<(const AbstractType& type) const {
|
||||||
|
for (auto& typeclass : requirements_) {
|
||||||
|
if (type.requirements_.count(typeclass) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbstractType::operator>(const AbstractType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DefinedType::operator<(const DefinedType& type) const {
|
||||||
|
return type_id_ == type.type_id_
|
||||||
|
&& *type_manager_->GetAnyType(type_).value() < *type_manager_->GetAnyType(type.type_).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DefinedType::operator>(const DefinedType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
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())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TupleType::operator<(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() < *type_manager_->GetAnyType(type.fields_[i].second).value())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TupleType::operator>(const TupleType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool VariantType::Same(const VariantType& type) const {
|
||||||
|
if (constructors_.size() != type.constructors_.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < constructors_.size(); ++i) {
|
||||||
|
if (!constructors_[i].Same(constructors_[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VariantType::operator<(const VariantType& type) const {
|
||||||
|
if (constructors_.size() != type.constructors_.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < constructors_.size(); ++i) {
|
||||||
|
if (!(constructors_[i] < constructors_[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VariantType::operator>(const VariantType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool OptionalType::Same(const OptionalType& type) const {
|
||||||
|
return type_manager_->GetAnyType(type_).value()->Same(*type_manager_->GetAnyType(type.type_).value());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OptionalType::operator<(const OptionalType& type) const {
|
||||||
|
return *type_manager_->GetAnyType(type_).value() < *type_manager_->GetAnyType(type.type_).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OptionalType::operator>(const OptionalType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool ReferenceToType::Same(const ReferenceToType& type) const {
|
||||||
|
return references_ == type.references_ && type_manager_->GetAnyType(type_).value()->Same(*type_manager_->GetAnyType(type.type_).value());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReferenceToType::operator<(const ReferenceToType& type) const {
|
||||||
|
return references_ == type.references_ && *type_manager_->GetAnyType(type_).value() < *type_manager_->GetAnyType(type.type_).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReferenceToType::operator>(const ReferenceToType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
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())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FunctionType::operator<(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() < *type_manager_->GetAnyType(type.argument_types_[i]).value())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FunctionType::operator>(const FunctionType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArrayType::operator<(const ArrayType& type) const {
|
||||||
|
return size_ == type.size_ && *type_manager_->GetAnyType(elements_type_).value() < *type_manager_->GetAnyType(type.elements_type_).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArrayType::operator>(const ArrayType& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool Type::Same(const Type& type) const {
|
||||||
|
size_t this_index = type_.index();
|
||||||
|
size_t type_index = type.type_.index();
|
||||||
|
|
||||||
|
if (this_index == type_index) {
|
||||||
|
switch (this_index) {
|
||||||
|
case 0:
|
||||||
|
return std::get<AbstractType>(type_).Same(std::get<AbstractType>(type.type_));
|
||||||
|
case 1:
|
||||||
|
return std::get<DefinedType>(type_).Same(std::get<DefinedType>(type.type_));
|
||||||
|
case 2:
|
||||||
|
return std::get<InternalType>(type_) == std::get<InternalType>(type.type_);
|
||||||
|
case 3:
|
||||||
|
return std::get<TupleType>(type_).Same(std::get<TupleType>(type.type_));
|
||||||
|
case 4:
|
||||||
|
return std::get<VariantType>(type_).Same(std::get<VariantType>(type.type_));
|
||||||
|
case 5:
|
||||||
|
return std::get<ReferenceToType>(type_).Same(std::get<ReferenceToType>(type.type_));
|
||||||
|
case 6:
|
||||||
|
return std::get<FunctionType>(type_).Same(std::get<FunctionType>(type.type_));
|
||||||
|
case 7:
|
||||||
|
return std::get<ArrayType>(type_).Same(std::get<ArrayType>(type.type_));
|
||||||
|
default:
|
||||||
|
// error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // some rule exceptions ??
|
||||||
|
|
||||||
|
bool Type::operator<(const Type& type) const {
|
||||||
|
size_t this_index = type_.index();
|
||||||
|
size_t type_index = type.type_.index();
|
||||||
|
|
||||||
|
if (this_index == type_index) {
|
||||||
|
switch (this_index) {
|
||||||
|
case 0:
|
||||||
|
return std::get<AbstractType>(type_) < std::get<AbstractType>(type.type_);
|
||||||
|
case 1:
|
||||||
|
return std::get<DefinedType>(type_) < std::get<DefinedType>(type.type_);
|
||||||
|
case 2:
|
||||||
|
return std::get<InternalType>(type_) == std::get<InternalType>(type.type_);
|
||||||
|
case 3:
|
||||||
|
return std::get<TupleType>(type_) < std::get<TupleType>(type.type_);
|
||||||
|
case 4:
|
||||||
|
return std::get<VariantType>(type_) < std::get<VariantType>(type.type_);
|
||||||
|
case 5:
|
||||||
|
return std::get<ReferenceToType>(type_) < std::get<ReferenceToType>(type.type_);
|
||||||
|
case 6:
|
||||||
|
return std::get<FunctionType>(type_) < std::get<FunctionType>(type.type_);
|
||||||
|
case 7:
|
||||||
|
return std::get<ArrayType>(type_) < std::get<ArrayType>(type.type_);
|
||||||
|
default:
|
||||||
|
// error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // TODO: some rule exceptions ??
|
||||||
|
|
||||||
|
bool Type::operator>(const Type& type) const {
|
||||||
|
return type < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
utils::IdType TypeManager::AddType(const T&& type) {
|
||||||
|
types_.emplace_back(std::forward(type));
|
||||||
|
return types_.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::optional<T*> TypeManager::GetType(utils::IdType type_id) {
|
||||||
|
if (!std::holds_alternative<T>(types_.at(type_id))) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return &std::get<T>(types_.at(type_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<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
|
||||||
|
|
||||||
|
} // namespace info::type
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue