mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-26 16:58: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
|
|
@ -159,28 +159,24 @@ void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) {
|
|||
void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) {
|
||||
is_in_statement = true;
|
||||
|
||||
info::definition::Type info;
|
||||
|
||||
info::definition::AbstractType abstract_type_info;
|
||||
info::definition::AbstractType info;
|
||||
|
||||
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();
|
||||
|
||||
switch (node->modifier) {
|
||||
case interpreter::AbstractTypeDefinitionStatement::Basic:
|
||||
abstract_type_info.modifier = info::definition::AbstractType::Basic;
|
||||
info.modifier = info::definition::AbstractType::Basic;
|
||||
break;
|
||||
case interpreter::AbstractTypeDefinitionStatement::Abstract:
|
||||
abstract_type_info.modifier = info::definition::AbstractType::Abstract;
|
||||
info.modifier = info::definition::AbstractType::Abstract;
|
||||
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_.AddType(type, std::move(info));
|
||||
node->type_id_ = namespace_visitor_.AddAbstractType(type, std::move(info));
|
||||
|
||||
is_in_statement = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,17 @@ void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name,
|
|||
current_path_.push_back(name);
|
||||
}
|
||||
|
||||
void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name) { // TODO: enter sibling namespace, etc.
|
||||
namespace_stack_.push_back(&namespace_stack_.back()->namespaces[name]);
|
||||
current_path_.push_back(name);
|
||||
void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& 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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error_handling::HandleInternalError("Can't find namespace", "GlobalInfo.NamespaceVisitor.EnterNamespace");
|
||||
}
|
||||
|
||||
void GlobalInfo::NamespaceVisitor::ExitNamespace() {
|
||||
|
|
@ -100,7 +108,7 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::str
|
|||
}
|
||||
|
||||
// TODO: internal types, etc.
|
||||
// TODO: extended constructor names
|
||||
// TODO: extended constructor names (point separated names)
|
||||
utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
||||
definition::Type&& type_info) {
|
||||
size_t id = 0;
|
||||
|
|
@ -153,38 +161,44 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type,
|
|||
return id;
|
||||
}
|
||||
|
||||
utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass,
|
||||
definition::Typeclass&& typeclass_info) {
|
||||
size_t id = 0;
|
||||
|
||||
auto typeclass_id_iter = namespace_stack_.back()->typeclasses.find(typeclass);
|
||||
|
||||
if (typeclass_id_iter == namespace_stack_.back()->typeclasses.end()) {
|
||||
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");
|
||||
// TODO: link abstract type with let definitions
|
||||
utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& abstract_type,
|
||||
definition::AbstractType&& abstract_type_info) {
|
||||
if (!FindAbstractType(abstract_type).has_value()) {
|
||||
size_t id = global_info_.abstract_types_.size();
|
||||
global_info_.name_to_abstract_type_[abstract_type] = id;
|
||||
global_info_.abstract_types_.push_b(ack(std::move(abstract_type_info));
|
||||
}
|
||||
|
||||
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,
|
||||
definition::Constructor&& constructor_info) {
|
||||
size_t id = 0;
|
||||
|
||||
auto constructor_id_iter = namespace_stack_.back()->constructors.find(constructor);
|
||||
|
||||
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;
|
||||
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) {
|
||||
|
|
@ -247,19 +261,24 @@ std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindType(
|
|||
});
|
||||
}
|
||||
|
||||
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindTypeclass(
|
||||
const std::optional<std::vector<std::string>>& path,
|
||||
const std::string& typeclass) {
|
||||
return FindSomething<utils::IdType>(path,
|
||||
[typeclass] (definition::Namespace* current_namespace) -> std::optional<utils::IdType> {
|
||||
std::optional<utils::IdType> GlobalInfo::NamespaceVisitor::FindAbstractType(const std::string& abstract_type) {
|
||||
auto abstract_type_id_iter = global_info_.name_to_abstract_type_.find(abstract_type);
|
||||
|
||||
auto typeclass_info_iter = current_namespace->typeclasses.find(typeclass);
|
||||
if (typeclass_info_iter == current_namespace->typeclasses.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (abstract_type_id_iter != global_info_.name_to_abstract_type_.end()) {
|
||||
return abstract_type_id_iter->second;
|
||||
}
|
||||
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -4,187 +4,57 @@
|
|||
|
||||
namespace interpreter {
|
||||
|
||||
// Sources -----------------
|
||||
|
||||
void LinkSymbolsVisitor::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
|
||||
}
|
||||
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(Sources* node) {
|
||||
abstract_types_.EnterContext();
|
||||
for (auto& statement : node->statements) {
|
||||
Visitor::Visit(statement);
|
||||
}
|
||||
abstract_types_.ExitContext();
|
||||
error_handling::HandleInternalError("Empty variant", "NameFromTypeSubExpression");
|
||||
exit(1); // TODO: better decision ??
|
||||
}
|
||||
|
||||
// Namespaces, partitions -----------------
|
||||
|
||||
void LinkSymbolsVisitor::Visit(Partition* node) {
|
||||
// TODO
|
||||
Visit(node->scope.get());
|
||||
}
|
||||
|
||||
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()) {
|
||||
error_handling::HandleTypecheckError("Variable namespace type not found");
|
||||
auto maybe_type = namespace_visitor_.FindType(std::nullopt, node->type); // TODO: find only in local namespace
|
||||
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);
|
||||
Visit(node->scope.get());
|
||||
|
||||
Visitor::Visit(&node->scope);
|
||||
|
||||
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
|
||||
|
||||
void LinkSymbolsVisitor::Visit(TypeExpression* node) {
|
||||
// TODO: link internal stages
|
||||
void LinkSymbolsVisitor::Visit(TypeExpression* node) { // TODO: check
|
||||
std::vector<std::string> path;
|
||||
path.reserve(node->namespaces.size());
|
||||
path.reserve(node->path.size());
|
||||
|
||||
for (auto& type_namespace : node->namespaces) {
|
||||
Visitor::Visit(type_namespace);
|
||||
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
|
||||
}
|
||||
for (auto& path_type : node->path) {
|
||||
path.push_back(NameFromTypeSubExpression(path_type));
|
||||
}
|
||||
|
||||
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindType(path, node->type);
|
||||
std::optional<utils::IdType> maybe_abstract_type = std::nullopt;
|
||||
std::optional<utils::IdType> maybe_type = namespace_visitor_.FindType(path, NameFromTypeSubExpression(node->type));
|
||||
|
||||
if (path.size() == 0) {
|
||||
maybe_abstract_type = abstract_types_.GetTypeId(node->type);
|
||||
}
|
||||
|
||||
if (maybe_abstract_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()) {
|
||||
if (maybe_type.has_value()) {
|
||||
node->type_id_ = maybe_type.value();
|
||||
} else {
|
||||
error_handling::HandleTypecheckError("Type not found");
|
||||
|
|
@ -193,36 +63,21 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) {
|
|||
|
||||
// Typeclass
|
||||
|
||||
void LinkSymbolsVisitor::Visit(TypeclassExpression* node) {
|
||||
std::vector<std::string> path;
|
||||
path.reserve(node->namespaces.size());
|
||||
void LinkSymbolsVisitor::Visit(TypeclassExpression* node) { // TODO: check
|
||||
std::string typeclass;
|
||||
|
||||
for (auto& typeclass_namespace : node->namespaces) {
|
||||
Visitor::Visit(typeclass_namespace);
|
||||
if (std::holds_alternative<std::unique_ptr<std::string>>(typeclass_namespace)) {
|
||||
path.push_back(*std::get<std::unique_ptr<std::string>>(typeclass_namespace));
|
||||
} 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 {
|
||||
// error
|
||||
}
|
||||
if (std::holds_alternative<std::unique_ptr<std::string>>(node->typeclass)) {
|
||||
typeclass = *std::get<std::unique_ptr<std::string>>(node->typeclass);
|
||||
} else if (std::holds_alternative<std::unique_ptr<ParametrizedTypeclass>>(node->typeclass)) {
|
||||
typeclass = std::get<std::unique_ptr<ParametrizedTypeclass>>(node->typeclass)->typeclass;
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
|
||||
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindType(path, node->typeclass);
|
||||
std::optional<utils::IdType> maybe_abstract_typeclass = std::nullopt;
|
||||
std::optional<utils::IdType> maybe_typeclass = namespace_visitor_.FindTypeclass(typeclass);
|
||||
|
||||
if (path.size() == 0) {
|
||||
maybe_abstract_typeclass = abstract_types_.GetTypeId(node->typeclass);
|
||||
}
|
||||
|
||||
if (maybe_abstract_typeclass.has_value()) {
|
||||
if (maybe_typeclass.has_value()) {
|
||||
error_handling::HandleTypecheckError("Ambigious type");
|
||||
} else {
|
||||
node->type_id_ = maybe_abstract_typeclass.value();
|
||||
}
|
||||
} else if (maybe_typeclass.has_value()) {
|
||||
node->type_id_ = maybe_typeclass.value();
|
||||
if (maybe_typeclass.has_value()) {
|
||||
node->typeclass_id_ = maybe_typeclass.value();
|
||||
} else {
|
||||
error_handling::HandleTypecheckError("Type not found");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,44 +12,47 @@ namespace interpreter {
|
|||
// Sources -----------------
|
||||
|
||||
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) {
|
||||
Visitor::Visit(statement);
|
||||
}
|
||||
|
||||
current_type_ = context_manager_.AddType(info::type::InternalType::Unit);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
void TypeCheckVisitor::Visit(Namespace* node) {
|
||||
if (node->name.has_value()) {
|
||||
// TODO: add modifiers
|
||||
context_manager_.EnterVariableContext(node->name.value().name,
|
||||
context_manager_.AddType(info::type::DefinedType {node->type_id_.value()}));
|
||||
if (node->modifier.has_value()) {
|
||||
// TODO
|
||||
// context_manager_.EnterVariableContext(node->name.value().name,
|
||||
// context_manager_.AddType(info::type::DefinedType {node->type_id_.value()}));
|
||||
}
|
||||
|
||||
namespace_visitor_.EnterNamespace(node->type);
|
||||
|
||||
Visit(node->scope.get());
|
||||
Visit(&node->scope);
|
||||
|
||||
namespace_visitor_.ExitNamespace();
|
||||
|
||||
|
|
@ -89,15 +92,24 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
|
|||
// check, that all paramaters used ??
|
||||
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()); // ??
|
||||
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
|
||||
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);
|
||||
context_manager_.EqualTypes(
|
||||
context_manager_.AddType(info::type::AbstractType { node->return_type_graph_id_ }), current_type_);
|
||||
context_manager_.EqualTypes(declaration.argument_types.back(), current_type_); // return type ??
|
||||
|
||||
context_manager_.ExitContext();
|
||||
|
||||
|
|
@ -113,7 +125,7 @@ void TypeCheckVisitor::Visit(TypeDefinitionStatement* 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()); ??
|
||||
for (auto& typeclass : node->type->typeclasses) { // TODO
|
||||
|
|
@ -680,9 +692,25 @@ void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) {
|
|||
|
||||
// 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. -----------------
|
||||
|
||||
|
|
|
|||
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