type structs -> type classes

This commit is contained in:
ProgramSnail 2023-05-02 15:18:08 +03:00
parent a512a92f92
commit 648f78afa3
14 changed files with 638 additions and 383 deletions

View file

@ -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;

View file

@ -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_;

View file

@ -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 {

View file

@ -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

View file

@ -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_;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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;
} }

View file

@ -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(

View file

@ -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");
} }

View file

@ -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
View 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