From 656f58bcde086578491aa35cc556f623db3e0738 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Sat, 22 Apr 2023 19:30:16 +0300 Subject: [PATCH] part of type_check_visitor done --- include/global_info.hpp | 4 + include/interpreter_tree.hpp | 4 +- include/link_symbols_visitor.hpp | 63 ++-- include/symbols_info.hpp | 8 +- include/type_check_visitor.hpp | 1 + include/type_info_contexts.hpp | 42 ++- include/types_info.hpp | 38 +-- include/visitor.hpp | 108 +++--- src/find_symbols_visitor.cpp | 4 +- src/global_info.cpp | 9 + src/link_symbols_visitor.cpp | 219 ++---------- src/print_visitor.cpp | 2 +- src/type_check_visitor.cpp | 569 ++++++++++++++++++++----------- src/visitor.cpp | 359 +++++++++++++++++++ 14 files changed, 891 insertions(+), 539 deletions(-) diff --git a/include/global_info.hpp b/include/global_info.hpp index 7156427..0537e39 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -64,6 +64,10 @@ public: return global_info_.GetAbstractTypeGraph(); } + GlobalInfo* GetGlobalInfo() { + return &global_info_; + } + const std::vector& GetCurrentPath() { return current_path_; } diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 96c9a3b..7647f0e 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -261,7 +261,6 @@ struct Namespace { std::unique_ptr scope; std::optional type_id_; - std::optional variable_type_; }; struct Partition { @@ -471,6 +470,9 @@ struct LambdaFunction { std::vector> parameters; std::vector arguments; Expression expression; + + std::vector argument_graph_ids_; + utils::IdType return_type_graph_id_; }; struct ArrayExpression { diff --git a/include/link_symbols_visitor.hpp b/include/link_symbols_visitor.hpp index a95fe73..d97deb7 100644 --- a/include/link_symbols_visitor.hpp +++ b/include/link_symbols_visitor.hpp @@ -41,66 +41,65 @@ private: void Visit(FunctionDefinition* node) override; void Visit(TypeDefinition* node) override; - void Visit(AnyAnnotatedType* node) override; + // // void Visit(AnyAnnotatedType* node) override; // Flow control ----------------- - void Visit(MatchCase* node) override; - void Visit(Match* node) override; - void Visit(Condition* node) override; - void Visit(DoWhileLoop* node) override; - void Visit(WhileLoop* node) override; - void Visit(ForLoop* node) override; - void Visit(LoopLoop* node) override; + // // void Visit(MatchCase* node) override; + // // void Visit(Match* node) override; + // // void Visit(Condition* node) override; + // // void Visit(DoWhileLoop* node) override; + // // void Visit(WhileLoop* node) override; + // // void Visit(ForLoop* node) override; + // // void Visit(LoopLoop* node) override; // Statements, expressions, blocks, etc. ----------------- - void Visit(Block* node) override; - - void Visit(ScopedStatement* node) override; + // // void Visit(Block* node) override; + // // void Visit(ScopedStatement* node) override; // Operators - void Visit(BinaryOperatorExpression* node) override; - void Visit(UnaryOperatorExpression* node) override; - void Visit(ReferenceExpression* node) override; - void Visit(AccessExpression* node) override; + // // void Visit(BinaryOperatorExpression* node) override; + // // void Visit(UnaryOperatorExpression* node) override; + // // void Visit(ReferenceExpression* node) override; + // // void Visit(AccessExpression* node) override; // Simple Expressions - void Visit(FunctionCallExpression* node) override; + // // void Visit(FunctionCallExpression* node) override; - void Visit(TupleExpression* node) override; - void Visit(VariantExpression* node) override; - void Visit(ReturnExpression* node) override; - void Visit(TypeConstructor* node) override; + // // void Visit(TupleExpression* node) override; + // // void Visit(VariantExpression* node) override; + // // void Visit(ReturnExpression* node) override; + // // void Visit(TypeConstructor* 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 // Name - void Visit(NameExpression* node) override; - void Visit(TupleName* node) override; - void Visit(VariantName* node) override; - void Visit(AnnotatedName* node) override; + // // void Visit(NameExpression* node) override; + // // void Visit(TupleName* node) override; + // // void Visit(VariantName* node) override; + // // void Visit(AnnotatedName* node) override; // Type, typeclass, etc. ----------------- // Type - void Visit(FunctionType* node) override; - void Visit(TupleType* node) override; - void Visit(VariantType* node) override; - void Visit(ParametrizedType* node) override; + // // void Visit(FunctionType* node) override; + // // void Visit(TupleType* node) override; + // // void Visit(VariantType* node) override; + // // void Visit(ParametrizedType* node) override; void Visit(TypeExpression* node) override; - void Visit(ExtendedScopedAnyType* node) override; + // // void Visit(ExtendedScopedAnyType* node) override; // Typeclass - void Visit(ParametrizedTypeclass* node) override; + // // void Visit(ParametrizedTypeclass* node) override; void Visit(TypeclassExpression* node) override; // Identifiers, constants, etc. ----------------- diff --git a/include/symbols_info.hpp b/include/symbols_info.hpp index 7c0bc9b..b7e48b2 100644 --- a/include/symbols_info.hpp +++ b/include/symbols_info.hpp @@ -85,17 +85,19 @@ struct FunctionDeclarationInfo { std::vector parameters; std::vector argument_type_nodes; std::vector argument_types; + interpreter::tokens::FunctionDeclaration* node = nullptr; }; struct FunctionDefinitionInfo { std::vector parameters; std::vector argument_names; - interpreter::tokens::SuperExpression* expression = nullptr; + interpreter::tokens::FunctionDefinitionStatement* node = nullptr; }; struct FunctionInfo { - FunctionDeclarationInfo declaration; - FunctionDefinitionInfo definition; + size_t argument_count = 0; + std::optional declaration; + std::optional definition; }; struct TypeclassInfo { diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp index 44e9323..fe4f461 100644 --- a/include/type_check_visitor.hpp +++ b/include/type_check_visitor.hpp @@ -117,6 +117,7 @@ private: info::TypeInfoContextManager context_manager_; utils::IdType current_type_; + std::optional returned_type_; }; } // namespace interpreter diff --git a/include/type_info_contexts.hpp b/include/type_info_contexts.hpp index 424273b..337e0bb 100644 --- a/include/type_info_contexts.hpp +++ b/include/type_info_contexts.hpp @@ -23,20 +23,21 @@ public: return types_[type_id]; } - // void AddTypeRequirement(utils::IdType type, utils::IdType requrement); // TODO + 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& names, - const std::vector& 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 CallFunction(const std::vector& names, + // const std::vector& 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() { contexts_.emplace_back(false); @@ -59,6 +60,15 @@ public: return contexts_.back().DefineVariable(name, type_id); } + bool RemoveVariable(const std::string& name) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { + if (contexts_[i].RemoveVariable(name)) { + return true; + } + } + return false; + } + void EnterVariableContext(const std::string& name, utils::IdType type_id) { // for variable namespaces, for loops contexts_.push_back(false); @@ -67,7 +77,7 @@ public: } std::optional GetVariableType(const std::string& name) { - for (ssize_t i = contexts_.size() - 1; i >= 0; --i) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { auto maybe_type = contexts_[i].GetVariableType(name); if (maybe_type.has_value()) { return maybe_type.value(); @@ -89,6 +99,10 @@ private: return true; } + bool RemoveVariable(const std::string& name) { + return variables_.erase(name); + } + std::optional GetVariableType(const std::string& name) { auto variable_iter = variables_.find(name); diff --git a/include/types_info.hpp b/include/types_info.hpp index 13f866b..d838186 100644 --- a/include/types_info.hpp +++ b/include/types_info.hpp @@ -6,7 +6,6 @@ #include // for clangd -#include "error_handling.hpp" #include "utils.hpp" namespace info::type { @@ -37,39 +36,14 @@ struct TupleType { // }; struct VariantType { - static VariantType MakeOptional(const std::variant& option) { - if (std::holds_alternative(option)) { - return MakeOptional(option); - } else if (std::holds_alternative(option)) { - return MakeOptional(std::get(option)); - } else { - error_handling::HandleInternalError("Can't construct optional from variant", "info::type::VariantType::MakeOptional"); - } - } - - static VariantType MakeOptional(TupleType option) { // TODO - VariantType type; - - type.type = option.type; - option.type = "\'Some"; - type.constructors.emplace_back(option); - type.constructors.emplace_back("\'None"); - return type; - } - - static VariantType MakeOptional(std::string& option) { // TODO - VariantType type; - - type.type = option; - type.constructors.emplace_back("\'Some"); - type.constructors.emplace_back("\'None"); - return type; - } - std::optional type; std::vector> constructors; }; +struct OptionalType { + std::optional type; // Can be empty (Some or None) +}; + struct ReferenceToType { std::vector references; utils::IdType type; @@ -77,10 +51,12 @@ struct ReferenceToType { struct FunctionType { std::vector argument_types; + utils::IdType return_type; }; struct ArrayType { - std::vector element_types; + size_t size; // ?? = 0 for dynamic ?? + std::optional elements_type; }; using Type = std::varianttype->types[i]; } + info.node = node; + if (was_in_statement) { current_info_ = std::move(info); } else { @@ -148,7 +150,7 @@ void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) { node->return_type_graph_id_ = namespace_visitor_.GetAbstractTypeGraph()->AddVertex(); - info.expression = &node->value; + info.node = node; node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info)); diff --git a/src/global_info.cpp b/src/global_info.cpp index a2f7e02..8d345cb 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -1,5 +1,6 @@ // for clangd #include "../include/global_info.hpp" +#include "../include/error_handling.hpp" namespace info { @@ -63,9 +64,13 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration(const std::st id = global_info_.functions_.size(); namespace_stack_.back()->functions[name] = id; global_info_.functions_.emplace_back(); + global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size(); global_info_.functions_.back().declaration = std::move(function_declaration_info); } else { id = function_id_iter->second; + if (global_info_.functions_.back().argument_count != function_declaration_info.argument_types.size()) { + error_handling::HandleInternalError("Not same argument count in function definition and declaration", "GlobalInfo"); + } global_info_.functions_[id].declaration = std::move(function_declaration_info); } @@ -82,9 +87,13 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition(const std::str id = global_info_.functions_.size(); namespace_stack_.back()->functions[name] = id; global_info_.functions_.emplace_back(); + global_info_.functions_.back().argument_count = function_definition_info.argument_names.size(); global_info_.functions_.back().definition = std::move(function_definition_info); } else { id = function_id_iter->second; + if (global_info_.functions_.back().argument_count != function_definition_info.argument_names.size()) { + error_handling::HandleInternalError("Not same argument count in function definition and declaration", "GlobalInfo"); + } global_info_.functions_[id].definition = std::move(function_definition_info); } diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 5dc0c40..26de5f3 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -54,7 +54,7 @@ void LinkSymbolsVisitor::Visit(AliasDefinitionStatement* node) { for (size_t i = 0; i parameters.size(); ++i) { abstract_types_.DefineType(node->parameters[i], node->parameter_graph_ids_[i]); } - Visit(node->value.get()); + Visitor::Visit(node->value.get()); abstract_types_.ExitContext(); } @@ -68,10 +68,10 @@ void LinkSymbolsVisitor::Visit(VariableDefinitionStatement* node) { void LinkSymbolsVisitor::Visit(FunctionDeclaration* node) { abstract_types_.EnterContext(); for (auto& parameter : node->parameters) { - Visit(parameter.get()); + Visitor::Visit(parameter.get()); abstract_types_.DefineType(parameter->type, parameter->type_graph_id_); } - Visit(node->type.get()); + Visitor::Visit(node->type.get()); abstract_types_.ExitContext(); } @@ -90,7 +90,7 @@ void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) { } void LinkSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) { - Visit(node->type.get()); + Visitor::Visit(node->type.get()); // TODO: can't be used before definition abstract_types_.DefineType(node->type->type, node->type->type_graph_id_); } @@ -108,224 +108,54 @@ void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { void LinkSymbolsVisitor::Visit(FunctionDefinition* node) { for (auto& parameter : node->parameters) { - Visit(parameter.get()); + Visitor::Visit(parameter.get()); abstract_types_.DefineType(parameter->type, parameter->type_graph_id_); } } void LinkSymbolsVisitor::Visit(TypeDefinition* node) { - Visit(node->type.get()); + Visitor::Visit(node->type.get()); for (auto& parameter : node->parameters) { - Visit(parameter.get()); + Visitor::Visit(parameter.get()); abstract_types_.DefineType(parameter->type, parameter->type_graph_id_); } } -void LinkSymbolsVisitor::Visit(AnyAnnotatedType* node) { - // TODO check ?? - if (!node->typeclasses.empty() > 0) { - for (auto& typeclass : node->typeclasses) { - Visitor::Visit(typeclass); - } - } -} - // Flow control ----------------- -void LinkSymbolsVisitor::Visit(MatchCase* node) { - Visitor::Visit(node->value); - if (node->condition.has_value()) { - Visitor::Visit(node->condition.value()); - } - if (node->statement.has_value()) { - Visitor::Visit(node->statement.value()); - } -} - -void LinkSymbolsVisitor::Visit(Match* node) { - Visitor::Visit(node->value); - for (auto& match_case : node->matches) { - Visit(&match_case); - } -} - -void LinkSymbolsVisitor::Visit(Condition* node) { - Visitor::Visit(node->conditions[0]); - Visitor::Visit(node->statements[0]); - for (size_t i = 1; i < node->conditions.size(); ++i) { - Visitor::Visit(node->conditions[i]); - Visitor::Visit(node->statements[i]); - } - if (node->statements.size() > node->conditions.size()) { - Visitor::Visit(node->statements[node->conditions.size()]); - } -} - -void LinkSymbolsVisitor::Visit(DoWhileLoop* node) { - Visitor::Visit(node->statement); - Visitor::Visit(node->condition); -} - -void LinkSymbolsVisitor::Visit(WhileLoop* node) { - Visitor::Visit(node->condition); - Visitor::Visit(node->statement); -} -void LinkSymbolsVisitor::Visit(ForLoop* node) { - Visitor::Visit(node->variable); - Visitor::Visit(node->interval); - Visitor::Visit(node->statement); -} - -void LinkSymbolsVisitor::Visit(LoopLoop* node) { - Visitor::Visit(node->statement); -} - // Statements, expressions, blocks, etc. ----------------- -void LinkSymbolsVisitor::Visit(Block* node) { - for (auto& statement : node->statements) { - Visitor::Visit(statement); - } -} - -void LinkSymbolsVisitor::Visit(ScopedStatement* node) { - Visitor::Visit(node->statement); -} - -void LinkSymbolsVisitor::Visit(LoopControlExpression& node) {} - // Operators -void LinkSymbolsVisitor::Visit(BinaryOperatorExpression* node) { - Visitor::Visit(node->left_expression); - Visitor::Visit(node->right_expression); -} - -void LinkSymbolsVisitor::Visit(UnaryOperatorExpression* node) { - Visitor::Visit(node->expression); -} - -void LinkSymbolsVisitor::Visit(ReferenceExpression* node) { - Visit(node->expression.get()); -} - -void LinkSymbolsVisitor::Visit(AccessExpression* node) { - Visitor::Visit(node->name.get()); - Visitor::Visit(node->id); -} - // Other Expressions -void LinkSymbolsVisitor::Visit(FunctionCallExpression* node) { - Visit(node->name.get()); - for (auto& argument : node->arguments) { - Visitor::Visit(argument); - } -} - -void LinkSymbolsVisitor::Visit(TupleExpression* node) { - for (auto& expression : node->expressions) { - Visitor::Visit(expression); - } -} - -void LinkSymbolsVisitor::Visit(VariantExpression* node) { - for (auto& expression : node->expressions) { - Visitor::Visit(expression); - } -} - -void LinkSymbolsVisitor::Visit(ReturnExpression* node) { - Visitor::Visit(node->expression); -} - -void LinkSymbolsVisitor::Visit(TypeConstructor* node) { - Visit(node->type.get()); - for (auto& parameter : node->parameters) { - Visitor::Visit(std::get<2>(parameter)); - } -} - +// TODO: move to find_symbols_visitor void LinkSymbolsVisitor::Visit(LambdaFunction* node) { abstract_types_.EnterContext(); for (auto& parameter : node->parameters) { - Visit(parameter.get()); + 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(); } -void LinkSymbolsVisitor::Visit(ArrayExpression* node) { - for (auto& element : node->elements) { - Visitor::Visit(element); - } -} - // Name -void LinkSymbolsVisitor::Visit(NameExpression* node) { - for (auto& variable_namespace : node->namespaces) { - Visitor::Visit(variable_namespace); - } - // for (auto& expression : node->expressions) { - // Visit(expression); - // } -} - -void LinkSymbolsVisitor::Visit(TupleName* node) { - for (auto& name : node->names) { - Visitor::Visit(name); - } -} - -void LinkSymbolsVisitor::Visit(VariantName* node) { - for (auto& name : node->names) { - Visitor::Visit(name); - } -} - -void LinkSymbolsVisitor::Visit(AnnotatedName* node) { - if (node->type.has_value()) { - Visitor::Visit(node->type.value()); - } -} - // Type, typeclass, etc. ----------------- // Type -void LinkSymbolsVisitor::Visit(FunctionType* node) { - for (auto& type : node->types) { - Visitor::Visit(type); - } -} - -void LinkSymbolsVisitor::Visit(TupleType* node) { - for (auto& entity : node->entities) { - Visit(entity.second.get()); - } -} - -void LinkSymbolsVisitor::Visit(VariantType* node) { - for (auto& constructor : node->constructors) { - if (std::holds_alternative(constructor)) { - // do nothing - } else if (std::holds_alternative>(constructor)) { - Visit(std::get>(constructor).get()); - } else { - // error - } - } -} - -void LinkSymbolsVisitor::Visit(ParametrizedType* node) { - Visit(node->type_expression.get()); - for (auto& parameter : node->parameters) { - Visitor::Visit(parameter); - } -} - void LinkSymbolsVisitor::Visit(TypeExpression* node) { std::vector path; path.reserve(node->namespaces.size()); @@ -361,19 +191,8 @@ void LinkSymbolsVisitor::Visit(TypeExpression* node) { } } -void LinkSymbolsVisitor::Visit(ExtendedScopedAnyType* node) { - Visitor::Visit(node->type); -} - // Typeclass -void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) { - Visit(node->typeclass_expression.get()); - for (auto& parameter : node->parameters) { - Visitor::Visit(parameter); - } -} - void LinkSymbolsVisitor::Visit(TypeclassExpression* node) { std::vector path; path.reserve(node->namespaces.size()); diff --git a/src/print_visitor.cpp b/src/print_visitor.cpp index d4a5242..51b9d42 100644 --- a/src/print_visitor.cpp +++ b/src/print_visitor.cpp @@ -250,7 +250,7 @@ void PrintVisitor::Visit(AnyAnnotatedType* node) { out_ << "[Annotated (Abstract) Type "; Visit(&node->type); out_ << ']'; - if (!node->typeclasses.empty() > 0) { + if (!node->typeclasses.empty()) { out_ << " ("; for (auto& typeclass : node->typeclasses) { Visitor::Visit(typeclass); diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 6519636..2af3584 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -1,5 +1,9 @@ -#include "../include/type_check_visitor.hpp" #include +#include + +// for clangd +#include "../include/type_check_visitor.hpp" +#include "../include/error_handling.hpp" // TODO @@ -17,26 +21,30 @@ void TypeCheckVisitor::Visit(SourceFile* node) { // 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(Partition* node) { Visit(node->scope.get()); + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(Namespace* node) { if (node->name.has_value()) { // TODO: add modifiers - node->variable_type_ = info::type::Type {info::type::DefinedType {node->type_id_.value()}}; context_manager_.EnterVariableContext(node->name.value().name, - &node->variable_type_.value()); + context_manager_.AddType(info::type::DefinedType {node->type_id_.value()})); } namespace_visitor_.EnterNamespace(node->type); @@ -44,6 +52,8 @@ void TypeCheckVisitor::Visit(Namespace* node) { Visit(node->scope.get()); namespace_visitor_.ExitNamespace(); + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } // Definitions ----------------- @@ -51,364 +61,520 @@ void TypeCheckVisitor::Visit(Namespace* node) { void TypeCheckVisitor::Visit(ImportStatement* node) {} void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) { - // TODO check, that all paramaters used + // check, that all paramaters used ?? + utils::IdType type = context_manager_.AddType(info::type::DefinedType {node->type_id_}); // ?? + Visit(node->value.get()); + context_manager_.EqualTypes(type, current_type_); + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(VariableDefinitionStatement* node) { + // TODO: remove variable on move // TODO: add modifiers Visitor::Visit(node->value); + // current_type from value automatically passed to name definitions Visitor::Visit(node->name); + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(FunctionDeclaration* node) { - // later check, that function definition requirements are satisfied + // check later that function definition requirements are satisfied + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { - Visit(node->definition.get()); + // check, that all paramaters used ?? + context_manager_.EnterContext(); + + // 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] })); + } + Visitor::Visit(node->value); + context_manager_.EqualTypes( + context_manager_.AddType(info::type::AbstractType { node->return_type_graph_id_ }), current_type_); + + context_manager_.ExitContext(); + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) { - switch (node->modifier) { - case TypeDefinitionStatement::Struct: - break; - case TypeDefinitionStatement::Class: - break; - } - Visit(node->definition.get()); - Visitor::Visit(node->value); + // TODO: add modifiers + // check, that all paramaters used ?? + // TODO: defined type typeclasses + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { - switch (node->modifier) { - case AbstractTypeDefinitionStatement::Basic: - break; - case AbstractTypeDefinitionStatement::Abstract: - break; + utils::IdType type = context_manager_.AddType(info::type::AbstractType {node->type_graph_id_} ); + + // Visit(node->type.get()); ?? + for (auto& typeclass : node->type->typeclasses) { // TODO + Visitor::Visit(typeclass); + context_manager_.AddTypeRequirement(type, current_type_); } - Visit(node->type.get()); + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(TypeclassDefinitionStatement* node) { - Visit(node->definition.get()); - if (!node->requirements.empty()) { - } - for (auto& requirement : node->requirements) { - Visit(requirement.get()); - } + // check, that all paramaters used ?? + // TODO: needed ?? + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } // Definition parts void TypeCheckVisitor::Visit(FunctionDefinition* node) { - switch (node->modifier) { - case FunctionDefinition::Operator: - break; - case FunctionDefinition::Function: - break; - } - Visit(&node->name); - if (!node->parameters.empty()) { - for (auto& parameter : node->parameters) { - Visit(parameter.get()); - } - } - if (!node->arguments.empty()) { - for (auto& argument : node->arguments) { - Visit(&argument); - } - } + // TODO: needed ?? + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } void TypeCheckVisitor::Visit(TypeDefinition* node) { - Visit(node->type.get()); - if (!node->parameters.empty()) { - for (auto& parameter : node->parameters) { - Visit(parameter.get()); - } - } + // TODO: needed ?? + + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } +// used on upper levels void TypeCheckVisitor::Visit(AnyAnnotatedType* node) { - Visit(&node->type); - if (!node->typeclasses.empty() > 0) { - for (auto& typeclass : node->typeclasses) { - Visitor::Visit(typeclass); - } - } + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } // Flow control ----------------- void TypeCheckVisitor::Visit(MatchCase* node) { - Visitor::Visit(node->value); + Visitor::Visit(node->value); // TODO: literal & name instead of expression if (node->condition.has_value()) { Visitor::Visit(node->condition.value()); } + context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_); + if (node->statement.has_value()) { Visitor::Visit(node->statement.value()); } + // current_type_ from statement is current_type_ for MatchCase } -void TypeCheckVisitor::Visit(Match* node) { +void TypeCheckVisitor::Visit(Match* node) { // TODO return variant type ?? (problems with same types) + // TODO: types can be different in statement + utils::IdType type; + Visitor::Visit(node->value); - for (auto& match_case : node->matches) { - Visit(&match_case); + for (size_t i = 0; i < node->matches.size(); ++i) { + Visit(&node->matches[i]); + if (i == 0) { + type = current_type_; + } else { + context_manager_.EqualTypes(type, current_type_); + } } + + current_type_ = type; } -void TypeCheckVisitor::Visit(Condition* node) { - Visitor::Visit(node->conditions[0]); - Visitor::Visit(node->statements[0]); - for (size_t i = 1; i < node->conditions.size(); ++i) { +void TypeCheckVisitor::Visit(Condition* node) { // TODO return variant type ?? (problem with same types) + // TODO: types can be different in statement + utils::IdType type; + + for (size_t i = 0; i < node->conditions.size(); ++i) { Visitor::Visit(node->conditions[i]); + context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_); + Visitor::Visit(node->statements[i]); + if (i == 0) { + type = current_type_; + } else { + context_manager_.EqualTypes(type, current_type_); + } } + if (node->statements.size() > node->conditions.size()) { Visitor::Visit(node->statements[node->conditions.size()]); + context_manager_.EqualTypes(type, current_type_); + current_type_ = type; + } else { + current_type_ = context_manager_.AddType(info::type::OptionalType {type}); } } void TypeCheckVisitor::Visit(DoWhileLoop* node) { - out_ << "[Do] (\n"; - Visitor::Visit(node->statement); - out_ << ") [while] ("; Visitor::Visit(node->condition); - out_ << ")\n"; + context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_); + + Visitor::Visit(node->statement); + + info::type::ArrayType type; + type.size = 0; + type.elements_type = current_type_; + current_type_ = context_manager_.AddType(type); } void TypeCheckVisitor::Visit(WhileLoop* node) { - out_ << "[While] ("; - Visitor::Visit(node->statement); - out_ << ") [do] (\n"; Visitor::Visit(node->condition); - out_ << ")\n"; -} -void TypeCheckVisitor::Visit(ForLoop* node) { - out_ << "[For] ("; - Visitor::Visit(node->variable); - out_ << ") [in] ("; - Visitor::Visit(node->interval); - out_ << ") [do] (\n"; + context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Bool), current_type_); + Visitor::Visit(node->statement); - out_ << ")\n"; + + info::type::ArrayType type; + type.size = 0; + type.elements_type = current_type_; + current_type_ = context_manager_.AddType(type); +} + +void TypeCheckVisitor::Visit(ForLoop* node) { + Visitor::Visit(node->interval); + + if (!std::holds_alternative(context_manager_.GetType(current_type_))) { + error_handling::HandleTypecheckError("For loop interval type mismatch"); + } + + info::type::ArrayType type_value = + std::get(context_manager_.GetType(current_type_)); + + current_type_ = context_manager_.AddType(type_value.elements_type); + Visitor::Visit(node->variable); + + Visitor::Visit(node->statement); + + info::type::ArrayType type; + type.size = 0; + type.elements_type = current_type_; + current_type_ = context_manager_.AddType(type); } void TypeCheckVisitor::Visit(LoopLoop* node) { - out_ << "[Loop] (\n"; Visitor::Visit(node->statement); - out_ << ")\n"; + + info::type::ArrayType type; + type.size = 0; + type.elements_type = current_type_; + current_type_ = context_manager_.AddType(type); } // Statements, expressions, blocks, etc. ----------------- -void TypeCheckVisitor::Visit(Block* node) { - out_ << "[Block] {\n"; +void TypeCheckVisitor::Visit(Block* node) { // TODO return variant type ?? (problem with same types) + utils::IdType type; + + bool is_first_returned_type = true; + for (auto& statement : node->statements) { + returned_type_ = std::nullopt; Visitor::Visit(statement); + if (returned_type_.has_value()) { + if (is_first_returned_type) { + type = returned_type_.value(); + is_first_returned_type = false; + } else { + context_manager_.EqualTypes(type, returned_type_.value()); + } + } } - out_ << "}\n"; + + if (is_first_returned_type) { + type = context_manager_.AddType(info::type::InternalType::Unit); + } + + current_type_ = type; } void TypeCheckVisitor::Visit(ScopedStatement* node) { - out_ << "[Scoped] ( "; Visitor::Visit(node->statement); - out_ << ")\n"; + // current_type_ is type of statement } void TypeCheckVisitor::Visit(LoopControlExpression& node) { // enum - switch (node) { - case LoopControlExpression::Break: - out_ << "[Break]\n"; - break; - case LoopControlExpression::Continue: - out_ << "[Continue]\n"; - break; - } + current_type_ = context_manager_.AddType(info::type::InternalType::Unit); } // Operators +// -------------------------- TODO -------------------------- void TypeCheckVisitor::Visit(BinaryOperatorExpression* node) { - out_ << "[BinaryOperator] ("; - Visitor::Visit(node->left_expression); - out_ << ") ["; - Visit(&node->operator_name); - out_ << "] ("; - Visitor::Visit(node->right_expression); - out_ << ')'; + auto maybe_operator_id = namespace_visitor_.FindFunction({}, node->operator_name); + + if (!maybe_operator_id.has_value()) { + error_handling::HandleTypecheckError("Operator not found"); + } + + auto operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); + + if (operator_info->argument_count != 2) { + error_handling::HandleTypecheckError("Operator wrong argument count"); + } + + if (operator_info->definition.has_value()) { + Visitor::Visit(node->left_expression); + context_manager_.AddTypeRequirement(current_type_, + context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[0]})); + + Visitor::Visit(node->right_expression); + context_manager_.AddTypeRequirement(current_type_, + context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[1]})); + } else if (operator_info->declaration.has_value()) { + // TODO: get argument types + } else { + error_handling::HandleInternalError("Operator definition and declaration both not found", "TypeCheckVisitor"); + } + } +// -------------------------- TODO -------------------------- void TypeCheckVisitor::Visit(UnaryOperatorExpression* node) { - out_ << "[UnaryOperator "; - Visit(&node->operator_name); - out_ << "] ("; - Visitor::Visit(node->expression); - out_ << ')'; + auto maybe_operator_id = namespace_visitor_.FindFunction({}, node->operator_name); + + if (!maybe_operator_id.has_value()) { + error_handling::HandleTypecheckError("Operator not found"); + } + + auto operator_info = namespace_visitor_.GetGlobalInfo()->GetFunctionInfo(maybe_operator_id.value()); + + if (operator_info->argument_count != 1) { + error_handling::HandleTypecheckError("Operator wrong argument count"); + } + + if (operator_info->definition.has_value()) { + Visitor::Visit(node->expression); + context_manager_.AddTypeRequirement(current_type_, + context_manager_.AddType(info::type::AbstractType {operator_info->definition.value().node->argument_graph_ids_[0]})); + } else if (operator_info->declaration.has_value()) { + // TODO: get argument type + } else { + error_handling::HandleInternalError("Operator definition and declaration both not found", "TypeCheckVisitor"); + } } void TypeCheckVisitor::Visit(ReferenceExpression* node) { - out_ << "[ReferenceExpression "; - for (auto& reference : node->references) { - switch (reference) { - case ReferenceType::Reference: - out_ << '~'; - break; - case ReferenceType::UniqueReference: - out_ << '@'; - break; - } - } - out_ << "] ("; Visit(node->expression.get()); - out_ << ')'; + + info::type::ReferenceToType type; + type.references = node->references; + type.type = current_type_; + current_type_ = context_manager_.AddType(type); } -void TypeCheckVisitor::Visit(AccessExpression* node) { // TODO - Visitor::Visit(node->name); +void TypeCheckVisitor::Visit(AccessExpression* node) { Visitor::Visit(node->id); + context_manager_.EqualTypes(context_manager_.AddType(info::type::InternalType::Int), current_type_); + // TODO: separate type for counting ? + + Visitor::Visit(node->name.get()); + if (!std::holds_alternative(context_manager_.GetType(current_type_))) { + error_handling::HandleTypecheckError("Access type mismatch"); + } + + info::type::ArrayType type_value = + std::get(context_manager_.GetType(current_type_)); + + current_type_ = context_manager_.AddType(type_value.elements_type); } // Other Expressions +// -------------------------- TODO -------------------------- void TypeCheckVisitor::Visit(FunctionCallExpression* node) { - out_ << "[FunctionCall "; + // TODO: add function paramaters Visit(node->name.get()); - out_ << "] ("; - for (auto& argument : node->arguments) { - Visitor::Visit(argument); - out_ << ", "; - } - out_ << ")"; + if (!std::holds_alternative(context_manager_.GetType(current_type_))) { + error_handling::HandleTypecheckError("Mismatched types in function call expression"); + } + + info::type::FunctionType type_value = std::get(context_manager_.GetType(current_type_)); + + if (type_value.argument_types.size() != node->arguments.size()) { + error_handling::HandleTypecheckError("Mismatched argument count in function call expression"); + } + + for (size_t i = 0; i < node->arguments.size(); ++i) { + Visitor::Visit(node->arguments[i]); + if (std::holds_alternative(node->arguments[i])) { + } else if (std::holds_alternative(node->arguments[i])) { + } else { + // error + } + context_manager_.AddTypeRequirement(current_type_, type_value.argument_types[i]); + } + + current_type_ = type_value.return_type; } void TypeCheckVisitor::Visit(TupleExpression* node) { - out_ << "[TupleExpression] ("; + info::type::TupleType type; + + type.fields.reserve(node->expressions.size()); for (auto& expression : node->expressions) { - out_ << "&"; Visitor::Visit(expression); + type.fields.push_back({std::nullopt, current_type_}); } - out_ << ")"; + + current_type_ = context_manager_.AddType(std::move(type)); } void TypeCheckVisitor::Visit(VariantExpression* node) { - out_ << "[VariantExpression] ("; + info::type::VariantType type; + for (auto& expression : node->expressions) { - out_ << "|"; + info::type::TupleType constructor; + Visitor::Visit(expression); + + constructor.fields.push_back({std::nullopt, current_type_}); // ?? + type.constructors.push_back(constructor); } - out_ << ")"; + + current_type_ = context_manager_.AddType(std::move(type)); } void TypeCheckVisitor::Visit(ReturnExpression* node) { Visitor::Visit(node->expression); } -void TypeCheckVisitor::Visit(TypeConstructor* node) { - out_ << "[TypeConstructor "; - Visit(node->type.get()); - out_ << "]\n("; +// -------------------------- TODO -------------------------- +void TypeCheckVisitor::Visit(TypeConstructor* node) { // TODO: find constructor names, etc. + utils::IdType type; - bool is_first = true; - for (auto& parameter : node->parameters) { - if (!is_first) { - out_ << ")\n"; - is_first = false; - } - out_ << '('; - Visit(&std::get<0>(parameter)); - switch (std::get<1>(parameter)) { - case TypeConstructor::Assign: - out_ << " = "; - break; - case TypeConstructor::Move: - out_ << " <- "; - break; - } - Visitor::Visit(std::get<2>(parameter)); + Visit(node->type.get()); + type = current_type_; + + info::AnyTypeInfo* type_info = &std::get( + namespace_visitor_.GetGlobalInfo()->GetTypeInfo( + std::get(context_manager_.GetType(type)).type_id)->type); + + for (size_t i = 0; i < node->parameters.size(); ++i) { + //Visit(&std::get<0>(parameter)); + // TODO: remove variable on move + Visitor::Visit(std::get<2>(node->parameters[i])); + //context_manager_.EqualTypes(/* TODO type_info->get_field(paramater).type */, current_type_); } - out_ << ")\n"; + + current_type_ = type; } void TypeCheckVisitor::Visit(LambdaFunction* node) { - out_ << "[LambdaFunction] ("; - for (auto& parameter : node->parameters) { - Visit(parameter.get()); + info::type::FunctionType type; + + // for (auto& parameter : node->parameters) { + // Visit(parameter.get()); + // } + + type.argument_types.reserve(node->argument_graph_ids_.size()); + for (auto& argument_graph_id : node->argument_graph_ids_) { + type.argument_types.push_back(context_manager_.AddType(info::type::AbstractType {argument_graph_id})); } - if (!node->parameters.empty()) { - out_ << ") : ("; - } - for (auto& argument : node->arguments) { - Visit(&argument); - } - out_ << ") -> (\n"; + + type.return_type = context_manager_.AddType(info::type::AbstractType {node->return_type_graph_id_}); + Visitor::Visit(node->expression); - out_ << ")\n"; + context_manager_.AddTypeRequirement(type.return_type, current_type_); // right order ?? + + current_type_ = context_manager_.AddType(std::move(type)); } void TypeCheckVisitor::Visit(ArrayExpression* node) { - out_ << "[ArrayExpression] (["; - for (auto& element : node->elements) { - Visitor::Visit(element); - out_ << ';'; + info::type::ArrayType type; + + type.size = node->elements.size(); + + for (size_t i = 0; i < node->elements.size(); ++i) { + Visitor::Visit(node->elements[i]); + if (i == 0) { + type.elements_type = current_type_; + } else { + context_manager_.EqualTypes(type.elements_type.value(), current_type_); + } } - out_ << "])"; + + current_type_ = context_manager_.AddType(std::move(type)); } // Name -void TypeCheckVisitor::Visit(NameExpression* node) { - out_ << "[NameExpression] ("; - for (auto& variable_namespace : node->namespaces) { - Visitor::Visit(variable_namespace); - out_ << '.'; - } - for (size_t i = 0; i < node->expressions.size(); ++i) { - Visitor::Visit(node->expressions[i]); - if (i + 1 < node->expressions.size()) { - out_ << '.'; +// -------------------------- TODO -------------------------- +void TypeCheckVisitor::Visit(NameExpression* node) { // TODO: ?? functions without arguments ?? + std::vector path; + std::string type_name; + + path.reserve(node->namespaces.size()); + for (size_t i = 0; i < node->namespaces.size(); ++i) { + std::string current_name; + if (std::holds_alternative>(node->namespaces[i])) { + current_name = *std::get>(node->namespaces[i]); + } else if (std::holds_alternative>(node->namespaces[i])) { + Visit(std::get>(node->namespaces[i]).get()); + // TODO: use current_type_ + } + if (i + 1 == node->namespaces.size()) { + type_name = std::move(current_name); + } else { + path.push_back(std::move(current_name)); } } - out_ << ')'; + + // auto name_type = namespace_visitor_.FindType(); + path.push_back(type_name); + auto name_namespace = namespace_visitor_.FindNamespace(path); + + for (size_t i = 0; i < node->expressions.size(); ++i) { + // Visitor::Visit(node->expressions[i]); + } + + } void TypeCheckVisitor::Visit(TupleName* node) { utils::IdType type = current_type_; - auto type_value = std::get_if(context_manager_.GetType(type)); - - if (type_value = nullptr) { + if (!std::holds_alternative(context_manager_.GetType(type))) { error_handling::HandleTypecheckError("Mismatched types in tuple variable definition"); } - if (type_value->constructors.size() != node->names.size()) { + info::type::TupleType type_value = std::get(context_manager_.GetType(type)); + + if (type_value.fields.size() != node->names.size()) { error_handling::HandleTypecheckError("Mismatched field count in tuple variable definition"); } - for (auto& name : node->names) { - current_type_ = type_value->fields[i]; - Visitor::Visit(name); + for (size_t i = 0; i < node->names.size(); ++i) { + current_type_ = type_value.fields[i].second; + Visitor::Visit(node->names[i]); } + current_type_ = type; } -void TypeCheckVisitor::Visit(VariantName* node) { // TODO +void TypeCheckVisitor::Visit(VariantName* node) { utils::IdType type = current_type_; - auto type_value = std::get_if(context_manager_.GetType(type)); - - if (type_value = nullptr) { + if (!std::holds_alternative(context_manager_.GetType(type))) { error_handling::HandleTypecheckError("Mismatched types in variant variable definition"); } - if (type_value->constructors.size() != node->names.size()) { + info::type::VariantType type_value = std::get(context_manager_.GetType(type)); + + if (type_value.constructors.size() != node->names.size()) { error_handling::HandleTypecheckError("Mismatched variant count in variant variable definition"); } for (size_t i = 0; i < node->names.size(); ++i) { - current_type_ = info::type::VariantType::MakeOptional(type_value->constructors[i]); - Visitor::Visit(name); + if (std::holds_alternative(type_value.constructors[i])) { + current_type_ = context_manager_.AddType(info::type::OptionalType {}); + } else if (std::holds_alternative(type_value.constructors[i])) { + // TODO: optimize + current_type_ = context_manager_.AddType(info::type::OptionalType { context_manager_.AddType(std::get(type_value.constructors[i])) }); + } else { + // error + } + + Visitor::Visit(node->names[i]); } current_type_ = type; @@ -428,9 +594,9 @@ void TypeCheckVisitor::Visit(AnnotatedName* node) { void TypeCheckVisitor::Visit(FunctionType* node) { info::type::FunctionType type; - type.argument_type_ids.reserve(node->types.size()); - for (auto& type : node->types) { - Visitor::Visit(type); + type.argument_types.reserve(node->types.size()); + for (auto& argument_type : node->types) { + Visitor::Visit(argument_type); type.argument_types.push_back(current_type_); } @@ -474,8 +640,7 @@ void TypeCheckVisitor::Visit(VariantType* node) { void TypeCheckVisitor::Visit(ParametrizedType* node) { info::type::DefinedType type; - Visit(node->type_expression.get()); - type.type = current_type_; + type.type_id = node->type_expression->type_id_; type.paramaters.reserve(node->parameters.size()); for (auto& paramater : node->parameters) { diff --git a/src/visitor.cpp b/src/visitor.cpp index 2b06376..337c564 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -319,4 +319,363 @@ void Visitor::Visit(Literal& node) { } } +//////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Sources ----------------- + +void Visitor::Visit(SourceFile* node) { + for (auto& statement : node->statements) { + if (std::holds_alternative(statement)) { + Visit(&std::get(statement)); + } else if (std::holds_alternative(statement)) { + Visit(std::get(statement)); + } else { + // error + } + } +} + +void Visitor::Visit(Sources* node) { + for (auto& statement : node->statements) { + Visit(statement); + } +} + +// Namespaces, partitions ----------------- + +void Visitor::Visit(Partition* node) { + Visit(node->scope.get()); +} + +void Visitor::Visit(Namespace* node) { + if (node->name.has_value()) { + Visit(&node->name.value()); + } + Visit(&node->type); + Visit(node->scope.get()); +} + +// Definitions ----------------- + +void Visitor::Visit(ImportStatement* node) { + for (auto& symbol : node->symbols) { + Visit(&symbol); + } +} + +void Visitor::Visit(AliasDefinitionStatement* node) { + Visit(&node->type); + Visit(node->value.get()); +} + +void Visitor::Visit(VariableDefinitionStatement* node) { + Visit(node->name); + Visit(node->value); +} + +void Visitor::Visit(FunctionDeclaration* node) { + Visit(&node->name); + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + Visit(node->type.get()); +} + +void Visitor::Visit(FunctionDefinitionStatement* node) { + Visit(node->definition.get()); + Visit(node->value); +} + +void Visitor::Visit(TypeDefinitionStatement* node) { + Visit(node->definition.get()); + Visit(node->value); +} + +void Visitor::Visit(AbstractTypeDefinitionStatement* node) { + Visit(node->type.get()); +} + +void Visitor::Visit(TypeclassDefinitionStatement* node) { + Visit(node->definition.get()); + for (auto& requirement : node->requirements) { + Visit(requirement.get()); + } +} + +// Definition parts + +void Visitor::Visit(FunctionDefinition* node) { + Visit(&node->name); + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + for (auto& argument : node->arguments) { + Visit(&argument); + } +} + +void Visitor::Visit(TypeDefinition* node) { + Visit(node->type.get()); + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } +} + +void Visitor::Visit(AnyAnnotatedType* node) { + Visit(&node->type); + for (auto& typeclass : node->typeclasses) { + Visit(typeclass); + } +} + +// Flow control ----------------- + +void Visitor::Visit(MatchCase* node) { + Visit(node->value); + if (node->condition.has_value()) { + Visit(node->condition.value()); + } + if (node->statement.has_value()) { + Visit(node->statement.value()); + } +} + +void Visitor::Visit(Match* node) { + Visit(node->value); + for (auto& match_case : node->matches) { + Visit(&match_case); + } +} + +void Visitor::Visit(Condition* node) { + for (size_t i = 0; i < node->conditions.size(); ++i) { + Visit(node->conditions[i]); + Visit(node->statements[i]); + } + if (node->statements.size() > node->conditions.size()) { + Visit(node->statements[node->conditions.size()]); + } +} + +void Visitor::Visit(DoWhileLoop* node) { + Visit(node->statement); + Visit(node->condition); +} + +void Visitor::Visit(WhileLoop* node) { + Visit(node->condition); + Visit(node->statement); +} +void Visitor::Visit(ForLoop* node) { + Visit(node->variable); + Visit(node->interval); + Visit(node->statement); +} + +void Visitor::Visit(LoopLoop* node) { + Visit(node->statement); +} + +// Statements, expressions, blocks, etc. ----------------- + +void Visitor::Visit(Block* node) { + for (auto& statement : node->statements) { + Visit(statement); + } +} + +void Visitor::Visit(ScopedStatement* node) { + Visit(node->statement); +} + +void Visitor::Visit(LoopControlExpression& node) {} // enum + +// Operators + +void Visitor::Visit(BinaryOperatorExpression* node) { + Visit(node->left_expression); + Visit(&node->operator_name); + Visit(node->right_expression); +} + +void Visitor::Visit(UnaryOperatorExpression* node) { + Visit(&node->operator_name); + Visit(node->expression); +} + +void Visitor::Visit(ReferenceExpression* node) { + Visit(node->expression.get()); +} + +void Visitor::Visit(AccessExpression* node) { + Visit(node->name.get()); + Visit(node->id); +} + +// Other Expressions + +void Visitor::Visit(FunctionCallExpression* node) { + Visit(node->name.get()); + for (auto& argument : node->arguments) { + Visit(argument); + } +} + +void Visitor::Visit(TupleExpression* node) { + for (auto& expression : node->expressions) { + Visit(expression); + } +} + +void Visitor::Visit(VariantExpression* node) { + for (auto& expression : node->expressions) { + Visit(expression); + } +} + +void Visitor::Visit(ReturnExpression* node) { + Visit(node->expression); +} + +void Visitor::Visit(TypeConstructor* node) { + Visit(node->type.get()); + for (auto& parameter : node->parameters) { + Visit(&std::get<0>(parameter)); + Visit(std::get<2>(parameter)); + } +} + +void Visitor::Visit(LambdaFunction* node) { + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + for (auto& argument : node->arguments) { + Visit(&argument); + } + Visit(node->expression); +} + +void Visitor::Visit(ArrayExpression* node) { + for (auto& element : node->elements) { + Visit(element); + } +} + +// Name + +void Visitor::Visit(NameExpression* node) { + for (auto& variable_namespace : node->namespaces) { + Visit(variable_namespace); + } + for (size_t i = 0; i < node->expressions.size(); ++i) { + Visit(&node->expressions[i]); + } +} + +void Visitor::Visit(TupleName* node) { + for (auto& name : node->names) { + Visit(name); + } +} + +void Visitor::Visit(VariantName* node) { + for (auto& name : node->names) { + Visit(name); + } +} + +void Visitor::Visit(AnnotatedName* node) { + Visit(&node->name); + if (node->type.has_value()) { + Visitor::Visit(node->type.value()); + } +} + +// Type, typeclass, etc. ----------------- + +// Type + +void Visitor::Visit(FunctionType* node) { + for (auto& type : node->types) { + Visitor::Visit(type); + } +} + +void Visitor::Visit(TupleType* node) { + if (node->type.has_value()) { + Visit(&node->type.value()); + } + for (auto& entity : node->entities) { + if (entity.first.has_value()) { + Visit(&entity.first.value()); + } + Visit(entity.second.get()); + } +} + +void Visitor::Visit(VariantType* node) { + if (node->type.has_value()) { + Visit(&node->type.value()); + } + for (auto& constructor : node->constructors) { + if (std::holds_alternative(constructor)) { + Visit(&std::get(constructor)); + } else if (std::holds_alternative>(constructor)) { + Visit(std::get>(constructor).get()); + } else { + // error + } + } +} + +void Visitor::Visit(ParametrizedType* node) { + Visit(node->type_expression.get()); + for (auto& parameter : node->parameters) { + Visit(parameter); + } +} + +void Visitor::Visit(TypeExpression* node) { + for (auto& type_namespace : node->namespaces) { + Visit(type_namespace); + } + Visit(&node->type); +} + +void Visitor::Visit(ExtendedScopedAnyType* node) { + Visit(node->type); +} + +// Typeclass + +void Visitor::Visit(ParametrizedTypeclass* node) { + Visit(node->typeclass_expression.get()); + for (auto& parameter : node->parameters) { + Visit(parameter); + } +} + +void Visitor::Visit(TypeclassExpression* node) { + for (auto& typeclass_namespace : node->namespaces) { + Visit(typeclass_namespace); + } + Visit(&node->typeclass); +} + +// Identifiers, constants, etc. ----------------- + +void Visitor::Visit(ExtendedName* node) {} + +void Visitor::Visit(std::string* node) {} // std::string + +void Visitor::Visit(FloatNumberLiteral* node) {} + +void Visitor::Visit(NumberLiteral* node) {} + +void Visitor::Visit(StringLiteral* node) {} + +void Visitor::Visit(CharLiteral* node) {} + } // namespace interpreter +