diff --git a/include/error_handling.hpp b/include/error_handling.hpp new file mode 100644 index 0000000..3c9d4df --- /dev/null +++ b/include/error_handling.hpp @@ -0,0 +1,29 @@ +#include + +enum class ErrorVisitor { + BuildVisitor, + PrintVisitor, + FindSymbolsVisitor, + // ... +}; + +// TODO +inline void handle_error(std::string message, ErrorVisitor visitor) { // TODO: add place in code + std::string visitor_str; + switch (visitor) { + case ErrorVisitor::BuildVisitor: + visitor_str = "Build Visitor"; + break; + case ErrorVisitor::PrintVisitor: + visitor_str = "Print Visitor"; + break; + case ErrorVisitor::FindSymbolsVisitor: + visitor_str = "Find Symbols Visitor"; + break; + // ... + default: + break; + } + std::cerr << "Error: " << message << " in " << visitor_str; + exit(1); +} diff --git a/include/find_symbols_visitor.hpp b/include/find_symbols_visitor.hpp new file mode 100644 index 0000000..a1b51a3 --- /dev/null +++ b/include/find_symbols_visitor.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include +#include + +// for clangd +#include "visitor.hpp" +#include "global_info.hpp" + +// TODO: +// add/remove global variables +// + +namespace interpreter { + +class FindSymbolsVisitor : public Visitor { +public: + explicit FindSymbolsVisitor(info::GlobalInfo& global_info) : global_info_(global_info) {} + +private: + //// void Visit(Node* node) override; + + // Sources ----------------- + + void Visit(SourceFile* node) override; + void Visit(Sources* node) override; + + // Namespaces, partitions ----------------- + + void Visit(Partition* node) override; + void Visit(Namespace* node) override; + + // Definitions ----------------- + + void Visit(ImportStatement* node) override; + void Visit(UsageDefinition* node) override; + void Visit(AliasDefinition* node) override; + //// void Visit(VariableDefinition* node) override; // TODO: decide + void Visit(FunctionDeclaration* node) override; + void Visit(FunctionDefinition* node) override; + void Visit(AliasTypeDefinition* node) override; + void Visit(TypeDefinition* node) override; + void Visit(TypeclassDefinition* node) override; + + // Definition parts + + void Visit(DefinedName* node) override; + void Visit(DefinedAnnotatedName* node) override; + void Visit(DefinedType* node) override; + void Visit(DefinedTypeclass* node) override; + void Visit(DefinitionParameter* node) override; + void Visit(DefinitionArgument* 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; + + // Statements, expressions, blocks, etc. ----------------- + + //// void Visit(Block* node) override; + //// void Visit(ScopedStatement* node) override; + + //// void Visit(LoopControlExpression& node) override; // enum + + // Operators + + void Visit(BinaryOperatorExpression* node) override; + void Visit(UnaryOperatorExpression* node) override; + + // Simple Expressions + + //// void Visit(FunctionCallExpression* node) override; + //// void Visit(TupleExpression* node) override; + //// void Visit(VariantExpression* node) override; + //// void Visit(ReturnExpression* node) override; + + // Lambda + + //// void Visit(LambdaFunction* node) override; + + // Name + + void Visit(NameSuperExpression* node) override; + void Visit(NameExpression* node) override; + void Visit(TupleName* node) override; + void Visit(VariantName* node) override; + void Visit(AnnotatedName* node) override; + + // Type + + void Visit(TypeConstructor* node) override; + void Visit(TupleType* node) override; + void Visit(VariantType* node) override; + void Visit(AnnotatedType* node) override; + void Visit(ParametrizedType* node) override; + void Visit(TypeExpression* node) override; + + // Typeclass + + void Visit(AnnotatedTypeclass* node) override; + void Visit(ParametrizedTypeclass* node) override; + void Visit(TypeclassExpression* node) override; + + // Identifiers, constants, etc. ----------------- + + //// void Visit(AnyIdentifier* node) override; // std::string + + //// void Visit(FloatNumberLiteral* node) override; + //// void Visit(NumberLiteral* node) override; + //// void Visit(StringLiteral* node) override; + //// void Visit(CharLiteral* node) override; +private: + info::GlobalInfo& global_info_; + std::any current_info_; +}; + +} // namespace interpreter diff --git a/include/global_info.hpp b/include/global_info.hpp index bc16a82..e5ed998 100644 --- a/include/global_info.hpp +++ b/include/global_info.hpp @@ -8,18 +8,95 @@ namespace info { +// TODO: partitions class GlobalInfo { public: - GlobalInfo(); + GlobalInfo() { + namespace_stack.push_back(&global_namespace_); + } + + template + void AddImport(T&& import_info) { + if (waiting_usage.has_value()) { + usages_[waiting_usage.value()] = std::forward(import_info); + waiting_usage = std::nullopt; + } else { + imports_.push_back(std::forward(import_info)); + } + } + + void AddUsageForNextImport(const std::string& name) { + if (waiting_usage.has_value()) { + // error + } + waiting_usage = name; + } + + void AddEnterNamespace(const std::optional& var, + const std::string& type) { + NamespaceInfo* namespace_info = &namespace_stack.back()->namespaces[type].emplace_back(); + namespace_stack.push_back(namespace_info); + + namespace_info->var = var; + namespace_info->type_name = type; + } + + void ExitNamespace() { + if (namespace_stack.size() <= 1) { + // error + return; + } + + namespace_stack.pop_back(); + } + + void ToGlobalNamespace() { + namespace_stack.clear(); + namespace_stack.push_back(&global_namespace_); + } + + template + void AddFunctionDeclaration(const std::string& name, + T&& function_declaration_info) { + FunctionInfo* function_info = &namespace_stack.back()->functions[name]; + + function_info->declaration = std::forward(function_declaration_info); + } + + template + void AddFunctionDefinition(const std::string& name, + T&& function_definition_info) { + FunctionInfo* function_info = &namespace_stack.back()->functions[name]; + + function_info->definition = std::forward(function_definition_info); + } + + template + void AddType(const std::string& type, + T&& type_info) { + &namespace_stack.back()->types[type] = std::forward(type_info); + } + + template + void AddTypeclass(const std::string& typeclass, + T&& typeclass_info) { + namespace_stack.back()->typeclasses[typeclass] = std::forward(typeclass_info); + } + + // AddVar ?? // TODO: decide + + // FindFunction + // FindType + + // FindVar ?? - // ?? EnterNamespace / ExitNamespace ?? - // concurrent work ?? - // AddType, AddFunction - // TODO private: - std::unordered_map namespaces_; + std::vector namespace_stack; + std::optional waiting_usage; + NamespaceInfo global_namespace_; - // lock for concurrency ?? + std::vector imports_; + std::unordered_map usages_; }; } // namespace info diff --git a/include/symbols_info.hpp b/include/symbols_info.hpp index f29e7bf..b59c374 100644 --- a/include/symbols_info.hpp +++ b/include/symbols_info.hpp @@ -1,10 +1,12 @@ #pragma once +#include "interpreter_tree.hpp" #include #include -#include #include +#include #include +#include // for clangd @@ -34,63 +36,110 @@ struct Value { }; // better variant value storage (then string) ?? -struct Info { - std::string name; -}; - struct VariantTypeInfo; struct TupleTypeInfo; struct AliasTypeInfo; +struct TypeInfo; + +struct TypeclassInfo; + enum class BuiltInTypeInfo { StringT, IntT, FloatT, }; -using TypeInfo = std::variant; +struct TypeUsageInfo { + std::vector param_names; + std::vector param_types; + std::vector arg_names; // ??, arg expr ?? +}; -struct VariableInfo : public Info { - Value value; +struct ParameterInfo { + std::string name; + std::vector param_names; + std::vector param_types; + std::vector arg_names; // ?? +}; + +struct AnyTypeInfo { + std::vector params; // ?? + std::vector arg_names; + + std::variant, + std::unique_ptr, + std::unique_ptr> info; +}; + +struct VariableInfo { + std::string name; + std::optional value; TypeInfo* type = nullptr; }; // TODO lambda functions as values -// TODO aliases ?? - -struct TupleTypeInfo : public Info { - std::vector, TypeInfo>> fields; +struct TupleTypeInfo { + std::optional name; + std::vector, AnyTypeInfo>> fields; }; -struct VariantTypeInfo : public Info { +struct VariantTypeInfo { + std::optional name; std::vector> constructors; // ?? any type instead of tuple type ?? }; -struct AliasTypeInfo : public Info { - bool isAnotherType; // = true by default ?? - TypeInfo* type = nullptr; +struct AliasTypeInfo { + std::vector params; + bool isAnotherType; + TypeUsageInfo value; }; -struct TypeclassInfo : public Info { - // TODO +struct TypeInfo { std::variant type; }; + +// struct PointerInfo { // ?? +// VariableInfo* variable; +// }; + +struct FunctionDeclarationInfo { + std::vector params; + std::vector arg_types; }; -struct PointerInfo { - VariableInfo* variable; +struct FunctionDefinitionInfo { + std::vector params; // TODO: dublicates ?? + std::vector arg_names; + + interpreter::tokens::SuperExpression* expression; }; -struct FunctionInfo : public Info { - interpreter::Node* definition; - std::vector args; +struct FunctionInfo { + FunctionDeclarationInfo declaration; + FunctionDefinitionInfo definition; // add requirements ?? }; -struct NamespaceInfo : public Info { +struct TypeclassInfo { + std::vector params; + std::vector arg_names; + std::vector requirements; +}; + +struct ImportInfo { + std::string module_name; + std::vector symbols; +}; + +struct NamespaceInfo { std::unordered_map types; - std::unordered_map variables; + std::unordered_map typeclasses; + // std::unordered_map variables; // TODO std::unordered_map functions; - std::unordered_map namespaces; + std::unordered_map> namespaces; + std::optional var; + std::string type_name; + TypeInfo* type_info = nullptr; }; } // namespace info diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index b6a1443..4cad466 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -24,7 +24,7 @@ void BuildVisitor::Visit(SourceFile* node) { Visit(std::get(node->statements[i])); } else if (current_node_type == parser::tokens::Partition) { node->statements[i].emplace(); - Visit(&std::get(node->statements[i])); + Visit(&std::get(node->statements[i]) ); } } @@ -1174,27 +1174,27 @@ void BuildVisitor::Visit(AnyName& node) { // Type void BuildVisitor::Visit(TypeConstructor* node) { - auto parse_node = current_node_; - - current_node_ = parse_node.ChildByFieldName("type"); - node->type = std::make_unique(); - Visit(node->type.get()); - - size_t parameter_count = (parse_node.NamedChildCount() - 1) / 2; - - node->parameters.resize(parameter_count); - - for (size_t i = 0; i < parameter_count * 2; ++i) { - current_node_ = parse_node.NthNamedChild(i + 1); - - if (i % 2 == 0) { - node->parameters[i / 2].first = current_node_.GetValue(); - } else { - Visit(node->parameters[i / 2].second); - } - } - - current_node_ = parse_node; + // auto parse_node = current_node_; + // + // current_node_ = parse_node.ChildByFieldName("type"); + // node->type = std::make_unique(); + // Visit(node->type.get()); + // + // size_t parameter_count = (parse_node.NamedChildCount() - 1) / 2; + // + // node->parameters.resize(parameter_count); + // + // for (size_t i = 0; i < parameter_count * 2; ++i) { + // current_node_ = parse_node.NthNamedChild(i + 1); + // + // if (i % 2 == 0) { + // node->parameters[i / 2].first = current_node_.GetValue(); + // } else { + // Visit(node->parameters[i / 2].second); + // } + // } + // + // current_node_ = parse_node; } void BuildVisitor::Visit(TupleType* node) { @@ -1538,8 +1538,8 @@ void BuildVisitor::Visit(NameSubSuperExpression& node) { std::string current_node_type = current_node_.GetType(); if (current_node_type == parser::tokens::NameIdentifier) { // optimize ?? - // TODO: choose : node = std::make_unique(current_node_.GetValue()); - Visit(std::get>(node).get()); + node = std::make_unique(current_node_.GetValue()); + //Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::Literal) { node = std::make_unique(); Visit(*std::get>(node)); diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp new file mode 100644 index 0000000..27f4c1b --- /dev/null +++ b/src/find_symbols_visitor.cpp @@ -0,0 +1,492 @@ +// for clangd +#include "../include/find_symbols_visitor.hpp" + +namespace interpreter { + +// Sources ----------------- +void FindSymbolsVisitor::Visit(SourceFile* node) { + for (auto& statement : node->statements) { + if (std::holds_alternative(statement)) { + Visit(&std::get(statement)); + } else if (std::holds_alternative(statement)) { + Visitor::Visit(std::get(statement)); + } else { + // error + } + } +} + +void FindSymbolsVisitor::Visit(Sources* node) { + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } +} + +// Namespaces, partitions ----------------- + +void FindSymbolsVisitor::Visit(Partition* node) { + // TODO + Visit(node->scope.get()); +} + +void FindSymbolsVisitor::Visit(Namespace* node) { + if (std::holds_alternative>(node->name)) { + Visit(std::get>(node->name).get()); + auto info = std::move(std::any_cast>(current_info_)); + global_info_.AddEnterNamespace(info.first, info.second); + current_info_.reset(); + } else if (std::holds_alternative>(node->name)) { + Visit(std::get>(node->name).get()); + auto info = std::move(std::any_cast(current_info_)); + global_info_.AddEnterNamespace(std::nullopt, info); + current_info_.reset(); + } else { + // error + } + Visit(node->scope.get()); + global_info_.ExitNamespace(); +} + +// Definitions ----------------- + +void FindSymbolsVisitor::Visit(ImportStatement* node) { + info::ImportInfo info; + info.module_name = node->module_name; + for (auto& symbol : node->symbols) { + Visitor::Visit(symbol); + info.symbols.push_back(std::move(std::any_cast(current_info_))); + } + global_info_.AddImport(std::move(info)); + // TODO: what if inside usage definition, global_info_.AddImport(std::move(info)); +} + +void FindSymbolsVisitor::Visit(UsageDefinition* node) { + global_info_.AddUsageForNextImport(node->name); + Visit(node->import_statement.get()); +} + +// <-- current position + +void FindSymbolsVisitor::Visit(AliasDefinition* node) { + info::TypeInfo info; + + Visit(node->type.get()); + auto type_info = std::move(std::any_cast>>(current_info_)); + current_info_.reset(); + + Visit(node->value.get()); + auto value_info = std::move(std::any_cast(current_info_)); + current_info_.reset(); + + info::AliasTypeInfo alias_info; + alias_info.isAnotherType = false; + alias_info.params = std::move(type_info.second); + alias_info.value = std::move(value_info); + info.type = std::move(alias_info); + + global_info_.AddType(type_info.first, info); +} + +// void FindSymbolsVisitor::Visit(VariableDefinition* node) { // TODO: decide +// out_ << "(Variable " << (node->is_const ? "const" : "var") << ' '; +// Visit(&node->name); +// out_ << " = "; +// Visitor::Visit(node->value); +// out_ << ")\n"; +// } + +void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { + info::FunctionDeclarationInfo info; + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + auto param_info = std::move(std::any_cast(current_info_)); + current_info_.reset(); + info.params.push_back(std::move(param_info)); + } + for (auto& argument_type : node->argument_types) { + Visitor::Visit(argument_type); + auto type_info = std::move(std::any_cast(current_info_)); + current_info_.reset(); + info.arg_types.push_back(std::move(type_info)); + } + global_info_.AddFunctionDeclaration(node->name, std::move(info)); +} + +void FindSymbolsVisitor::Visit(FunctionDefinition* node) { + info::FunctionDefinitionInfo info; + + Visit(node->name.get()); + auto name_info = std::move( + std::any_cast, + std::vector>>>(current_info_)); + current_info_.reset(); + + info.params = std::move(name_info.second.first); + info.arg_names = std::move(name_info.second.second); + info.expression = &node->value; + + global_info_.AddFunctionDefinition(name_info.first, std::move(info)); +} + +void FindSymbolsVisitor::Visit(AliasTypeDefinition* node) { // TODO: unite with AliasDefinition + info::TypeInfo info; + + Visit(node->type.get()); + auto type_info = std::move(std::any_cast>>(current_info_)); + current_info_.reset(); + + Visit(node->value.get()); + auto value_info = std::move(std::any_cast(current_info_)); + current_info_.reset(); + + info::AliasTypeInfo alias_info; + alias_info.isAnotherType = true; + alias_info.params = std::move(type_info.second); + alias_info.value = std::move(value_info); + + info.type = std::move(alias_info); + + global_info_.AddType(type_info.first, std::move(info)); +} + +void FindSymbolsVisitor::Visit(TypeDefinition* node) { + info::TypeInfo info; + + Visit(node->type.get()); + auto type_info = std::move( + std::any_cast, + std::vector>>>(current_info_)); + current_info_.reset(); + + Visitor::Visit(node->value); + auto value_info = std::move(std::any_cast>(current_info_)); + current_info_.reset(); + + info::AnyTypeInfo any_type_info; + any_type_info.params = std::move(type_info.second.first); + any_type_info.arg_names = std::move(type_info.second.second); + + switch (value_info.index()) { + case 0: + any_type_info.info = + std::make_unique( + std::move(std::get(value_info))); + break; + case 1: + any_type_info.info = + std::make_unique( + std::move(std::get(value_info))); + break; + case 2: + any_type_info.info = + std::make_unique( + std::move(std::get(value_info))); + break; + default: + // error + break; + } + + info.type = std::move(any_type_info); + + global_info_.AddType(type_info.first, std::move(info)); +} + +void FindSymbolsVisitor::Visit(TypeclassDefinition* node) { + info::TypeclassInfo info; + + Visit(node->typeclass.get()); + auto typeclass_info = std::move( + std::any_cast, + std::vector>>>(current_info_)); + current_info_.reset(); + info.params = std::move(typeclass_info.second.first); + info.arg_names = std::move(typeclass_info.second.second); + + for (auto& requirement : node->requirements) { + Visit(requirement.get()); + auto requrement_info = std::move(std::any_cast(current_info_)); + current_info_.reset(); + info.requirements.push_back(std::move(requrement_info)); + } + + global_info_.AddTypeclass(typeclass_info.first, std::move(info)); +} + +// Definition parts + +void FindSymbolsVisitor::Visit(DefinedName* node) { + out_ << "(DefinedName "; + Visit(&node->name); + if (!node->parameters.empty()) { + out_ << "\n"; + } + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + if (!node->arguments.empty()) { + out_ << " : \n"; + } + for (auto& argument : node->arguments) { + Visit(argument.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(DefinedAnnotatedName* node) { + out_ << "(DefinedAnnotatedName "; + Visit(&node->name); + out_ << " : "; + if (std::holds_alternative>(node->type)) { + Visit(std::get>(node->type).get()); + } else if (std::holds_alternative>(node->type)) { + Visit(std::get>(node->type).get()); + } else { + // no annotation + } + out_ << " )"; +} + +void FindSymbolsVisitor::Visit(DefinedType* node) { + out_ << "(DefinedType "; + Visit(node->type.get()); + if (!node->parameters.empty()) { + out_ << "\n"; + } + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + if (!node->arguments.empty()) { + out_ << " : \n"; + } + for (auto& argument : node->arguments) { + Visit(argument.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(DefinedTypeclass* node) { + out_ << "(DefinedTypeclass "; + Visit(node->typeclass.get()); + if (!node->parameters.empty()) { + out_ << "\n"; + } + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + if (!node->arguments.empty()) { + out_ << " : \n"; + } + for (auto& argument : node->arguments) { + Visit(argument.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(DefinitionParameter* node) { + out_ << "(DefinitionParameter " << (!node->typeclasses.empty() > 0 ? "(" : ""); + Visit(&node->type); + out_ << ' '; + for (auto& typeclass : node->typeclasses) { + Visit(typeclass.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(DefinitionArgument* node) { + out_ << "(DefinitionArgument " << (!node->types.empty() ? "(" : ""); + Visit(&node->name); + out_ << ' '; + for (auto& type : node->types) { + Visit(type.get()); + } + out_ << ")"; +} + +// Statements, expressions, blocks, etc. ----------------- + +// Name + +void FindSymbolsVisitor::Visit(NameSuperExpression* node) { + out_ << "(NameSuperExpression "; + 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_ << '.'; + } + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(NameExpression* node) { + out_ << "(NameExpression "; + for (auto& variable_namespace : node->namespaces) { + Visitor::Visit(variable_namespace); + out_ << '.'; + } + for (size_t i = 0; i < node->names.size(); ++i) { + Visit(&node->names[i]); + if (i + 1 < node->names.size()) { + out_ << '.'; + } + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(TupleName* node) { + out_ << "(TupleName "; + for (auto& name : node->names) { + out_ << '&'; + Visit(name.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(VariantName* node) { + out_ << "(VariantName "; + for (auto& name : node->names) { + out_ << '|'; + Visit(name.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(AnnotatedName* node) { + out_ << "(AnnotatedName "; + Visit(&node->name); + if (node->type.has_value()) { + out_ << " : "; + Visit(node->type.value().get()); + } + out_ << " )"; +} + +// Type + +void FindSymbolsVisitor::Visit(TypeConstructor* node) { + out_ << "(TypeConstructor "; + Visit(node->type.get()); + out_ << '\n'; + for (auto& parameter : node->parameters) { + Visit(¶meter.first); + out_ << " = "; + Visitor::Visit(parameter.second); + out_ << '\n'; + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(TupleType* node) { + out_ << "(TupleType "; + if (node->type.has_value()) { + Visit(&node->type.value()); + } + out_ << ' '; + for (auto& entity : node->entities) { + out_ << "& "; + if (entity.first.has_value()) { + Visit(&entity.first.value()); + out_ << " : "; + } + Visitor::Visit(entity.second); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(VariantType* node) { + out_ << "(VariantType "; + if (node->type.has_value()) { + Visit(&node->type.value()); + } + out_ << ' '; + for (auto& constructor : node->constructors) { + out_ << "| "; + if (std::holds_alternative(constructor)) { + Visit(&std::get(constructor)); + } else if (std::holds_alternative>(constructor)) { + Visit(std::get>(constructor).get()); + } else { + // error + } + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(AnnotatedType* node) { + out_ << "(AnnotatedType "; + Visit(node->type_expression.get()); + if (!node->annotations.empty()) { + out_ << " :"; + } + for (auto& annotation : node->annotations) { + out_ << " "; + Visit(annotation.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(ParametrizedType* node) { + out_ << "(ParametrizedType "; + Visit(node->type_expression.get()); + for (auto& parameter : node->parameters) { + out_ << ' '; + Visitor::Visit(parameter); + } + out_ << " )"; +} + +void FindSymbolsVisitor::Visit(TypeExpression* node) { + out_ << "(TypeExpression "; + for (auto& type_namespace : node->namespaces) { + Visitor::Visit(type_namespace); + out_ << '.'; + } + Visit(&node->type); + out_ << " )"; +} + +// Typeclass + +void FindSymbolsVisitor::Visit(AnnotatedTypeclass* node) { + out_ << "(AnnotatedTypeclass "; + Visit(node->typeclass_expression.get()); + if (!node->annotations.empty()) { + out_ << " :"; + } + for (auto& annotation : node->annotations) { + out_ << " "; + Visit(annotation.get()); + } + out_ << ")"; +} + +void FindSymbolsVisitor::Visit(ParametrizedTypeclass* node) { + out_ << "(ParametrizedTypeclass "; + Visit(node->typeclass_expression.get()); + for (auto& paramater : node->parameters) { + out_ << ' '; + Visitor::Visit(paramater); + } + out_ << " )"; +} + +void FindSymbolsVisitor::Visit(TypeclassExpression* node) { + out_ << "(TypeclassExpression "; + for (auto& typeclass_namespace : node->namespaces) { + Visitor::Visit(typeclass_namespace); + out_ << '.'; + } + Visit(&node->typeclass); + out_ << " )"; +} + +} // namespace interpreter