diff --git a/.clang_tidy b/.clang_tidy new file mode 100644 index 0000000..e8ef467 --- /dev/null +++ b/.clang_tidy @@ -0,0 +1,18 @@ +Checks: "*, + -abseil-*, + -altera-*, + -android-*, + -fuchsia-*, + -google-*, + -llvm*, + -modernize-use-trailing-return-type, + -zircon-*, + -readability-else-after-return, + -readability-static-accessed-through-instance, + -readability-avoid-const-params-in-decls, + -cppcoreguidelines-non-private-member-variables-in-classes, + -misc-non-private-member-variables-in-classes, +" +WarningsAsErrors: '' +HeaderFilterRegex: '' +FormatStyle: none diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..c7a47fe --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Add: [-std=c++17] diff --git a/.gitignore b/.gitignore index e83f82e..e2c3c16 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,9 @@ compile_commands.json CTestTestfile.cmake _deps + +build +build_make +cmake-build-debug + +.idea diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..01357f7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "lang-parser"] + path = lang-parser + url = https://codeberg.org/ProgramSnail/lang-parser.git +[submodule "tree-sitter"] + path = tree-sitter + url = https://github.com/tree-sitter/tree-sitter.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..60f3366 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.10) + +project(LangInterpreter) + +set(CMAKE_CXX_STANDARD 17) + +# find_package(Catch2 2 REQUIRED) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + +include_directories(include + tree-sitter/lib/src + tree-sitter/lib/include) + + +# add_executable(interpreter_tests tests/tests.cpp) +# target_link_libraries(tests PRIVATE Catch2::Catch2WithMain) + +add_executable(lang_interpreter src/main.cpp + src/types.cpp + src/values.cpp + src/utils.cpp + src/global_info.cpp + src/typeclass_graph.cpp + src/visitor.cpp + src/build_visitor.cpp + src/print_visitor.cpp + src/find_symbols_visitor.cpp + src/link_symbols_visitor.cpp + src/type_check_visitor.cpp + src/typed_print_visitor.cpp + src/execute_visitor.cpp + lang-parser/src/parser.c + lang-parser/src/tree_sitter/parser.h + tree-sitter/lib/src/lib.c) diff --git a/README.md b/README.md index 3ba44a4..0cbce79 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # lang-interpreter +Build steps: + +- clone submodules +- cd lang-parser/ && tree-sitter generate +- mkdir build && cd build/ && cmake .. && make + +**lang_interpreter** is interpreter diff --git a/archived/abstract_types_contexts.hpp b/archived/abstract_types_contexts.hpp new file mode 100644 index 0000000..0113185 --- /dev/null +++ b/archived/abstract_types_contexts.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include +#include + +// for clangd +#include "utils.hpp" + +namespace info { + +class AbstractTypesContextManager { +public: + void EnterContext() { + contexts_.emplace_back(); + } + + void ExitContext() { + if (contexts_.empty()) { + // error + } + + contexts_.pop_back(); + } + + void ExitFromAllContexts() { + contexts_.clear(); + } + + bool DefineType(const std::string& type, utils::IdType id) { + return contexts_.back().DefineType(type, id); + } + + std::optional GetTypeId(const std::string& type) { + for (ssize_t i = contexts_.size() - 1; i >= 0; --i) { + auto maybe_type = contexts_[i].GetTypeId(type); + if (maybe_type.has_value()) { + return maybe_type.value(); + } + } + return std::nullopt; + } + +private: + class Context { + public: + bool DefineType(const std::string& type, utils::IdType id) { + if (types_.count(type) > 0) { + return false; + } + types_[type] = id; + return true; + } + + std::optional GetTypeId(const std::string& type) { + auto type_iter = types_.find(type); + + if (type_iter == types_.end()) { + return std::nullopt; + } + + return type_iter->second; + } + + private: + std::unordered_map types_; + }; + + std::vector contexts_; +}; + +} // namespace info diff --git a/archived/symbols_info.hpp b/archived/symbols_info.hpp new file mode 100644 index 0000000..de8f391 --- /dev/null +++ b/archived/symbols_info.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include "interpreter_tree.hpp" +#include +#include +#include +#include +#include +#include + +// for clangd +#include "utils.hpp" + +namespace interpreter { + class Node; +} // namespace interpreter + +namespace info { + +struct VariantTypeInfo; +struct TupleTypeInfo; +struct AliasTypeInfo; + +struct TypeInfo; + +struct TypeclassInfo; + +enum class BuiltInTypeInfo { + StringT, + IntT, + FloatT, + UnitT, +}; + +struct TypeUsageInfo { + interpreter::tokens::TypeExpression* node; + TypeInfo* info = nullptr; +}; + +struct ParameterInfo { + std::string type; + std::vector typeclass_nodes; + std::vector typeclass_types; +}; + +struct AbstractTypeInfo { + enum { Basic, Abstract } modifier; + ParameterInfo type; +}; + +struct AliasTypeInfo { + enum {Alias, Type, Let} modifier; + std::vector parameters; + TypeUsageInfo value; +}; + +struct AnyTypeInfo { + ParameterInfo type; + std::vector parameters; + interpreter::tokens::AnyType* value; +}; + +struct TypeInfo { + std::variant type; +}; + +struct ConstructorInfo { + std::string name; + size_t order; + utils::IdType type_id; +}; + +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::FunctionDefinitionStatement* node = nullptr; +}; + +struct FunctionInfo { + size_t argument_count = 0; + std::optional declaration; + std::optional definition; +}; + +struct TypeclassInfo { + std::vector parameters; + std::vector requirements; +}; + +struct ImportInfo { + std::string module_name; + std::vector symbols; +}; + +struct NamespaceInfo { + enum Modifier { Const, Var }; + + std::unordered_map types; + std::unordered_map typeclasses; + std::unordered_map functions; + std::unordered_map constructors; + std::unordered_map namespaces; + std::unordered_map> variable_namespaces; + + std::optional modifier; + std::optional variable; + std::string type_name; + TypeInfo* type_info = nullptr; +}; + +} // namespace info diff --git a/archived/type_graph.hpp b/archived/type_graph.hpp new file mode 100644 index 0000000..6f36270 --- /dev/null +++ b/archived/type_graph.hpp @@ -0,0 +1,235 @@ +//////////////////////////////////////////////////////////////////////////////////////// +// Temporary frozen, TODO +//////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include +#include + +// for clangd +#include "utils.hpp" + +namespace info { + +// TODO: fix dfs, etc. +// TODO: optimize recalc + +class TypeGraph { +public: + size_t AddVertex(const std::vector& methods = {}, + const std::vector& typeclasses = {}) { + is_calculated_ = false; + + Vertex vertex; + + for (auto& method : methods) { + vertex.new_requirements.methods.insert(storage_.GetId(method)); + } + + for (auto& typeclass : typeclasses) { + vertex.new_requirements.typeclasses.insert(storage_.GetId(typeclass)); + } + + verticles_.push_back(vertex); + edges_.emplace_back(); + back_edges_.emplace_back(); + + groups_.AddElement(); + + return verticles_.size() - 1; + } + + std::vector VertexMethods(size_t id) { + if (!is_calculated_) { + // error + return {}; + } + + size_t cluster_id = verticles_[id].cluster.value(); + + std::vector methods; + + methods.reserve(cluster_requirements_[cluster_id].methods.size()); + + for (auto& method : cluster_requirements_[cluster_id].methods) { + methods.push_back(std::move(storage_.GetValue(method))); + } + + return methods; + } + + std::vector VertexTypeclasses(size_t id) { + if (!is_calculated_) { + // error + return {}; + } + + size_t cluster_id = verticles_[id].cluster.value(); + + typeclasses_[id].methods[method.first].definition = method.second.definition; + std::vector typeclasses; + + typeclasses.reserve(cluster_requirements_[cluster_id].typeclasses.size()); + + for (auto& typeclass : cluster_requirements_[cluster_id].typeclasses) { + typeclasses.push_back(typeclass); + } + + return typeclasses; + } + + void AddMethod(size_t id, const std::string& method) { + is_calculated_ = false; + + verticles_[id].new_requirements.methods.insert(storage_.GetId(method)); + } + + void AddTypeclass(size_t id, utils::IdType typeclass) { + is_calculated_ = false; + + verticles_[id].new_requirements.typeclasses.insert(typeclass); + } + + void AddEdge(size_t from, size_t to) { + is_calculated_ = false; + + edges_[from].push_back(to); + back_edges_[to].push_back(from); + } + + void SetEqual(size_t u, size_t v) { + AddEdge(u, v); + AddEdge(v, u); + groups_.Unite(u, v); + } + + void Calculate() { + if (is_calculated_) { + return; + } + + auto clusters = FindClusters(); + + std::vector cluster_requirements(clusters.size()); + std::vector> cluster_edges(clusters.size()); + + for (size_t i = 0; i < clusters.size(); ++i) { + for (auto& vertex_id : clusters[i]) { + for (auto& method : verticles_[vertex_id].new_requirements.methods) { + cluster_requirements[i].methods.insert(method); + } + verticles_[vertex_id].new_requirements.methods.clear(); + + for (auto& typeclass : verticles_[vertex_id].new_requirements.typeclasses) { + cluster_requirements[i].typeclasses.insert(typeclass); + } + verticles_[vertex_id].new_requirements.methods.clear(); + + for (auto& edge : edges_[vertex_id]) { + cluster_edges[i].insert(edge); + } + } + } + + // TODO: check, that clusters are top sorted + for (size_t i = 0; i < clusters.size(); ++i) { + for (auto& edge : cluster_edges[i]) { + for (auto& method : cluster_requirements[edge].methods) { + cluster_requirements[i].methods.insert(method); + } + + for (auto& typeclass : cluster_requirements[edge].typeclasses) { + cluster_requirements[i].typeclasses.insert(typeclass); + } + } + } + + for (size_t i = 0; i < clusters.size(); ++i) { + for (auto& vertex_id : clusters[i]) { + verticles_[vertex_id].cluster = i; + } + } + + clusters_ = std::move(clusters); + cluster_requirements_ = std::move(cluster_requirements); + + is_calculated_ = true; + } + + + +private: + struct RequirementsData { + std::unordered_set methods; + std::unordered_set typeclasses; + }; + + struct Vertex { + RequirementsData new_requirements; + std::optional cluster; + }; + + std::vector> FindClusters() { + std::vector> clusters; + + auto sorted_verticles = BackTopSort(); + + std::vector marks(sorted_verticles.size(), 0); + for (size_t i = 0; i < sorted_verticles.size(); ++i) { + if (marks[i] == 0) { + clusters.emplace_back(); + BackVisitDfs(i, clusters[i], marks, back_edges_, clusters.size()); + } + } + + return clusters; + } + + void BackVisitDfs(size_t id, + std::vector& verticles, + std::vector& marks, + const std::vector>& edges, + size_t mark) { + if (marks[id] != 0) { + return; + } + + marks[id] = mark; + + for (size_t i = 0; i < edges[id].size(); ++i) { + BackVisitDfs(id, verticles, marks, edges, mark); + } + + verticles.push_back(id); + } + + std::vector BackTopSort() { + std::vector sorted_verticles; + std::vector marks(verticles_.size(), 0); + + for (size_t i = 0; i < marks.size(); ++i) { + BackVisitDfs(i, sorted_verticles, marks, edges_, 1); + } + + return sorted_verticles; + } + +private: + std::vector> edges_; + std::vector> back_edges_; + std::vector verticles_; + + std::vector> clusters_; + std::vector cluster_requirements_; + + utils::Storage storage_; + utils::GroupsManager groups_; + + bool is_calculated_ = false; +}; + +} // namespace info diff --git a/include/build_visitor.hpp b/include/build_visitor.hpp new file mode 100644 index 0000000..2d0b3e3 --- /dev/null +++ b/include/build_visitor.hpp @@ -0,0 +1,151 @@ +#pragma once + +// for clangd +#include "interpreter_tree.hpp" +#include "visitor.hpp" +#include "parse_tree.hpp" + +namespace interpreter { + +class BuildVisitor : public Visitor { +public: + explicit BuildVisitor(const parser::ParseTree& parse_tree) : parse_tree_(parse_tree) {} + + void VisitSourceFile(SourceFile* source_file) override { + current_node_ = parse_tree_.GetRoot(); + Visit(source_file); + } + +private: + // Sources ----------------- + + void Visit(SourceFile* node) override; + + // Namespaces, partitions ----------------- + + void Visit(NamespaceSources* node) override; + void Visit(Namespace* node) override; + + // Definitions ----------------- + + void Visit(ImportStatement* node) override; + void Visit(AliasDefinitionStatement* node) override; + void Visit(VariableDefinitionStatement* node) override; + void Visit(FunctionDeclaration* node) override; + void Visit(FunctionDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; + void Visit(AbstractTypeDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; + void Visit(PartitionStatement* node) override; + + void Visit(NamespaceStatement& node) override; // variant + void Visit(SourceStatement& node) override; // variant + + // Definition parts + + void Visit(FunctionDefinition* node) override; + void Visit(TypeDefinition* node) override; + void Visit(AnyAnnotatedType* node) override; + + // Flow control ----------------- + + void Visit(TypeConstructorPatternParameter* node) override; + void Visit(TypeConstructorPattern* 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; + + void Visit(Pattern& node) override; // variant + void Visit(FlowControl& node) override; // variant + + // Statements, expressions, blocks, etc. ----------------- + + void Visit(BlockStatement& node) override; // variant + + void Visit(Block* node) override; + + void Visit(SubExpressionToken& node) override; // variant + void Visit(SubExpression& node) override; // variant + void Visit(PrefixedExpression& node) override; // variant + void Visit(Expression& node) override; // variant + void Visit(SuperExpression& node) override; // variant + + void Visit(ScopedStatement* node) override; + + // Operators + + void Visit(ReferenceExpression* node) override; + void Visit(AccessExpression* node) override; + + // Other expressions + + void Visit(FunctionCallExpression* node) override; + + void Visit(TupleExpression* node) override; + void Visit(VariantExpression* node) override; + void Visit(ReturnExpression* node) override; + void Visit(TypeConstructorParameter* node) override; + void Visit(TypeConstructor* node) override; + void Visit(LambdaFunction* node) override; + void Visit(ArrayExpression* node) override; + + void Visit(LoopControlExpression& node) override; // enum + + // Name + + void Visit(PartitionName* node) override; + void Visit(NameExpression* node) override; + void Visit(TupleName* node) override; + void Visit(VariantName* node) override; + void Visit(AnnotatedName* node) override; + + void Visit(AnyName& node) override; // variant + + // Type, typeclass, etc. ----------------- + + // Type + + void Visit(FunctionType* node) override; + void Visit(TupleType* node) override; + void Visit(VariantType* node) override; + void Visit(TypeExpression* node) override; + + void Visit(AnyType& node) override; // variant + + void Visit(ExtendedScopedAnyType* node) override; + + // Typeclass + + void Visit(ParametrizedTypeclass* node) override; + + // Typeclass & Type + + void Visit(ParametrizedType* 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; + void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; + + void Visit(Literal& node) override; // variant + + // + + void VisitBinaryOperatorExpression(FunctionCallExpression* node); + +private: + const parser::ParseTree& parse_tree_; + parser::ParseTree::Node current_node_; +}; + +} // namespace interpreter diff --git a/include/builtin_functions.hpp b/include/builtin_functions.hpp new file mode 100644 index 0000000..25324de --- /dev/null +++ b/include/builtin_functions.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +// for clangd + +namespace info::builtin { + +template +inline void Print(const T& value) { // only for strings ?? + std::cout << "\x1b[1;32mOutput:\x1b[0m "; + std::cout << value; + std::cout << '\n'; +} + +template +inline T Read() { + T value; + std::cout << "\x1b[1;32mInput:\x1b[0m "; + std::cin >> value; + return value; +} + +} // namespace info diff --git a/include/contexts.hpp b/include/contexts.hpp new file mode 100644 index 0000000..853701b --- /dev/null +++ b/include/contexts.hpp @@ -0,0 +1,275 @@ +#pragma once + +#include +#include +#include +#include +#include + +// for clangd +#include "error_handling.hpp" +#include "utils.hpp" + +namespace info { + +template +class ContextManager { +public: + ContextManager() { + contexts_.emplace_back(true); // no difference ?? + } + + size_t ContextCount() { + return contexts_.size(); + } + + template + utils::IdType AddValue(const T& value, utils::ValueType value_type) { + return value_manager_.AddValue(value, value_type); + } + + utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { + return value_manager_.AddAnyValue(std::move(value), value_type); + } + + template + std::optional GetValue(utils::IdType value_id) { + return value_manager_.template GetValue(value_id); + } + + Value* GetAnyValue(utils::IdType value_id) { + return value_manager_.GetAnyValue(value_id); + } + + bool AddValueRequirement(utils::IdType type, utils::IdType requrement) { + return value_manager_.AddValueRequirement(type, requrement); + } + + bool EqualValues(utils::IdType first_type, utils::IdType second_type) { + return value_manager_.EqualValues(first_type, second_type); + } + + utils::ValueType GetValueType(utils::IdType value_id) { + return value_manager_.GetValueType(value_id); + } + + void ModifiyValue(utils::IdType value_id, utils::ValueType new_value_type) { + value_manager_.SetValueType(value_id, new_value_type); + } + + utils::IdType ToModifiedValue(utils::IdType value_id, utils::ValueType new_value_type) { + Value value = *GetAnyValue(value_id); + return AddAnyValue(std::move(value), new_value_type); + } + + utils::IdType ToModifiedValueCopy(utils::IdType value_id, + utils::ValueType new_value_type) { + Value* value = GetAnyValue(value_id); + return value->DeepCopy(&value_manager_, new_value_type); + } + + // make deep copy if not temporary + utils::IdType ToTemporaryValue(utils::IdType value_id) { + if (GetValueType(value_id) == utils::ValueType::Tmp) { + return value_id; + } + + return ToModifiedValueCopy(value_id, utils::ValueType::Tmp); + } + + ValueManager* GetValueManager() { + return &value_manager_; + } + + void EnterContext(bool is_hiding_previous = false) { + contexts_.emplace_back(is_hiding_previous); + } + + void ExitContext() { + if (contexts_.empty()) { + error_handling::HandleInternalError("contexts_ is empty", + "ContextManager.ExitContext", + std::nullopt); + } + + contexts_.pop_back(); + } + + void ChangeHidingOfCurrentContextTo(bool is_hiding_previous) { + contexts_.back().ChangeHidingTo(is_hiding_previous); + } + + bool DefineVariable(const std::string& name, utils::IdType value_id) { + return contexts_.back().DefineVariable(name, value_id); + } + + bool DefineLocalType(const std::string& name, utils::IdType type_id) { + return contexts_.back().DefineLocalType(name, type_id); + } + + bool AssignVariable(const std::string& name, utils::IdType value_id) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { + if (contexts_[i].AssignVariable(name, value_id)) { + return true; + } + + if (contexts_[i].IsHidingPrevious()) { + break; + } + } + return false; + } + + bool AssignLocalType(const std::string& name, utils::IdType type_id) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { + if (contexts_[i].AssignLocalType(name, type_id)) { + return true; + } + + if (contexts_[i].IsHidingPrevious()) { + break; + } + } + return false; + } + + 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; + } + + if (contexts_[i].IsHidingPrevious()) { + break; + } + } + return false; + } + + void EnterVariableContext(const std::string& name, + utils::IdType value_id, + bool is_hiding_previous = false) { + EnterContext(is_hiding_previous); + + DefineVariable(name, value_id); + } + + std::optional FindVariable(const std::string& name) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { + auto maybe_variable = contexts_[i].FindVariable(name); + if (maybe_variable.has_value()) { + return maybe_variable.value(); + } + + if (contexts_[i].IsHidingPrevious()) { + break; + } + } + return std::nullopt; + } + + std::optional FindLocalType(const std::string& name) { + for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { + auto maybe_type = contexts_[i].FindLocalType(name); + if (maybe_type.has_value()) { + return maybe_type.value(); + } + + if (contexts_[i].IsHidingPrevious()) { + break; + } + } + return std::nullopt; + } + +private: + class Context { + public: + explicit Context(bool is_hiding_previous) : is_hiding_previous_(is_hiding_previous) {} + + bool DefineVariable(const std::string& name, utils::IdType value_id) { + if (name == "_") { // placeholder + return true; + } + + if (variables_.count(name) != 0) { + return false; + } + variables_[name] = value_id; + return true; + } + + bool DefineLocalType(const std::string& name, utils::IdType type_id) { + if (local_types_.count(name) != 0) { + return false; + } + local_types_[name] = type_id; + return true; + } + + bool AssignVariable(const std::string& name, utils::IdType value_id) { + if (name == "_") { // placeholder + return true; + } + + auto variable_iter = variables_.find(name); + if (variable_iter == variables_.end()) { + return false; + } + variable_iter->second = value_id; + return true; + } + + bool AssignLocalType(const std::string& name, utils::IdType type_id) { + auto local_type_iter = local_types_.find(name); + if (local_type_iter == local_types_.end()) { + return false; + } + local_type_iter->second = type_id; + return true; + } + + bool RemoveVariable(const std::string& name) { + return variables_.erase(name); + } + + std::optional FindVariable(const std::string& name) { + auto variable_iter = variables_.find(name); + + if (variable_iter == variables_.end()) { + return std::nullopt; + } + + return variable_iter->second; + } + + std::optional FindLocalType(const std::string& name) { + auto local_abstract_type_iter = local_types_.find(name); + + if (local_abstract_type_iter == local_types_.end()) { + return std::nullopt; + } + + return local_abstract_type_iter->second; + } + + bool IsHidingPrevious() { + return is_hiding_previous_; + } + + void ChangeHidingTo(bool is_hiding_previous) { + is_hiding_previous_ = is_hiding_previous; + } + + private: + std::unordered_map variables_; + std::unordered_map local_types_; + + bool is_hiding_previous_ = false; + }; + + std::vector contexts_; + ValueManager value_manager_; +}; + +} // namespace info diff --git a/include/definitions.hpp b/include/definitions.hpp new file mode 100644 index 0000000..6a09d8c --- /dev/null +++ b/include/definitions.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +// for clangd +#include "interpreter_tree.hpp" +#include "utils.hpp" + +namespace interpreter { + class Node; +} // namespace interpreter + +namespace info::definition { + +struct Namespace; + +struct TypeUsage { + interpreter::tokens::TypeExpression* node; +}; + +struct Parameter { + std::string type; + std::vector typeclass_nodes; + + interpreter::tokens::AnyAnnotatedType* node = nullptr; +}; + +struct AbstractType { + utils::AbstractTypeModifier modifier; + Parameter type; + interpreter::tokens::AbstractTypeDefinitionStatement* node = nullptr; +}; + +struct AliasType { + utils::AliasModifier modifier; + std::vector parameters; + TypeUsage value; + interpreter::tokens::AliasDefinitionStatement* node = nullptr; +}; + +struct AnyType { + Parameter type; + std::vector parameters; + utils::ClassModifier modifier; + interpreter::tokens::TypeDefinitionStatement* node = nullptr; + + utils::IdType parent_namespace = 0; +}; + +struct Type { + std::variant type; +}; + +struct Constructor { + std::string name; + std::optional order; // no order for tuple types + utils::IdType type_id = 0; + std::optional constructor_tuple_node; +}; + +struct FunctionDeclaration { + std::vector parameters; + std::vector argument_types; + interpreter::tokens::FunctionDeclaration* node = nullptr; +}; + +struct FunctionDefinition { + std::vector argument_names; + interpreter::tokens::FunctionDefinitionStatement* node = nullptr; +}; + +struct Function { + size_t argument_count = 0; + std::optional declaration; + std::optional definition; +}; + +struct Typeclass { + std::vector parameters; + interpreter::tokens::TypeclassDefinitionStatement* node; + + utils::IdType parent_namespace = 0; + + utils::IdType graph_id_ = 0; // TODO: make safe?? +}; + +struct Import { + std::string module_name; + std::vector symbols; // size == 0 => all symbols imported +}; + +struct Namespace { + std::unordered_map types; + std::unordered_map functions; + std::unordered_map constructors; + std::unordered_map namespaces; + std::unordered_map var_namespaces; + std::unordered_map const_namespaces; + + utils::IdType parent_namespace = 0; + + utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; + std::string type_name; + + // all nodes have same info + std::optional any_node; +}; + +} // namespace info::definition diff --git a/include/error_handling.hpp b/include/error_handling.hpp new file mode 100644 index 0000000..619e51c --- /dev/null +++ b/include/error_handling.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include "interpreter_tree.hpp" +#include +#include + +namespace error_handling { + +inline void PrintPosition(std::ostream& out, + std::pair start_position, + std::pair end_position) { + out << '[' + << start_position.first + 1 + << ", " + << start_position.second + 1 + << "] - [" + << end_position.first + 1 + << ", " + << end_position.second + 1 + << ']'; +} + +inline void HandleParsingError(const std::string& message, + std::pair start_position, + std::pair end_position) { + std::cerr << "\x1b[1;31mParsing Error:\x1b[0m " << message << " at "; + PrintPosition(std::cerr, start_position, end_position); + std::cerr << ".\n"; + exit(1); +} + +inline void HandleGeneralError(const std::string& message) { + std::cerr << "\x1b[1;31mGeneral Error:\x1b[0m " << message << ".\n"; + exit(1); +} + +inline void HandleInternalError(const std::string& message, + const std::string& place, + std::optional node) { + std::cerr << "\x1b[1;31mInternal Error:\x1b[0m " << message << " at " << place; + if (node.has_value()) { + std::cerr << ", at "; + PrintPosition(std::cerr, node.value()->start_position, node.value()->end_position); + } + std::cerr << ".\n"; + exit(1); +} + +inline void HandleTypecheckError(const std::string& message, + const interpreter::tokens::BaseNode& node) { + std::cerr << "\x1b[1;31mTypecheck Error:\x1b[0m " << message << " at "; + PrintPosition(std::cerr, node.start_position, node.end_position); + std::cerr << ".\n"; + exit(1); +} + +inline void HandleRuntimeError(const std::string& message, + const interpreter::tokens::BaseNode& node) { + std::cerr << "\x1b[1;31mRuntime Error:\x1b[0m " << message << " at "; + PrintPosition(std::cerr, node.start_position, node.end_position); + std::cerr << ".\n"; + exit(1); +} + +inline void HandleNamesError(const std::string& message, + const interpreter::tokens::BaseNode& node) { + std::cerr << "\x1b[1;31mNames Error:\x1b[0m " << message << " at "; + PrintPosition(std::cerr, node.start_position, node.end_position); + std::cerr << ".\n"; + exit(1); +} + +template +inline void DebugPrint(const T& value) { + std::cerr << "\x1b[1;33mDebug:\x1b[0m " << value << '\n'; +} + +} // namespace error_handling diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp new file mode 100644 index 0000000..0d1da6e --- /dev/null +++ b/include/execute_visitor.hpp @@ -0,0 +1,193 @@ +#pragma once + +#include + +// for clangd +#include "contexts.hpp" +#include "global_info.hpp" +#include "interpreter_tree.hpp" +#include "types.hpp" +#include "utils.hpp" +#include "values.hpp" +#include "visitor.hpp" +#include "error_handling.hpp" + +namespace interpreter { + +class ExecuteVisitor : public Visitor { +public: + explicit ExecuteVisitor(info::GlobalInfo& global_info, + info::ContextManager& type_context_manager, + info::ContextManager& context_manager) + : global_info_(global_info), + typeclass_graph_(*global_info.GetTypeclassGraph()), + type_context_manager_(type_context_manager), + context_manager_(context_manager) {} + + void VisitSourceFile(SourceFile* node) override { + error_handling::HandleInternalError("VisitSourceFile unavailible", + "ExecuteVisitor.VisitSourceFile", + &node->base); + }; + + void ExecutePartition(interpreter::tokens::PartitionStatement* partition) { + Visit(partition); + } + +private: + // Sources ----------------- + + void Visit(SourceFile* node) override; + + // Namespaces, partitions ----------------- + + void Visit(NamespaceSources* node) override; + void Visit(Namespace* node) override; + + // Definitions ----------------- + + void Visit(ImportStatement* node) override; + void Visit(AliasDefinitionStatement* node) override; + void Visit(VariableDefinitionStatement* node) override; + void Visit(FunctionDeclaration* node) override; + void Visit(FunctionDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; + void Visit(AbstractTypeDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; + void Visit(PartitionStatement* node) override; + + // Definition parts + + // // void Visit(FunctionDefinition* node) override; + // // void Visit(TypeDefinition* node) override; + // // void Visit(AnyAnnotatedType* node) override; + + // Flow control ----------------- + + void Visit(TypeConstructorPatternParameter* node) override; + void Visit(TypeConstructorPattern* 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; + + // Operators + + void Visit(ReferenceExpression* node) override; + void Visit(AccessExpression* node) override; + + // Simple Expressions + + void Visit(FunctionCallExpression* node) override; + + void Visit(TupleExpression* node) override; + void Visit(VariantExpression* node) override; + void Visit(ReturnExpression* node) override; + void Visit(TypeConstructorParameter* node) override; + void Visit(TypeConstructor* node) override; + void Visit(LambdaFunction* node) override; + void Visit(ArrayExpression* node) override; + + void Visit(LoopControlExpression& node) override; // enum + + // Name + + // // void Visit(PartitionName* 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(TypeExpression* node) override; + + void Visit(ExtendedScopedAnyType* node) override; + + // Typeclass + + void Visit(ParametrizedTypeclass* node) override; + + // Typeclass & Type + + void Visit(ParametrizedType* node) override; + + // Identifiers, constants, etc. ----------------- + + // // void Visit(std::string* node) override; // std::string + + void Visit(FloatNumberLiteral* node) override; + void Visit(NumberLiteral* node) override; + void Visit(StringLiteral* node) override; + void Visit(CharLiteral* node) override; + void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; + + bool HandleCondition(Expression& condition, const BaseNode& base_node); + void CollectTypeContext(const ParametrizedType& type); + void CheckPattern(Pattern& node, const BaseNode& base_node); + + template + T* ExtractValue(utils::IdType value, const BaseNode& base_node) { + std::optional maybe_value_info = context_manager_.GetValue(value); + if (!maybe_value_info.has_value()) { + error_handling::HandleRuntimeError("Value has value class that is different from exprected one", base_node); + } + return maybe_value_info.value(); + } + + template + T* ExtractInternalValue(utils::IdType value, const BaseNode& base_node) { + info::value::InternalValue* value_info = ExtractValue(value, base_node); + std::optional maybe_internal_value_info = value_info->GetValue(); + if (!maybe_internal_value_info.has_value()) { + error_handling::HandleRuntimeError("Value has internal value class that is different from exprected one", base_node); + } + return maybe_internal_value_info.value(); + } + + utils::IdType GraphIdByTypeId(utils::IdType type_id) { + auto maybe_any_type = global_info_.GetTypeInfo(type_id); + if (!maybe_any_type.has_value()) { + error_handling::HandleInternalError("Only AnyType implemented", + "ExecuteVisitor.ExtractInternalValue", + std::nullopt); + } + return maybe_any_type.value()->node->definition->type->graph_id_; + } + + // + + bool HandleBuiltinFunctionCall(FunctionCallExpression* node); + + bool HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, + info::type::InternalType type); +private: + info::GlobalInfo& global_info_; + info::TypeclassGraph& typeclass_graph_; + info::ContextManager& type_context_manager_; + + info::ContextManager& context_manager_; + // local types store types graph ids + + utils::IdType current_value_; + std::optional active_loop_control_expression_; + std::optional is_const_definition_; + bool case_matched_; +}; + +} // namespace interpreter diff --git a/include/find_symbols_visitor.hpp b/include/find_symbols_visitor.hpp new file mode 100644 index 0000000..b5a6ef2 --- /dev/null +++ b/include/find_symbols_visitor.hpp @@ -0,0 +1,127 @@ +#pragma once + +#include +#include + +// for clangd +#include "interpreter_tree.hpp" +#include "visitor.hpp" +#include "global_info.hpp" + +namespace interpreter { + +class FindSymbolsVisitor : public Visitor { +public: + explicit FindSymbolsVisitor(info::GlobalInfo& global_info) + : namespace_visitor_(global_info.CreateVisitor()) {} + +private: + // Sources ----------------- + + // void Visit(SourceFile* node) override; // default + + // Namespaces, partitions ----------------- + + // void Visit(NamespaceSources* node) override; // default + void Visit(Namespace* node) override; + + // Definitions ----------------- + + void Visit(ImportStatement* node) override; + void Visit(AliasDefinitionStatement* node) override; + // // void Visit(VariableDefinitionStatement* node) override; + void Visit(FunctionDeclaration* node) override; + void Visit(FunctionDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; + void Visit(AbstractTypeDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; + void Visit(PartitionStatement* node) override; + + // Definition parts + + // // void Visit(FunctionDefinition* node) override; + // // void Visit(TypeDefinition* node) override; + void Visit(AnyAnnotatedType* node) override; + + // Flow control ----------------- + + // // void Visit(TypeConstructorPatternParameter* node) override; + // // void Visit(TypeConstructorPattern* 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; + + // Operators + + // // void Visit(ReferenceExpression* node) override; + // // void Visit(AccessExpression* node) override; + + // Simple Expressions + + // // void Visit(FunctionCallExpression* node) override; + + // // void Visit(TupleExpression* node) override; + // // void Visit(VariantExpression* node) override; + // // void Visit(ReturnExpression* node) override; + // // void Visit(TypeConstructorParameter* node) override; + // // void Visit(TypeConstructor* node) override; + // // void Visit(LambdaFunction* node) override; + // // void Visit(ArrayExpression* node) override; + + // // void Visit(LoopControlExpression& node) override; // enum + + // Name + + // // void Visit(PartitionName* 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(TypeExpression* node) override; + + // // void Visit(ExtendedScopedAnyType* node) override; + + // Typeclass + + // // void Visit(ParametrizedTypeclass* node) override; + + // Typeclass & Type + + // // void Visit(ParametrizedType* node) override; + + // Identifiers, constants, etc. ----------------- + + // // void Visit(std::string* node) override; // std::string + + // // void Visit(FloatNumberLiteral* node) override; + // // void Visit(NumberLiteral* node) override; + // // void Visit(StringLiteral* node) override; + // // void Visit(CharLiteral* node) override; + // // void Visit(UnitLiteral* node) override; + // // void Visit(BoolLiteral* node) override; + +private: + info::GlobalInfo::NamespaceVisitor namespace_visitor_; + + std::any current_info_; +}; + +} // namespace interpreter diff --git a/include/global_info.hpp b/include/global_info.hpp new file mode 100644 index 0000000..fe95619 --- /dev/null +++ b/include/global_info.hpp @@ -0,0 +1,401 @@ +#pragma once + +#include +#include +#include +#include + +// for clangd +#include "definitions.hpp" +#include "interpreter_tree.hpp" +#include "typeclass_graph.hpp" +#include "utils.hpp" + +namespace info { + +// TODO: add classes / structs and functions module interface +class GlobalInfo { + friend class NamespaceVisitor; +public: + GlobalInfo() { + namespaces_.emplace_back(); // global namespace + } + + struct PartitionInfo { + std::vector path; + interpreter::tokens::PartitionStatement* node = nullptr; + }; + + class NamespaceVisitor { + friend GlobalInfo; + NamespaceVisitor() = delete; + public: + + struct Path { + std::vector> path_types; + definition::Namespace* result; + }; + + void AddImport(definition::Import&& import_info, const std::optional& name = std::nullopt); + + void AddEnterNamespace(const std::string& name, + utils::ClassInternalsModifier modifier, + std::optional node, + const interpreter::tokens::BaseNode& base_node); + + void EnterNamespace(const std::string& name, + utils::ClassInternalsModifier modifier); + + void ExitNamespace(); + + void ToGlobalNamespace(); + + utils::IdType AddFunctionDeclaration(const std::string& name, + definition::FunctionDeclaration&& function_declaration_info, + const interpreter::tokens::BaseNode& base_node); + + utils::IdType AddFunctionDefinition(const std::string& name, + definition::FunctionDefinition&& function_definition_info, + const interpreter::tokens::BaseNode& base_node); + + utils::IdType AddType(const std::string& type, + definition::Type&& type_info, + const interpreter::tokens::BaseNode& base_node); + + utils::IdType AddAbstractType(const std::string& abstract_type, + definition::AbstractType&& abstract_type_info, + const interpreter::tokens::BaseNode& base_node); + + utils::IdType AddTypeclass(const std::string& typeclass, + definition::Typeclass&& typeclass_info, + const interpreter::tokens::BaseNode& base_node); + + utils::IdType AddConstructor(const std::string& constructor, + definition::Constructor&& constructor_info, + const interpreter::tokens::BaseNode& base_node); + + utils::IdType AddPartition(const std::vector& path, + interpreter::tokens::PartitionStatement* node, + const interpreter::tokens::BaseNode& base_node); + + std::optional FindNamespaceId(const std::optional>& path); + + std::optional FindFunctionId(const std::optional>& path, + const std::string& name); + + std::optional FindMethodId(const std::optional>& path, + const std::string& type, + const std::string& name, + utils::IsConstModifier modifier); + + std::optional FindTypeId(const std::optional>& path, + const std::string& type); + + std::optional FindLocalTypeId(const std::string& type); + + std::optional FindAbstractTypeId(const std::string& abstract_type); + + std::optional FindTypeclassId(const std::string& typeclass); + + std::optional FindConstructorId(const std::optional>& path, + const std::string& constructor); + + std::optional FindNamespace(const std::optional>& path) { + std::optional id = FindNamespaceId(path); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetNamespaceInfo(id.value()); + } + + std::optional FindFunction(const std::optional>& path, + const std::string& name) { + std::optional id = FindFunctionId(path, name); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetFunctionInfo(id.value()); + } + + std::optional FindMethod(const std::optional>& path, + const std::string& type, + const std::string& name, + utils::IsConstModifier modifier) { + std::optional id = FindMethodId(path, type, name, modifier); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetFunctionInfo(id.value()); + } + + std::optional FindAnyType(const std::optional>& path, + const std::string& type) { + std::optional id = FindTypeId(path, type); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetAnyTypeInfo(id.value()); + } + + template + std::optional FindType(const std::optional>& path, + const std::string& type) { + std::optional id = FindTypeId(path, type); + if (!id.has_value()) { + return std::nullopt; + } + return global_info_.GetTypeInfo(id.value()); + } + + std::optional FindAnyLocalType(const std::string& type) { + std::optional id = FindLocalTypeId(type); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetAnyTypeInfo(id.value()); + } + + template + std::optional FindLocalType(const std::string& type) { + std::optional id = FindLocalTypeId(type); + if (!id.has_value()) { + return std::nullopt; + } + return global_info_.GetTypeInfo(id.value()); + } + + std::optional FindAbstractType(const std::string& abstract_type) { + std::optional id = FindAbstractTypeId(abstract_type); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetAbstractTypeInfo(id.value()); + } + + std::optional FindTypeclass(const std::string& typeclass) { + std::optional id = FindTypeclassId(typeclass); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetTypeclassInfo(id.value()); + } + + std::optional FindConstructor(const std::optional>& path, + const std::string& constructor) { + std::optional id = FindConstructorId(path, constructor); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetConstructorInfo(id.value()); + } + + NamespaceVisitor CreateVisitor() { + return global_info_.CreateVisitor(); + } + + GlobalInfo* GetGlobalInfo() { + return &global_info_; + } + + TypeclassGraph* GetTypeclassGraph() { + return global_info_.GetTypeclassGraph(); + } + + const std::vector& GetCurrentPath() { + return current_path_; + } + + const std::vector& GetCurrentPathNamespaces() { + return namespace_stack_; + } + + // use only after LinkSymbolsVisitor + std::vector> GetCurrentPathTypes() { + std::vector> types; + + types.reserve(namespace_stack_.size()); + for (auto& namespace_id : namespace_stack_) { + definition::Namespace& namespace_info = global_info_.GetNamespaceInfo(namespace_id); + if (namespace_info.any_node.has_value() && namespace_info.any_node.value()->link_type_id_.has_value()) { + types.push_back(namespace_info.any_node.value()->link_type_id_.value()); + } else { + types.push_back(std::nullopt); + } + } + + return types; + } + + utils::IdType GetCurrentNamespaceId() { + return namespace_stack_.back(); + } + + definition::Namespace* GetCurrentNamespace() { + return &global_info_.namespaces_[GetCurrentNamespaceId()]; + } + + std::optional GetCurrentNamespaceTypeId() { + if (!GetCurrentNamespace()->any_node.has_value()) { + return std::nullopt; + } + return GetCurrentNamespace()->any_node.value()->link_type_id_; + } + + std::optional GetCurrentNamespaceAnyType() { + std::optional id = GetCurrentNamespaceTypeId(); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetAnyTypeInfo(id.value()); + } + + template + std::optional GetCurrentNamespaceType() { + std::optional id = GetCurrentNamespaceTypeId(); + if (!id.has_value()) { + return std::nullopt; + } + return global_info_.GetTypeInfo(id.value()); + } + + std::optional GetCurrentNamespaceTypeclassId() { + if (!GetCurrentNamespace()->any_node.has_value()) { + return std::nullopt; + } + return GetCurrentNamespace()->any_node.value()->link_typeclass_id_; + } + + std::optional GetCurrentNamespaceTypeclass() { + std::optional id = GetCurrentNamespaceTypeclassId(); + if (!id.has_value()) { + return std::nullopt; + } + return &global_info_.GetTypeclassInfo(id.value()); + } + + bool IsInGlobalNamespace() { + return namespace_stack_.size() == 1; + } + private: + NamespaceVisitor(GlobalInfo& global_info) : global_info_(global_info), + namespace_stack_ {global_info.GlobalNamespaceId} {} + + template + std::optional FindSomething( + const std::optional>& path, + std::function(utils::IdType)> search_func); + + std::optional FindNamespaceIn( + utils::IdType current_namespace, + const std::vector& path); + private: + GlobalInfo& global_info_; + + std::vector namespace_stack_; + std::vector current_path_; + }; + + NamespaceVisitor CreateVisitor() { + return NamespaceVisitor(*this); + } + + definition::Function& GetFunctionInfo(utils::IdType id) { + return functions_.at(id); + } + + definition::Type& GetAnyTypeInfo(utils::IdType id) { + return types_.at(id); + } + + template + std::optional GetTypeInfo(utils::IdType id) { + if (!std::holds_alternative(types_.at(id).type)) { + return std::nullopt; + } + return &std::get(types_[id].type); + } + + definition::AbstractType& GetAbstractTypeInfo(utils::IdType id) { + return abstract_types_.at(id); + } + + definition::Typeclass& GetTypeclassInfo(utils::IdType id) { + return typeclasses_.at(id); + } + + definition::Constructor& GetConstructorInfo(utils::IdType id) { + return constructors_.at(id); + } + + definition::Namespace& GetNamespaceInfo(utils::IdType id) { + return namespaces_.at(id); + } + + PartitionInfo& GetPartitionInfo(utils::IdType id) { + return partitions_.at(id); + } + + std::optional FindPartition(const std::vector& path) { + auto trie_ans = partitions_trie_.Find(path); + return trie_ans.has_value() ? std::optional(*trie_ans.value()) : std::nullopt; + } + + std::vector FindPartitionsByPrefix(const std::vector& path) { // optimize ?? + auto trie_ans = partitions_trie_.FindByPrefix(path); + + std::vector ans(trie_ans.size()); + + for (size_t i = 0; i < ans.size(); ++i) { + ans[i] = *trie_ans[i]; + } + + return ans; + } + + TypeclassGraph* GetTypeclassGraph() { + return &typeclass_graph_; + } + + std::optional GetTypeNamespace(utils::IdType id, + utils::ClassInternalsModifier modifier); + + std::unordered_map* ChooseNamespaces( + utils::ClassInternalsModifier modifier, + definition::Namespace* current_namespace); + + std::optional AddTypeclassToGraph(utils::IdType typeclass); + + // function declarations & definitions should be added latter + std::optional AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node); + +private: + void CollectFunctionInfo( + utils::IdType current_namespace, + utils::ClassInternalsModifier modifier, + std::vector>>& function_declarations, + std::vector>& function_definitions); + +private: + const utils::IdType GlobalNamespaceId = 0; + + std::vector functions_; + std::vector types_; + std::vector abstract_types_; + std::vector typeclasses_; + std::vector constructors_; + + std::vector namespaces_; + + std::unordered_map name_to_typeclass_; + std::unordered_map name_to_abstract_type_; + + std::vector partitions_; + utils::Trie partitions_trie_; + + std::vector imports_; + std::unordered_map usages_; + + TypeclassGraph typeclass_graph_; +}; + +} // namespace info diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp new file mode 100644 index 0000000..62918d8 --- /dev/null +++ b/include/interpreter_tree.hpp @@ -0,0 +1,717 @@ +#pragma once + +#include +#include +#include +#include +#include + +// for clangd +#include "utils.hpp" + +namespace interpreter::tokens { + +struct BaseNode { + std::pair start_position; + std::pair end_position; + + std::optional type_; +}; + +// ----------------- Declarations ----------------- + +using AnyIdentifier = std::string; +using NameOrOperatorIdentifier = std::string; +using NameIdentifier = std::string; +using AnyTypeIdentifier = std::string; +using TypeIdentifier = std::string; +using AbstractTypeIdentifier = std::string; +using OperatorIdentifier = std::string; +using TypeclassIdentifier = std::string; + +// Sources ----------------- + +struct SourceFile; + +// Namespaces, partitions ----------------- + +struct Namespace; +struct NamespaceSources; + +// Definitions ----------------- + +struct ImportStatement; +struct AliasDefinitionStatement; +struct VariableDefinitionStatement; +struct FunctionDeclaration; +struct FunctionDefinitionStatement; +struct TypeDefinitionStatement; +struct AbstractTypeDefinitionStatement; +struct TypeclassDefinitionStatement; +struct PartitionStatement; + +// +using NamespaceStatement = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; +// +using SourceStatement = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; +// + +// Definition parts + +using ImportSymbol = AnyIdentifier; // can be extended name + +struct FunctionDefinition; +struct TypeDefinition; +struct AnyAnnotatedType; + +// TypeIdentifier <-> AbstractTypeIdentifier <-> std::string +using AnnotatedType = AnyAnnotatedType; + +using AnnotatedAbstractType = AnyAnnotatedType; + +// Flow control ----------------- + +struct TypeConstructorPatternParameter; +struct TypeConstructorPattern; + +struct Match; +struct Condition; +struct DoWhileLoop; +struct WhileLoop; +struct ForLoop; +struct LoopLoop; + +using FlowControl = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; + +// Statements, expressions, blocks, etc. ----------------- + +struct Block; + +struct FloatNumberLiteral; +struct NumberLiteral; +struct StringLiteral; +struct CharLiteral; +struct UnitLiteral; +struct BoolLiteral; + +using Literal = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; + +// +struct NameExpression; +struct ScopedStatement; +struct AccessExpression; +struct ReferenceExpression; +using SubExpressionToken = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; +// +struct FunctionCallExpression; +struct ArrayExpression; +using SubExpression = std::variant< // BiaryOperatorExpression is FunctionCallExpression + std::unique_ptr, + std::unique_ptr>; +// +enum class LoopControlExpression { + Break, + Continue, +}; +// +struct ReturnExpression; +using PrefixedExpression = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; +// +struct LambdaFunction; +struct TypeConstructor; +using Expression = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; +// +struct TupleExpression; +struct VariantExpression; +using SuperExpression = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; +// + +struct ScopedStatement; + +// Operators + +struct ReferenceExpression; + +// Other expressions + +struct FunctionCallExpression; + +struct TupleExpression; +struct VariantExpression; +struct ReturnExpression; +struct TypeConstructorParameter; +struct TypeConstructor; +struct LambdaFunction; +struct ArrayExpression; + +// Name + +struct PartitionName { + BaseNode base; + + std::vector path; // name is last element of path +}; + +struct NameExpression; +struct TupleName; +struct VariantName; +struct AnnotatedName; + +// // ScopedAnyName <-> AnyName +using AnyName = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; + +using ScopedAnyName = AnyName; + +// Type, typeclass, etc. ----------------- + +// Type + +struct FunctionType; +struct TupleType; +struct VariantType; +struct TypeExpression; +struct TypeExpression; + +using Constructor = std::string; + +// // ScopedAnyType <-> AnyType +using AnyType = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; + +using ScopedAnyType = AnyType; + +struct ExtendedScopedAnyType; + +// Typeclass + +struct ParametrizedTypeclass; + +// TypeclassSubExpression -> ParametrizedTypeclass + +// Typeclass & Type + +struct ParametrizedType; + +// Identifiers, constants, etc. ----------------- + +using Pattern = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; + + +using ScopedPattern = Pattern; + +//////////////////////////////////////////////////////////////////////////////////////////// + +// ----------------- Sources ----------------- + +struct SourceFile { + BaseNode base; + + std::vector statements; +}; + +// ----------------- Namespaces, partittions ----------------- + +struct NamespaceSources { + BaseNode base; + + std::vector statements; +}; + +struct Namespace { + BaseNode base; + + utils::ClassInternalsModifier modifier; + TypeIdentifier type; + NamespaceSources scope; + + std::optional link_type_id_; + std::optional link_typeclass_id_; +}; + +// ----------------- Definitions ----------------- + +struct ImportStatement { + BaseNode base; + + std::optional name; + std::string module_name; + std::vector symbols; +}; + +struct AliasDefinitionStatement { + BaseNode base; + + utils::AliasModifier modifier; + TypeIdentifier type; + std::vector parameters; + std::unique_ptr value; + + utils::IdType type_id_ = 0; +}; + +struct VariableDefinitionStatement { + BaseNode base; + + utils::IsConstModifier modifier; + utils::AssignmentModifier assignment_modifier; + AnyName name; + SuperExpression value; +}; + +struct FunctionDeclaration { + BaseNode base; + + bool is_in_interface = false; + NameOrOperatorIdentifier name; + std::vector> parameters; + std::unique_ptr type; + + utils::IdType function_id_ = 0; +}; + +struct FunctionDefinitionStatement { + BaseNode base; + + std::unique_ptr definition; + SuperExpression value; + + utils::IdType function_id_ = 0; +}; + +struct TypeDefinitionStatement { + BaseNode base; + + bool is_in_interface = false; + utils::ClassModifier modifier; + std::unique_ptr definition; + AnyType value; + + utils::IdType type_id_ = 0; +}; + +struct AbstractTypeDefinitionStatement { + BaseNode base; + + utils::AbstractTypeModifier modifier; + std::unique_ptr type; + + utils::IdType type_id_ = 0; +}; + +struct TypeclassDefinitionStatement { + BaseNode base; + + std::unique_ptr definition; + std::vector>> requirements; + + utils::IdType typeclass_id_ = 0; +}; + +struct PartitionStatement { + BaseNode base; + + utils::PartitionModifier modifier; + PartitionName name; + SuperExpression value; + + utils::IdType executable_id_ = 0; +}; + +// Definition parts ----------------- + +struct FunctionDefinition { + BaseNode base; + + NameOrOperatorIdentifier name; + std::vector arguments; +}; + +struct TypeDefinition { + BaseNode base; + + std::unique_ptr type; + std::vector> parameters; +}; + +struct AnyAnnotatedType { + BaseNode base; + + AnyTypeIdentifier type; + std::vector> typeclasses; + + utils::IdType graph_id_ = 0; // for types +}; + +// ----------------- Flow control ----------------- + +struct TypeConstructorPatternParameter { + BaseNode base; + + std::optional name; + ScopedPattern value; +}; + +struct TypeConstructorPattern { + BaseNode base; + + std::unique_ptr constructor; + std::vector parameters; +}; + +struct MatchCase { + BaseNode base; + + Pattern value; + std::optional condition; + std::optional statement; +}; + +struct Match { + BaseNode base; + + Expression value; + std::vector matches; + + bool is_consuming_value = false; +}; + +struct Condition { + BaseNode base; + + std::vector conditions; // if, elif + std::vector statements; // if, elif, else +}; + +struct DoWhileLoop { + BaseNode base; + + Expression condition; + Expression statement; +}; + +struct WhileLoop { + BaseNode base; + + Expression condition; + Expression statement; +}; + +struct ForLoop { + BaseNode base; + + utils::IsConstModifier variable_modifier; + AnyName variable; + Expression interval; + Expression statement; +}; + +struct LoopLoop { + BaseNode base; + + Expression statement; +}; + +// ----------------- Statements, expressions, blocks, etc. ----------------- + +using BlockStatement = std::variant< + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr>; + +struct Block { + BaseNode base; + + std::vector statements; +}; + +struct ScopedStatement { + BaseNode base; + + SuperExpression statement; +}; + +// Operators ----------------- + +// struct BinaryOperatorExpression { +// BaseNode base; +// +// OperatorIdentifier operator_name; +// SubExpression left_expression; +// SubExpression right_expression; +// size_t precedence = utils::MaxOperatorPrecedence; +// +// utils::IdType function_id_; +// bool is_method_ = false; +// }; + +struct ReferenceExpression { + BaseNode base; + + utils::ReferenceModifier reference; + std::unique_ptr expression; +}; + +struct AccessExpression { + BaseNode base; + + std::unique_ptr name; + SubExpressionToken id; + + bool is_string_access_ = false; +}; + +// Other Expressions ----------------- + +struct FunctionCallExpression { + BaseNode base; + + std::optional, + std::unique_ptr>> prefix; + NameOrOperatorIdentifier name; + std::vector> parameters; + std::vector arguments; + + std::optional precedence; // for operators + bool is_binary_operator_expression = false; // for operators + + // only one from two is present + std::optional function_id_; + std::optional graph_id_; // for type or typeclass + + std::optional abstract_type_name_; // for typeclasses + + bool is_method_of_first_argument_ = false; +}; + +struct TupleExpression { + BaseNode base; + + std::vector expressions; +}; + +struct VariantExpression { + BaseNode base; + + std::vector expressions; +}; + +struct ReturnExpression { + BaseNode base; + + Expression expression; + + bool is_from_definition = false; // from definition or from current block +}; + +struct TypeConstructorParameter { + BaseNode base; + + std::optional name; + std::optional asignment_modifier; + SubExpression value; +}; + +struct TypeConstructor { + BaseNode base; + + std::unique_ptr constructor; + std::vector parameters; + + bool is_allocated_on_heap = false; +}; + +struct LambdaFunction { + BaseNode base; + + std::vector> parameters; + std::vector arguments; + Expression expression; + + std::vector argument_graph_ids_; + utils::IdType return_type_graph_id_ = 0; +}; + +struct ArrayExpression { + BaseNode base; + + std::vector elements; +}; + +// Name ----------------- + +struct NameExpression { + BaseNode base; + + std::vector names; +}; + +struct TupleName { + BaseNode base; + + std::vector names; +}; + +struct VariantName { + BaseNode base; + + std::vector names; +}; + +struct AnnotatedName { + BaseNode base; + + NameIdentifier name; + std::optional type; +}; + +// ----------------- Type, typeclass, etc. ----------------- + +// Type ----------------- + +struct FunctionType { + BaseNode base; + + std::vector types; +}; + +struct TupleType { + BaseNode base; + + std::optional type; + std::vector, std::unique_ptr>> entities; +}; + +struct VariantType { + BaseNode base; + + std::optional type; + std::vector>> constructors; +}; + +struct ParametrizedType { + BaseNode base; + + AnyTypeIdentifier type; + std::vector> parameters; + + std::optional type_id_; // std::nullopt, if it is namespace without type +}; + +struct TypeExpression { + BaseNode base; + + std::vector path; + ParametrizedType type; + + std::optional array_size; // if array; 0 - dynamic size + + std::optional type_id_; + std::optional constructor_id_; +}; + +struct ExtendedScopedAnyType { + BaseNode base; + + std::vector references; + AnyType type; +}; + +// Typeclass ----------------- + +struct ParametrizedTypeclass { + BaseNode base; + + TypeclassIdentifier typeclass; + std::vector> parameters; + + utils::IdType typeclass_id_ = 0; +}; + +// ----------------- Comments [IGNORE] ----------------- +// ----------------- Identifiers, constants, etc. ----------------- + +struct FloatNumberLiteral { + BaseNode base; + + double value; +}; + +struct NumberLiteral { + BaseNode base; + + int64_t value; +}; + +struct StringLiteral { + BaseNode base; + + std::string value; +}; + +struct CharLiteral { + BaseNode base; + + char value; +}; + +struct UnitLiteral { + BaseNode base; +}; + +struct BoolLiteral { + BaseNode base; + + bool value; +}; + +} // namespace interpereter::tokens diff --git a/include/link_symbols_visitor.hpp b/include/link_symbols_visitor.hpp new file mode 100644 index 0000000..f02e9cd --- /dev/null +++ b/include/link_symbols_visitor.hpp @@ -0,0 +1,142 @@ +#pragma once + +#include + +// for clangd +#include "definitions.hpp" +#include "error_handling.hpp" +#include "typeclass_graph.hpp" +#include "utils.hpp" +#include "visitor.hpp" +#include "global_info.hpp" + +namespace interpreter { + +// TODO, (maybe add VisitSourceFile?) +class LinkSymbolsVisitor : public Visitor { +public: + explicit LinkSymbolsVisitor(info::GlobalInfo& global_info) + : namespace_visitor_(global_info.CreateVisitor()), + global_info_(global_info), + typeclass_graph_(*global_info.GetTypeclassGraph()) {} + + void VisitSourceFile(SourceFile* source_file) override { + Visitor::Visit(source_file); + namespace_visitor_.GetTypeclassGraph()->CalculateGraph(); + } + +private: + // Sources ----------------- + + // // void Visit(SourceFile* node) override; + + // Namespaces, partitions ----------------- + + // // void Visit(NamespaceSources* node) override; + void Visit(Namespace* node) override; + + // Definitions ----------------- + + // // void Visit(ImportStatement* node) override; + // // void Visit(AliasDefinitionStatement* node) override; + // // void Visit(VariableDefinitionStatement* node) override; + // // void Visit(FunctionDeclaration* node) override; + // // void Visit(FunctionDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; + // // void Visit(AbstractTypeDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; + // // void Visit(PartitionStatement* node) override; + + // Definition parts + + // // void Visit(FunctionDefinition* node) override; + // // void Visit(TypeDefinition* node) override; + // // void Visit(AnyAnnotatedType* node) override; + + // Flow control ----------------- + + // // void Visit(TypeConstructorPatternParameter* node) override; + // // void Visit(TypeConstructorPattern* 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; + + // Operators + + // // void Visit(ReferenceExpression* node) override; + // // void Visit(AccessExpression* node) override; + + // Simple Expressions + + // // void Visit(FunctionCallExpression* node) override; + + // // void Visit(TupleExpression* node) override; + // // void Visit(VariantExpression* node) override; + // // void Visit(ReturnExpression* node) override; + // // void Visit(TypeConstructorParameter* node) override; + // // void Visit(TypeConstructor* node) override; + // // void Visit(LambdaFunction* node) override; + // // void Visit(ArrayExpression* node) override; + + // // void Visit(LoopControlExpression& node) override; // enum + + // Name + + // // void Visit(PartitionName* 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(TypeExpression* node) override; + + // // void Visit(ExtendedScopedAnyType* node) override; + + // Typeclass + + void Visit(ParametrizedTypeclass* node) override; + + // Typeclass & Type + + // // void Visit(ParametrizedType* node) override; + + // Identifiers, constants, etc. ----------------- + + // // void Visit(std::string* node) override; // std::string + + // // void Visit(FloatNumberLiteral* node) override; + // // void Visit(NumberLiteral* node) override; + // // void Visit(StringLiteral* node) override; + // // void Visit(CharLiteral* node) override; + // // void Visit(BoolLiteral* node) override; + + // + + void AddTypeFunctionsToTypeclassGraph(utils::IdType type_id, + utils::IdType graph_id, + utils::ClassInternalsModifier namespace_modifier, + const BaseNode& base_node); + +private: + info::GlobalInfo::NamespaceVisitor namespace_visitor_; + info::GlobalInfo& global_info_; + info::TypeclassGraph& typeclass_graph_; +}; + +} // namespace interpreter diff --git a/include/node.hpp b/include/node.hpp new file mode 100644 index 0000000..0540dd8 --- /dev/null +++ b/include/node.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +// for clangd +#include "parse_tree.hpp" + +namespace info { + class GlobalInfo; + class Context; +} // namespace info + +namespace interpreter { +class Visitor; + +struct Node { +//public: + //Node(info::GlobalInfo& global_info) : global_info_(global_info) {} + + // ?? not needed ?? virtual void Accept(Visitor* visitor); + + /* ------------ use visitor instead ------------ + virtual void build(parser::ParseTree::Cursor& cursor) = 0; // build tree from parse tree + + virtual void find_symbols() = 0; // find types, typeclasses, namespaces, .. + virtual void assign_types() = 0; // typecheck + virtual void execute(info::Context& context) = 0; // execute part of tree + */ +/*private: + size_t start_position_; // ?? + size_t end_position_; // ?? + Node* parent_; // ?? + info::GlobalInfo& global_info_;*/ +}; + +} // namespace interpreter diff --git a/include/parse_token_types.hpp b/include/parse_token_types.hpp new file mode 100644 index 0000000..540118d --- /dev/null +++ b/include/parse_token_types.hpp @@ -0,0 +1,132 @@ +#pragma once + +#include + +namespace parser::tokens { + +// Sources ----------------- + +const std::string SourceFile = "source_file"; +const std::string SourceStatement = "source_statement"; +const std::string NamespaceSources = "namespace_sources"; +const std::string NamespaceStatement = "namespace_statement"; + +// Namespaces, partitions ----------------- + +const std::string Namespace = "namespace"; + +// Definitions ----------------- + +const std::string ImportStatement = "import_statement"; +const std::string AliasDefinitionStatement = "alias_definition_statement"; +const std::string VariableDefinitionStatement = "variable_definition_statement"; +const std::string FunctionDeclaration = "function_declaration"; +const std::string FunctionDefinitionStatement = "function_definition_statement"; +const std::string TypeDefinitionStatement = "type_definition_statement"; +const std::string AbstractTypeDefinitionStatement = "abstract_type_definition_statement"; +const std::string TypeclassDefinitionStatement = "typeclass_definition_statement"; +const std::string PartitionStatement = "partition_statement"; + +// Definition parts + +const std::string ImportSymbol = "import_symbol"; +const std::string FunctionDefinition = "function_definition"; +const std::string TypeDefinition = "type_definition"; +const std::string AnnotatedAbstractType = "annotated_abstract_type"; +const std::string AnnotatedType = "annotated_type"; + +// Flow control ----------------- + +const std::string TypeConstructorPatternParameter = "type_constructor_pattern_parameter"; +const std::string TypeConstructorPattern = "type_constructor_pattern"; +const std::string ScopedPattern = "scoped_pattern"; +const std::string Pattern = "pattern"; +const std::string MatchCase = "match_case"; +const std::string Match = "match"; +const std::string Condition = "condition"; +const std::string DoWhileLoop = "do_while_loop"; +const std::string WhileLoop = "while_loop"; +const std::string ForLoop = "for_loop"; +const std::string LoopLoop = "loop_loop"; +const std::string FlowControl = "flow_control"; + +// Statements, expressions, blocks, etc. ----------------- + +const std::string BlockStatement = "block_statement"; +const std::string Block = "block"; +const std::string SubExpressionToken = "subexpression_token"; +const std::string SubExpression = "subexpression"; +const std::string PrefixedExpression = "prefixed_expression"; +const std::string Expression = "expression"; +const std::string SuperExpression = "superexpression"; +const std::string ScopedStatement = "scoped_statement"; + +// Operators + +const std::string BinaryOperatorExpression = "binary_operator_expression"; +const std::string ReferenceExpression = "reference_expression"; +const std::string AccessExpression = "access_expression"; + +// Other expressions + +const std::string FunctionArgument = "function_argument"; +const std::string FunctionCallExpression = "function_call_expression"; +const std::string TupleExpression = "tuple_expression"; +const std::string VariantExpression = "variant_expression"; +const std::string ReturnExpression = "return_expression"; +const std::string TypeConstructorParameter = "type_constructor_parameter"; +const std::string TypeConstructor = "type_constructor"; +const std::string LambdaFunction = "lambda_function"; +const std::string ArrayExpression = "array_expression"; +const std::string LoopControlExpression = "loop_control_expression"; + +// Name + +const std::string PartitionName = "partition_name"; +const std::string NameExpression = "name_expression"; +const std::string TupleName = "tuple_name"; +const std::string VariantName = "variant_name"; +const std::string AnnotatedName = "annotated_name"; +const std::string AnyName = "any_name"; +const std::string ScopedAnyName = "scoped_any_name"; + +// Type, typeclass, etc. ----------------- + +// Type + +const std::string FunctionType = "function_type"; +const std::string TupleType = "tuple_type"; +const std::string VariantType = "variant_type"; +const std::string TypeExpression = "type_expression"; +const std::string Constructor = "constructor"; +const std::string AnyType = "any_type"; +const std::string ScopedAnyType = "scoped_any_type"; +const std::string ExtendedScopedAnyType = "extended_scoped_any_type"; + +// Typeclass + +const std::string ParametrizedTypeclass = "parametrized_typeclass"; + + +// Typeclass & Type + +const std::string ParametrizedType = "parametrized_type"; + +// Identifiers, constants, etc. ----------------- + +const std::string TypeclassIdentifier = "typeclass_identifier"; +const std::string NameIdentifier = "name_identifier"; +const std::string TypeIdentifier = "type_identifier"; +const std::string AbstractTypeIdentifier = "abstract_type_identifier"; +const std::string OperatorIdentifier = "operator"; + +const std::string FloatNumberLiteral = "float_number_literal"; +const std::string NumberLiteral = "number_literal"; +const std::string StringLiteral = "string_literal"; +const std::string CharLiteral = "char_literal"; +const std::string UnitLiteral = "unit_literal"; +const std::string BoolLiteral = "bool_literal"; + +const std::string Literal = "literal"; + +} // namespace parser::tokens diff --git a/include/parse_tree.hpp b/include/parse_tree.hpp new file mode 100644 index 0000000..f8b6a0d --- /dev/null +++ b/include/parse_tree.hpp @@ -0,0 +1,142 @@ +#pragma once + +#include + +// for clangd +#include "tree_sitter/api.h" + +extern "C" const TSLanguage* tree_sitter_LANG(); + +namespace parser { + +class ParseTree { +public: + class Node { + public: + Node() : uninitialized_(true) { + for (unsigned int& i : node_.context) { + i = 0; + } + node_.id = nullptr; + node_.tree = nullptr; + + source_ = nullptr; + }; + Node(const TSNode& node, const std::string* source) : uninitialized_(false), node_(node), source_(source) {} + + std::string GetType() { + return ts_node_type(node_); + } + + std::pair GetStartPoint() { + TSPoint point = ts_node_start_point(node_); + return {point.row, point.column}; + } + + std::pair GetEndPoint() { + TSPoint point = ts_node_end_point(node_); + return {point.row, point.column}; + } + + std::string GetAsSExpression() { + return ts_node_string(node_); + } + + std::string GetValue() { // from source + size_t start = ts_node_start_byte(node_); + size_t end = ts_node_end_byte(node_); + return source_->substr(start, end - start); + } + + bool IsNull() { + return ts_node_is_null(node_); + } + + bool IsNamed() { + return ts_node_is_named(node_); + } + + bool IsMissing() { + return ts_node_is_missing(node_); + } + + bool IsExtra() { // comments, etc. + return ts_node_is_extra(node_); + } + + bool HasError() { + return ts_node_has_error(node_); + } + + Node NthChild(size_t n) { + return Node(ts_node_child(node_, n), source_); + } + + size_t ChildCount() { + return ts_node_child_count(node_); + } + + Node NthNamedChild(size_t n) { + return Node(ts_node_named_child(node_, n), source_); + } + size_t NamedChildCount() { + return ts_node_named_child_count(node_); + } + + Node ChildByFieldName(const std::string& name) { + return Node(ts_node_child_by_field_name(node_, name.c_str(), name.size()), source_); + } + + Node PreviousSibling() { + return Node(ts_node_prev_sibling(node_), source_); + } + + Node PreviousNamedSibling() { + return Node(ts_node_prev_named_sibling(node_), source_); + } + + Node NextSibling() { + return Node(ts_node_next_sibling(node_), source_); + } + + Node NextNamedSibling() { + return Node(ts_node_next_named_sibling(node_), source_); + } + private: + bool uninitialized_; + TSNode node_; + const std::string* source_; + }; + + ParseTree(const std::string& source) : source_(source) { + TSParser* parser = ts_parser_new(); + ts_parser_set_language(parser, tree_sitter_LANG()); + + tree_ = ts_parser_parse_string( + parser, + nullptr, + source_.c_str(), + source_.size()); + + ts_parser_delete(parser); + } + + ParseTree(const ParseTree& parse_tree) : tree_(ts_tree_copy(parse_tree.tree_)), source_(parse_tree.source_) {} + + Node GetRoot() const { + return Node(ts_tree_root_node(tree_), &source_); + } + + ~ParseTree() { + ts_tree_delete(tree_); + } + + bool IsProperlyParsed() { // TODO: check + return !GetRoot().HasError(); + } +private: + TSTree* tree_; + std::string source_; // for token value extraction +}; + +} // namespace parser diff --git a/include/print_visitor.hpp b/include/print_visitor.hpp new file mode 100644 index 0000000..c13aac1 --- /dev/null +++ b/include/print_visitor.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include + +// for clangd +#include "interpreter_tree.hpp" +#include "visitor.hpp" + +namespace interpreter { + +class PrintVisitor : public Visitor { +public: + explicit PrintVisitor(std::ostream& out) : out_(out) {} + +private: + // Sources ----------------- + + void Visit(SourceFile* node) override; + + // Namespaces, partitions ----------------- + + void Visit(NamespaceSources* node) override; + void Visit(Namespace* node) override; + + // Definitions ----------------- + + void Visit(ImportStatement* node) override; + void Visit(AliasDefinitionStatement* node) override; + void Visit(VariableDefinitionStatement* node) override; + void Visit(FunctionDeclaration* node) override; + void Visit(FunctionDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; + void Visit(AbstractTypeDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; + void Visit(PartitionStatement* node) override; + + + // Definition parts + + void Visit(FunctionDefinition* node) override; + void Visit(TypeDefinition* node) override; + void Visit(AnyAnnotatedType* node) override; + + // Flow control ----------------- + + void Visit(TypeConstructorPatternParameter* node) override; + void Visit(TypeConstructorPattern* 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; + + // Operators + + void Visit(ReferenceExpression* node) override; + void Visit(AccessExpression* node) override; + + // Simple Expressions + + void Visit(FunctionCallExpression* node) override; + + void Visit(TupleExpression* node) override; + void Visit(VariantExpression* node) override; + void Visit(ReturnExpression* node) override; + void Visit(TypeConstructorParameter* node) override; + void Visit(TypeConstructor* node) override; + void Visit(LambdaFunction* node) override; + void Visit(ArrayExpression* node) override; + + void Visit(LoopControlExpression& node) override; // enum + + // Name + + void Visit(PartitionName* 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(TypeExpression* node) override; + + void Visit(ExtendedScopedAnyType* node) override; + + // Typeclass + + void Visit(ParametrizedTypeclass* node) override; + + // Typeclass & Type + + void Visit(ParametrizedType* node) override; + + // Identifiers, constants, etc. ----------------- + + void Visit(std::string* node) override; // std::string + + void Visit(FloatNumberLiteral* node) override; + void Visit(NumberLiteral* node) override; + void Visit(StringLiteral* node) override; + void Visit(CharLiteral* node) override; + void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; + +private: + std::ostream& out_; +}; + +} // namespace interpreter diff --git a/include/type_check_visitor.hpp b/include/type_check_visitor.hpp new file mode 100644 index 0000000..f77f197 --- /dev/null +++ b/include/type_check_visitor.hpp @@ -0,0 +1,246 @@ +#pragma once + +// for clangd +#include "interpreter_tree.hpp" +#include "typeclass_graph.hpp" +#include "types.hpp" +#include "contexts.hpp" +#include "utils.hpp" +#include "visitor.hpp" +#include "global_info.hpp" +#include + +// TODO: class fields and constructors can't be accessed not from associated namespace + +namespace interpreter { + +class TypeCheckVisitor : public Visitor { +public: + explicit TypeCheckVisitor(info::GlobalInfo& global_info, + info::ContextManager& context_manager) + : namespace_visitor_(global_info.CreateVisitor()), + global_info_(global_info), + typeclass_graph_(*global_info.GetTypeclassGraph()), + context_manager_(context_manager) {} + + void VisitSourceFile(SourceFile* source_file) override { + // init internal type abstrac types + for (size_t i = 0; i < info::type::InternalTypesCount; ++i) { + info::type::InternalType type = static_cast(i); + Visit(namespace_visitor_.FindAbstractType(info::type::ToString(type)).value()->node); + } + + Visit(source_file); + } + +private: + // Sources ----------------- + + void Visit(SourceFile* node) override; + + // Namespaces, partitions ----------------- + + void Visit(NamespaceSources* node) override; + void Visit(Namespace* node) override; + + // Definitions ----------------- + + void Visit(ImportStatement* node) override; + void Visit(AliasDefinitionStatement* node) override; + void Visit(VariableDefinitionStatement* node) override; + void Visit(FunctionDeclaration* node) override; + void Visit(FunctionDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; + void Visit(AbstractTypeDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; + void Visit(PartitionStatement* node) override; + + // Definition parts + + void Visit(FunctionDefinition* node) override; + void Visit(TypeDefinition* node) override; + void Visit(AnyAnnotatedType* node) override; + + // Flow control ----------------- + + void Visit(TypeConstructorPatternParameter* node) override; + void Visit(TypeConstructorPattern* 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; + + // Operators + + void Visit(ReferenceExpression* node) override; + void Visit(AccessExpression* node) override; + + // Simple Expressions + + void Visit(FunctionCallExpression* node) override; + + void Visit(TupleExpression* node) override; + void Visit(VariantExpression* node) override; + void Visit(ReturnExpression* node) override; + void Visit(TypeConstructorParameter* node) override; + void Visit(TypeConstructor* node) override; + void Visit(LambdaFunction* node) override; + void Visit(ArrayExpression* node) override; + + void Visit(LoopControlExpression& node) override; // enum + + // Name + + void Visit(PartitionName* 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(TypeExpression* node) override; + + void Visit(ExtendedScopedAnyType* node) override; + + // Typeclass + + void Visit(ParametrizedTypeclass* node) override; + + // Typeclass & Type + + void Visit(ParametrizedType* node) override; + + // Identifiers, constants, etc. ----------------- + + // // void Visit(std::string* node) override; // std::string + + void Visit(FloatNumberLiteral* node) override; + void Visit(NumberLiteral* node) override; + void Visit(StringLiteral* node) override; + void Visit(CharLiteral* node) override; + void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; + + // + + void CollectTypeContext(const ParametrizedType& type, + std::unordered_map& context); + + void CollectTypeExpressionContext(const TypeExpression& type_expression, + std::unordered_map& context); + + utils::IdType TypeInContext(utils::IdType type, + const std::unordered_map& context); + + void CheckPattern(Pattern& node, const BaseNode& base_node); + + + std::optional + FindExpressionMethodAndUpdate(FunctionCallExpression* node, + utils::IdType expression_type); + + std::optional + FindTypeFunctionAndUpdate(FunctionCallExpression* node, + TypeExpression* type_node, + std::unordered_map& context); + + std::optional FindFunctionAndUpdate(FunctionCallExpression* node); + + std::optional + FindAbstractTypeTypeclassFunctionAndUpdate( + FunctionCallExpression* node, + info::type::AbstractType* abstract_type, + bool is_method); + + std::optional + FindDefinedTypeFunctionAndUpdate( + FunctionCallExpression* node, + info::definition::AnyType* defined_type, + utils::IdType type, + bool is_method); + + void ResetReturnedAndBroughtTypes() { + if (returned_type_.has_value()) { + all_branches_returned_value_ = false; + } + if (brought_type_.has_value()) { + all_branches_brought_value_ = false; + } + } + + void AddGraphIdLocalTypes(utils::IdType graph_id, utils::IdType type) { + std::unordered_set requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id); + requirement_graph_ids.insert(graph_id); + + for (auto& requirement_graph_id : requirement_graph_ids) { + context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, type); + } + } + + utils::IdType AddGraphIdLocalAbstractTypes(utils::IdType graph_id) { + std::unordered_set requirement_graph_ids = typeclass_graph_.GetDependenciesSet(graph_id); + requirement_graph_ids.insert(graph_id); + + utils::IdType abstract_type = context_manager_.AddValue( + info::type::AbstractType(utils::AbstractTypeModifier::Abstract, + graph_id, + typeclass_graph_), + utils::ValueType::Tmp); + + for (auto& requirement_graph_id : requirement_graph_ids) { + context_manager_.DefineLocalType(typeclass_graph_.GetVertex(requirement_graph_id).name, abstract_type); + } + + return abstract_type; + } + + void VisitDefinedType(info::definition::AnyType* defined_type, + const std::unordered_map& context) { + Visitor::Visit(defined_type->node->value); + current_type_ = TypeInContext(current_type_, context); + current_type_ = + context_manager_.AddValue(info::type::DefinedType(defined_type->node->type_id_, + current_type_, + defined_type->modifier, + context_manager_.GetValueManager()), + utils::ValueType::Tmp); + } + +private: + info::GlobalInfo::NamespaceVisitor namespace_visitor_; + info::GlobalInfo& global_info_; + info::TypeclassGraph& typeclass_graph_; + info::ContextManager& context_manager_; + + std::unordered_set type_namespaces_; + utils::IdType current_type_; + + std::optional returned_type_; + bool all_branches_returned_value_ = true; + + std::optional brought_type_; + bool all_branches_brought_value_ = true; + + std::unordered_map internal_to_abstract_type_; + + std::optional is_const_definition_; + + bool is_in_statement_ = false; +}; + +} // namespace interpreter diff --git a/include/typeclass_graph.hpp b/include/typeclass_graph.hpp new file mode 100644 index 0000000..ce5dc34 --- /dev/null +++ b/include/typeclass_graph.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include +#include +#include + +// for clangd +#include "utils.hpp" +#include "interpreter_tree.hpp" + +namespace info { + +// move constructor parameters ?? +class TypeclassGraph { +public: + enum class Modifier { + Typeclass = 0, + Type = 1, + }; + + struct FunctionInfo { + utils::ClassInternalsModifier modifier = utils::ClassInternalsModifier::Static; + interpreter::tokens::FunctionDeclaration* declaration = nullptr; + std::optional definition; + bool is_defined_in_owner = false; + }; + + struct Vertex { // make constructor ?? + std::string name; + std::unordered_map functions; + std::unordered_set dependencies; // TODO: parameters + interpreter::tokens::BaseNode* base_node; // for error handling + std::optional type_id; // for defined types + Modifier modifier; + }; + + utils::IdType AddVertex( + const std::string& name, + const std::vector& dependencies, + const std::vector>>& function_declarations, + const std::vector>& function_definitions, + interpreter::tokens::BaseNode* base_node, + Modifier modifier); + + std::optional FindFunctionTypeclass(const std::string& name); + + bool IsFunctionInVertex(const std::string& name, utils::IdType vertex_id) { + return verticles_[vertex_id].functions.count(name) != 0; + } + + // if vertex_id == std::nullopt, info can be not complete + std::optional GetFunctionInfo(const std::string& name, + std::optional vertex_id); + + const Vertex& GetVertex(utils::IdType id) { + return verticles_.at(id); + } + + std::optional GetTypeVertex(utils::IdType id) { + if (verticles_.at(id).modifier == Modifier::Type) { + return &verticles_[id]; + } + return std::nullopt; + } + + // cache ?? + std::unordered_set GetDependenciesSet(utils::IdType id); + std::vector GetDependenciesVector(utils::IdType id); + + const std::unordered_map& GetVertexFunctions(utils::IdType id) { + return verticles_.at(id).functions; + } + + bool IsCalculated() { + return is_calculated_; + } + + // can exit by typecheck error + void CalculateGraph(); + +private: + std::unordered_map method_to_vertex_; + std::unordered_map name_to_typeclass_; + std::vector verticles_; + + bool is_calculated_ = true; +}; + +} // namespace info diff --git a/include/typed_print_visitor.hpp b/include/typed_print_visitor.hpp new file mode 100644 index 0000000..faf7012 --- /dev/null +++ b/include/typed_print_visitor.hpp @@ -0,0 +1,126 @@ +#pragma once + +#include + +// for clangd +#include "visitor.hpp" +#include "types.hpp" +#include "contexts.hpp" + +namespace interpreter { + +class TypedPrintVisitor : public Visitor { +public: + explicit TypedPrintVisitor(std::ostream& out, + info::ContextManager& context_manager) + : out_(out), context_manager_(context_manager) {} + +private: + // Sources ----------------- + + void Visit(SourceFile* node) override; + + // Namespaces, partitions ----------------- + + void Visit(NamespaceSources* node) override; + void Visit(Namespace* node) override; + + // Definitions ----------------- + + void Visit(ImportStatement* node) override; + void Visit(AliasDefinitionStatement* node) override; + void Visit(VariableDefinitionStatement* node) override; + void Visit(FunctionDeclaration* node) override; + void Visit(FunctionDefinitionStatement* node) override; + void Visit(TypeDefinitionStatement* node) override; + void Visit(AbstractTypeDefinitionStatement* node) override; + void Visit(TypeclassDefinitionStatement* node) override; + void Visit(PartitionStatement* node) override; + + // Definition parts + + void Visit(FunctionDefinition* node) override; + void Visit(TypeDefinition* node) override; + void Visit(AnyAnnotatedType* node) override; + + // Flow control ----------------- + + void Visit(TypeConstructorPatternParameter* node) override; + void Visit(TypeConstructorPattern* 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; + + // Operators + + void Visit(ReferenceExpression* node) override; + void Visit(AccessExpression* node) override; + + // Simple Expressions + + void Visit(FunctionCallExpression* node) override; + + void Visit(TupleExpression* node) override; + void Visit(VariantExpression* node) override; + void Visit(ReturnExpression* node) override; + void Visit(TypeConstructorParameter* node) override; + void Visit(TypeConstructor* node) override; + void Visit(LambdaFunction* node) override; + void Visit(ArrayExpression* node) override; + + void Visit(LoopControlExpression& node) override; // enum + + // Name + + void Visit(PartitionName* 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(TypeExpression* node) override; + + void Visit(ExtendedScopedAnyType* node) override; + + // Typeclass + + void Visit(ParametrizedTypeclass* node) override; + + // Typeclass & Type + + void Visit(ParametrizedType* node) override; + + // Identifiers, constants, etc. ----------------- + + void Visit(std::string* node) override; // std::string + + void Visit(FloatNumberLiteral* node) override; + void Visit(NumberLiteral* node) override; + void Visit(StringLiteral* node) override; + void Visit(CharLiteral* node) override; + void Visit(UnitLiteral* node) override; + void Visit(BoolLiteral* node) override; + +private: + std::ostream& out_; + info::ContextManager& context_manager_; +}; + +} // namespace interpreter diff --git a/include/types.hpp b/include/types.hpp new file mode 100644 index 0000000..3756856 --- /dev/null +++ b/include/types.hpp @@ -0,0 +1,401 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +// for clangd +#include "error_handling.hpp" +#include "typeclass_graph.hpp" +#include "utils.hpp" + +namespace info::type { + +// TODO: move in constructors + +class TypeManager; + +class AbstractType { // latter will be found in context +public: + AbstractType(utils::AbstractTypeModifier modifier, + utils::IdType graph_id, + info::TypeclassGraph& typeclass_graph) + : modifier_(modifier), + graph_id_(graph_id), + typeclass_graph_(typeclass_graph) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const AbstractType& type) const; + bool operator<(const AbstractType& type) const; + bool operator>(const AbstractType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + utils::IdType GetGraphId() { + return graph_id_; + } + + bool HasTypeclass(utils::IdType graph_id) { // TODO: cache dependencies set + return graph_id == graph_id_ || typeclass_graph_.GetDependenciesSet(graph_id_).count(graph_id) != 0; + } + + std::string ToString() { + return "Abstract " + std::to_string(graph_id_); + } +private: + utils::AbstractTypeModifier modifier_; + utils::IdType graph_id_; + info::TypeclassGraph& typeclass_graph_; +}; + +class DefinedType { +public: + DefinedType() = default; + DefinedType(utils::IdType type_id, + utils::IdType type, + utils::ClassModifier class_modifier, + TypeManager* type_manager) + : type_id_(type_id), type_(type), class_modifier_(class_modifier), type_manager_(type_manager) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const DefinedType& type) const; + bool operator<(const DefinedType& type) const; + bool operator>(const DefinedType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + utils::IdType GetTypeId() const { + return type_id_; + } + + utils::IdType GetType() const { + return type_; + } + + utils::ClassModifier GetClassModifier() const { + return class_modifier_; + } + + std::string ToString() { + return "Defined"; + } +private: + utils::IdType type_id_; // in defined types + utils::IdType type_; // in types manager, created using context types (if specific type) + utils::ClassModifier class_modifier_; + TypeManager* type_manager_ = nullptr; +}; + +const size_t InternalTypesCount = 6; +enum class InternalType { + Float = 0, + Int = 1, + String = 2, + Char = 3, + Bool = 4, + Unit = 5, +}; + +inline std::optional ToInternalType(const std::string& type) { + if (type.empty()) { + return std::nullopt; + } + + switch (type[0]) { + case 'F': + if (type == "Float") { return InternalType::Float; } + break; + case 'I': + if (type == "Int") { return InternalType::Int; } + break; + case 'S': + if (type == "String") { return InternalType::String; } + break; + case 'C': + if (type == "Char") { return InternalType::Char; } + break; + case 'B': + if (type == "Bool") { return InternalType::Bool; } + break; + case 'U': + if (type == "Unit") { return InternalType::Unit; } + break; + default: + break; + } + + return std::nullopt; +} + +inline std::string ToString(InternalType type) { + std::string result; + + switch (type) { + case InternalType::Float: + result = "Float"; + break; + case InternalType::Int: + result = "Int"; + break; + case InternalType::String: + result = "String"; + break; + case InternalType::Char: + result = "Char"; + break; + case InternalType::Bool: + result = "Bool"; + break; + case InternalType::Unit: + result = "Unit"; + break; + } + return result; +} + +class TupleType { +public: + TupleType() = default; + TupleType(const std::optional& name, + const std::vector, utils::IdType>>& fields, + TypeManager* type_manager) + : name_(name), fields_(fields), type_manager_(type_manager) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const TupleType& type) const; + bool operator<(const TupleType& type) const; + bool operator>(const TupleType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + const std::vector, utils::IdType>>& GetFields() const { + return fields_; + } + + std::string ToString(); +private: + std::optional name_; + std::vector, utils::IdType>> fields_; + TypeManager* type_manager_ = nullptr; +}; + +class VariantType { +public: + VariantType() = default; + VariantType(const std::optional& name, + const std::vector& constructors, + std::optional current_constructor) + : name_(name), constructors_(constructors), current_constructor_(current_constructor) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const VariantType& type) const; + bool operator<(const VariantType& type) const; + bool operator>(const VariantType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + const std::vector& GetConstructors() const { + return constructors_; + } + + void SetCurrentConstructor(size_t constructor) { + current_constructor_ = constructor; + } + + std::string ToString(); +private: + std::optional name_; + std::vector constructors_; + std::optional current_constructor_; +}; + +class OptionalType { +public: + OptionalType() = default; + OptionalType(utils::IdType type, + TypeManager* type_manager) + : type_(type), type_manager_(type_manager) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const OptionalType& type) const; + bool operator<(const OptionalType& type) const; + bool operator>(const OptionalType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + std::string ToString(); +private: + utils::IdType type_; + TypeManager* type_manager_ = nullptr; +}; + +class ReferenceToType { +public: + ReferenceToType() = default; + ReferenceToType(const std::vector& references, + utils::IdType type, + TypeManager* type_manager) + : references_(references), type_(type), type_manager_(type_manager) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const ReferenceToType& type) const; + bool operator<(const ReferenceToType& type) const; + bool operator>(const ReferenceToType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + std::string ToString(); +private: + std::vector references_; + utils::IdType type_; + TypeManager* type_manager_ = nullptr; +}; + +///////////////////////////// + +class FunctionType { +public: + FunctionType() = default; + FunctionType(const std::vector& argument_types, + utils::IdType return_type, + TypeManager* type_manager) + : argument_types_(argument_types), return_type_(return_type), type_manager_(type_manager) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const FunctionType& type) const; + bool operator<(const FunctionType& type) const; + bool operator>(const FunctionType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + std::string ToString(); +private: + std::vector argument_types_; + utils::IdType return_type_; + TypeManager* type_manager_ = nullptr; +}; + +class ArrayType { +public: + ArrayType() = default; + ArrayType(size_t size, + utils::IdType elements_type, + TypeManager* type_manager) + : size_(size), elements_type_(elements_type), type_manager_(type_manager) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const ArrayType& type) const; + bool operator<(const ArrayType& type) const; + bool operator>(const ArrayType& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + utils::IdType GetElementsType() { + return elements_type_; + } + + std::string ToString(); +private: + size_t size_; // = 0 for dynamic + utils::IdType elements_type_; + TypeManager* type_manager_ = nullptr; +}; + +class Type { +public: + template + explicit Type(const T& type) : type_(type) {} + + std::optional InContext(const std::unordered_map& context); + bool Same(const Type& type) const; + bool operator<(const Type& type) const; // TODO: rule exceptions + bool operator>(const Type& type) const; + + std::optional GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const; + + std::string GetTypeName() const; + + std::variant& GetType() { + return type_; + } + + std::string ToString(); +private: + std::variant type_; +}; + +class TypeManager { +public: + template + utils::IdType AddValue(const T& type, utils::ValueType value_type) { + types_.push_back(std::pair {type, value_type}); + return types_.size() - 1; + } + + utils::IdType AddAnyValue(Type&& type, utils::ValueType value_type) { + types_.push_back(std::pair {std::move(type), value_type}); + return types_.size() - 1; + } + + template + std::optional GetValue(utils::IdType type_id) { + if (!std::holds_alternative(types_.at(type_id).first.GetType())) { + return std::nullopt; + } + return &std::get(types_.at(type_id).first.GetType()); + } + + Type* GetAnyValue(utils::IdType type_id) { + return &types_.at(type_id).first; + } + + utils::ValueType GetValueType(utils::IdType type_id) { + return types_.at(type_id).second; + } + + void SetValueType(utils::IdType type_id, utils::ValueType value_type) { + types_.at(type_id).second = value_type; + } + + bool EqualValues(utils::IdType first_type, utils::IdType second_type) { + return GetAnyValue(first_type)->Same(*GetAnyValue(second_type)); + } + + bool AddValueRequirement(utils::IdType type, utils::IdType requrement) { + return *GetAnyValue(requrement) < *GetAnyValue(type); + } + +private: + std::vector> types_; +}; + +} // namespace info::type + diff --git a/include/utils.hpp b/include/utils.hpp new file mode 100644 index 0000000..175f7ec --- /dev/null +++ b/include/utils.hpp @@ -0,0 +1,225 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace utils { + +using std::size_t; + +using IdType = size_t; + +const std::string ClassInternalVarName = "self"; +const size_t MaxOperatorPrecedence = 4; + +struct ValueReturnedMarker {}; +struct ValueBroughtMarker {}; + +enum class ReferenceModifier { Reference = 0, UniqueReference = 1, Dereference = 2 }; +enum class IsConstModifier { Const = 0, Var = 1 }; +enum class ClassInternalsModifier { Static = 0, Const = 1, Var = 2}; +enum class ClassModifier { Struct = 0, Class = 1 }; +enum class AssignmentModifier { Assign = 0, Move = 1 }; +enum class AliasModifier { Alias = 0, Type = 1, Let = 2 }; +enum class AbstractTypeModifier { Basic = 0, Abstract = 1 }; +enum class PartitionModifier { Exec = 0, Test = 1 }; + +enum class ValueType { Const = 0, Var = 1, Tmp = 2 }; + +ValueType IsConstModifierToValueType(IsConstModifier modifier); + +ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier); + +bool IsBuiltinFunction(const std::string& name); + +template +class Storage { +public: + Storage() = default; + + IdType GetId(const T& value) { + IdType id = 0; + auto value_position = value_to_id_.find(value); + + if (value_position == value_to_id_.end()) { + id = id_to_value_.size(); + value_to_id_[value] = id; + id_to_value_.push_back(value); + } else { + id = value_position->second; + } + + return id; + } + + const T& GetValue(IdType id) { + return id_to_value_[id]; + } + +private: + std::vector id_to_value_; + std::unordered_map value_to_id_; +}; + +template +class Trie { // optimize ?? +public: + Trie() { + verticles_.emplace_back(); + } + + bool Insert(const std::vector& path, const Value& value) { + return RecursiveInsert(verticles_[0], path, 0, value); + } + + std::optional Find(const std::vector& path) { + return RecursiveFind(verticles_[0], path, 0); + } + + std::vector FindByPrefix(const std::vector& path) { + return RecursiveFindByPrefix(verticles_[0], path, 0); + } +private: + struct Vertex { + std::unordered_map children_; + std::optional value; + }; + + bool RecursiveInsert(Vertex& vertex, + const std::vector& path, + size_t path_position, + const Value& value) { + if (path_position == path.size()) { + if (vertex.value.has_value()) { + return false; + } + vertex.value = value; + return true; + } + + auto child_iter = vertex.children_.find(path[path_position]); + + if (child_iter != vertex.children_.end()) { + return RecursiveInsert(verticles_[child_iter->second], path, path_position + 1, value); + } + + vertex.children_[path[path_position]] = verticles_.size(); + verticles_.emplace_back(); + return RecursiveInsert(verticles_.back(), path, path_position + 1, value); + } + + std::optional RecursiveFind(Vertex& vertex, + const std::vector& path, + size_t path_position) { + if (path_position == path.size()) { + if (!vertex.value.has_value()) { + return std::nullopt; + } + return &vertex.value.value(); + } + + auto child_iter = vertex.children_.find(path[path_position]); + + if (child_iter != vertex.children_.end()) { + return RecursiveFind(verticles_[child_iter->second], path, path_position + 1); + } + + return std::nullopt; + } + + std::vector RecursiveFindByPrefix(Vertex& vertex, + const std::vector& path, + size_t path_position) { + if (path_position == path.size()) { + std::vector ans; + RecursiveGetAll(vertex, ans); + return ans; + } + + auto child_iter = vertex.children_.find(path[path_position]); + + if (child_iter != vertex.children_.end()) { + return RecursiveFindByPrefix(verticles_[child_iter->second], path, path_position + 1); + } + + return {}; + } + + void RecursiveGetAll(Vertex& vertex, std::vector& accumulator) { + std::vector ans; + + if (vertex.value.has_value()) { + accumulator.push_back(&vertex.value.value()); + } + + for (auto& child : vertex.children_) { + RecursiveGetAll(verticles_[child.second], accumulator); + } + } + +private: + std::vector verticles_; +}; + +class GroupsManager { // TODO: recall right algorithm name +public: + GroupsManager() = default; + + explicit GroupsManager(size_t n) { + edges_.resize(n); + ranks_.resize(n); + + for (size_t i = 0; i < n; ++i) { + edges_[i] = i; + ranks_[i] = 1; + } + } + + void Unite(size_t u, size_t v) { // TODO: recall choice algorithm + u = GetGroupRoot(u); + v = GetGroupRoot(v); + if (ranks_[v] >= ranks_[u]) { + edges_[u] = v; + ranks_[v] = std::max(ranks_[u] + 1, ranks_[v]); + } else { + edges_[v] = u; + // always ranks_[u] > ranks_[v] + } + } + + bool IsInOneGroup(size_t u, size_t v) { + return GetGroupRoot(u) == GetGroupRoot(v); + } + + size_t AddElement() { + size_t id = edges_.size(); + edges_.push_back(id); + ranks_.push_back(1); + return id; + } + + size_t GetGroupRoot(size_t v) { + if (edges_[v] == v) { + return v; + } + return edges_[v] = GetGroupRoot(edges_[v]); + } +private: + std::vector edges_; + std::vector ranks_; +}; + +void BackVisitDfs(size_t id, + std::vector& verticles, + std::vector& marks, + const std::vector>& edges, + size_t mark); + +std::vector BackTopSort(const std::vector>& edges_); + +} // namespace utils diff --git a/include/values.hpp b/include/values.hpp new file mode 100644 index 0000000..3925ef9 --- /dev/null +++ b/include/values.hpp @@ -0,0 +1,244 @@ +#pragma once + +#include +#include +#include +#include +#include + +// for clangd +#include "interpreter_tree.hpp" +#include "utils.hpp" + +namespace info::value { + +struct ValueManager; + +struct Unit {}; + +struct InternalValue { +public: + InternalValue() = default; + + template + explicit InternalValue(const T& value) : value(value) {} // move ?? + + template + std::optional GetValue() { + if (!std::holds_alternative(value)) { + return std::nullopt; + } + return &std::get(value); + } + + bool Same(const InternalValue& value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); + +public: + std::variant value; +}; + +struct TupleValue { /// no need to store strings (only store associated type) ?? +public: + TupleValue() = default; + + TupleValue(std::vector, utils::IdType>>&& fields, + ValueManager* value_manager) + : fields(std::move(fields)), value_manager_(value_manager) {} + + bool Same(const TupleValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); // TODO + +public: + std::vector, utils::IdType>> fields; + +private: + ValueManager* value_manager_ = nullptr; +}; + +struct VariantValue { +public: + explicit VariantValue() = default; + + VariantValue(TupleValue&& value, size_t current_constructor) + : value(std::move(value)), current_constructor(current_constructor) {} + + bool Same(const VariantValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); + +public: + TupleValue value; + size_t current_constructor; +}; + +struct ReferenceToValue { +public: + ReferenceToValue() = default; + + ReferenceToValue(const std::vector& references, + utils::IdType value, + ValueManager* value_manager) + : references(references), value(value), value_manager_(value_manager) {} + + bool Same(const ReferenceToValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); + +public: + std::vector references; + utils::IdType value; + +private: + ValueManager* value_manager_ = nullptr; +}; + +struct FunctionValue { +public: + FunctionValue() = default; + + template + FunctionValue(const T& function, ValueManager* value_manager) + : function(function), value_manager_(value_manager) {} + + bool Same(const FunctionValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); + +public: + std::variant function; + +private: + ValueManager* value_manager_ = nullptr; +}; + + +struct ArrayValue { +public: + ArrayValue() = default; + + ArrayValue(std::vector&& elements, + bool is_constant_size, + ValueManager* value_manager) + : elements(std::move(elements)), is_constant_size(is_constant_size), value_manager_(value_manager) {} + + bool Same(const ArrayValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); + +public: + std::vector elements; + bool is_constant_size = false; + +private: + ValueManager* value_manager_ = nullptr; +}; + +struct OptionalValue { +public: + OptionalValue() = default; + + OptionalValue(std::optional value, ValueManager* value_manager) + : value(value), value_manager_(value_manager) {} + + bool Same(const OptionalValue& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); + +public: + std::optional value; + +private: + ValueManager* value_manager_ = nullptr; +}; + +struct Value { // DefinedValue ?? +public: + Value() = default; + + template + explicit Value(const T& value) : value(value) {} // move ?? + + bool Same(const Value& other_value) const; + std::optional GetFieldValue(const std::string& name) const; + + utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); + +public: + std::variant value; +}; + +class ValueManager { +public: + template + utils::IdType ExplicitAddValue(const T& value, utils::ValueType value_type) { + values_.push_back(std::pair {Value(value), value_type}); + return values_.size() - 1; + } + + utils::IdType ExplicitAddAnyValue(Value&& value, utils::ValueType value_type) { + values_.push_back(std::pair {std::move(value), value_type}); + return values_.size() - 1; + } + + template + utils::IdType AddValue(const T& value, utils::ValueType value_type) { + return ExplicitAddValue(std::move(value), value_type); + } + + utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { + return ExplicitAddAnyValue(std::move(value), value_type); + } + + template + std::optional GetValue(utils::IdType value_id) { + if (!std::holds_alternative(values_.at(value_id).first.value)) { + return std::nullopt; + } + return &std::get(values_.at(value_id).first.value); + } + + Value* GetAnyValue(utils::IdType value_id) { + return &values_.at(value_id).first; + } + + utils::ValueType GetValueType(utils::IdType value_id) { + return values_.at(value_id).second; + } + + void SetValueType(utils::IdType value_id, utils::ValueType value_type) { + values_.at(value_id).second = value_type; + } + + bool EqualValues(utils::IdType first_value, utils::IdType second_value) { + return GetAnyValue(first_value)->Same(*GetAnyValue(second_value)); + } + + bool AddValueRequirement(utils::IdType value, utils::IdType requrement) = delete; + +private: + std::vector> values_; +}; + +} // namespace info::value diff --git a/include/visitor.hpp b/include/visitor.hpp new file mode 100644 index 0000000..3ba14b3 --- /dev/null +++ b/include/visitor.hpp @@ -0,0 +1,141 @@ +#pragma once + +// for clangd +#include "interpreter_tree.hpp" + +namespace interpreter { + +using namespace tokens; + +class Visitor { +public: + virtual void VisitSourceFile(SourceFile* source_file) { + Visit(source_file); + } + +protected: + // Sources ----------------- + + virtual void Visit(SourceFile* node); + + // Namespaces, partitions ----------------- + + virtual void Visit(NamespaceSources* node); + virtual void Visit(Namespace* node); + + // Definitions ----------------- + + virtual void Visit(ImportStatement* node); + virtual void Visit(AliasDefinitionStatement* node); + virtual void Visit(VariableDefinitionStatement* node); + virtual void Visit(FunctionDeclaration* node); + virtual void Visit(FunctionDefinitionStatement* node); + virtual void Visit(TypeDefinitionStatement* node); + virtual void Visit(AbstractTypeDefinitionStatement* node); + virtual void Visit(TypeclassDefinitionStatement* node); + virtual void Visit(PartitionStatement* node); + + virtual void Visit(NamespaceStatement& node); // variant + virtual void Visit(SourceStatement& node); // variant + + // Definition parts + + virtual void Visit(FunctionDefinition* node); + virtual void Visit(TypeDefinition* node); + virtual void Visit(AnyAnnotatedType* node); + + // Flow control ----------------- + + virtual void Visit(TypeConstructorPatternParameter* node); + virtual void Visit(TypeConstructorPattern* node); + virtual void Visit(MatchCase* node); + virtual void Visit(Match* node); + virtual void Visit(Condition* node); + virtual void Visit(DoWhileLoop* node); + virtual void Visit(WhileLoop* node); + virtual void Visit(ForLoop* node); + virtual void Visit(LoopLoop* node); + + virtual void Visit(Pattern& node); // variant + virtual void Visit(FlowControl& node); // variant + + // Statements, expressions, blocks, etc. ----------------- + + virtual void Visit(BlockStatement& node); // variant + + virtual void Visit(Block* node); + + virtual void Visit(SubExpressionToken& node); // variant + virtual void Visit(SubExpression& node); // variant + virtual void Visit(PrefixedExpression& node); // variant + virtual void Visit(Expression& node); // variant + virtual void Visit(SuperExpression& node); // variant + + virtual void Visit(ScopedStatement* node); + + // Operators + + virtual void Visit(ReferenceExpression* node); + virtual void Visit(AccessExpression* node); + + // Other expressions + + virtual void Visit(FunctionCallExpression* node); + + virtual void Visit(TupleExpression* node); + virtual void Visit(VariantExpression* node); + virtual void Visit(ReturnExpression* node); + virtual void Visit(TypeConstructorParameter* node); + virtual void Visit(TypeConstructor* node); + virtual void Visit(LambdaFunction* node); + virtual void Visit(ArrayExpression* node); + + virtual void Visit(LoopControlExpression& node); // enum + + // Name + + virtual void Visit(PartitionName* node); + virtual void Visit(NameExpression* node); + virtual void Visit(TupleName* node); + virtual void Visit(VariantName* node); + virtual void Visit(AnnotatedName* node); + + virtual void Visit(AnyName& node); // variant + + // Type, typeclass, etc. ----------------- + + // Type + + virtual void Visit(FunctionType* node); + virtual void Visit(TupleType* node); + virtual void Visit(VariantType* node); + virtual void Visit(TypeExpression* node); + + virtual void Visit(AnyType& node); // variant + + virtual void Visit(ExtendedScopedAnyType* node); + + // Typeclass + + virtual void Visit(ParametrizedTypeclass* node); + + // Typeclass & Type + + virtual void Visit(ParametrizedType* node); + + // Identifiers, constants, etc. ----------------- + + virtual void Visit(AnyIdentifier* node); // std::string + + virtual void Visit(FloatNumberLiteral* node); + virtual void Visit(NumberLiteral* node); + virtual void Visit(StringLiteral* node); + virtual void Visit(CharLiteral* node); + virtual void Visit(UnitLiteral* node); + virtual void Visit(BoolLiteral* node); + + virtual void Visit(Literal& node); // variant +}; + +} // namespace interpreter + diff --git a/lang-parser b/lang-parser new file mode 160000 index 0000000..ddb08e9 --- /dev/null +++ b/lang-parser @@ -0,0 +1 @@ +Subproject commit ddb08e9b65123324800d1126d38764764363c0e5 diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp new file mode 100644 index 0000000..7a4219c --- /dev/null +++ b/src/build_visitor.cpp @@ -0,0 +1,1585 @@ +#include +#include + +// for clangd +#include "../include/build_visitor.hpp" +#include "../include/parse_token_types.hpp" +#include "../include/error_handling.hpp" + +namespace interpreter { + +void SetPosition(BaseNode& base_node, parser::ParseTree::Node& parse_node) { + base_node.start_position = parse_node.GetStartPoint(); + base_node.end_position = parse_node.GetEndPoint(); +} + +// Sources ----------------- +void BuildVisitor::Visit(SourceFile* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + size_t statement_count = parse_node.NamedChildCount(); + + node->statements.resize(statement_count); + + for (size_t i = 0; i < statement_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->statements[i]); + } + + current_node_ = parse_node; +} + +// Namespaces, partitions ----------------- + +void BuildVisitor::Visit(NamespaceSources* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + size_t statement_count = parse_node.NamedChildCount(); + + node->statements.resize(statement_count); + + for (size_t i = 0; i < statement_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->statements[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(Namespace* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.ChildCount(); + + if (child_count > 3) { // "namespace", ["var"/"const",] type, scope + std::string modifier = parse_node.NthChild(1).GetValue(); + if (modifier == "const") { + node->modifier = utils::ClassInternalsModifier::Const; + } else if (modifier == "var") { + node->modifier = utils::ClassInternalsModifier::Var; + } else { + error_handling::HandleInternalError("Can't parse namespace modifier", + "BuildVisitor.Namespace", + &node->base); + } + } else { + node->modifier = utils::ClassInternalsModifier::Static; + } + + node->type = parse_node.ChildByFieldName("type").GetValue(); + + current_node_ = parse_node.ChildByFieldName("scope"); + Visit(&node->scope); + + current_node_ = parse_node; +} + +// Definitions ----------------- + +void BuildVisitor::Visit(ImportStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t excluded_child_count = 0; + + if (parse_node.NthChild(0).GetValue() == "use") { + node->name = parse_node.ChildByFieldName("name").GetValue(); + ++excluded_child_count; + } + + StringLiteral module_name; + current_node_ = parse_node.ChildByFieldName("module_name"); + Visit(&module_name); + node->module_name = module_name.value; + ++excluded_child_count; + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > excluded_child_count) { + node->symbols.resize(child_count - excluded_child_count); + + for (size_t i = 0; i < child_count - excluded_child_count; ++i) { + node->symbols[i] = parse_node.NthNamedChild(i + excluded_child_count).GetValue(); + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(AliasDefinitionStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + std::string modifier = parse_node.NthChild(0).GetValue(); + if (modifier == "alias") { + node->modifier = utils::AliasModifier::Alias; + } else if (modifier == "type") { + node->modifier = utils::AliasModifier::Type; + } else if (modifier == "let") { + node->modifier = utils::AliasModifier::Let; + } + + node->type = parse_node.ChildByFieldName("type").GetValue(); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 2) { + node->parameters.resize(child_count - 2); + + for (size_t i = 0; i + 2 < child_count; ++i) { + node->parameters[i] = parse_node.NthNamedChild(i + 1).GetValue(); + } + } + + current_node_ = parse_node.ChildByFieldName("value"); + node->value = std::make_unique(); + Visit(node->value.get()); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(VariableDefinitionStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + std::string modifier = parse_node.NthChild(0).GetValue(); + if (modifier == "const") { + node->modifier = utils::IsConstModifier::Const; + } else if (modifier == "var") { + node->modifier = utils::IsConstModifier::Var; + } else { + // error + } + + current_node_ = parse_node.ChildByFieldName("name"); + Visit(node->name); + + current_node_ = parse_node.ChildByFieldName("value"); + Visit(node->value); + + std::string assignment_modifier = parse_node.NthChild(2).GetValue(); + if (assignment_modifier == "=") { + node->assignment_modifier = utils::AssignmentModifier::Assign; + } else if (assignment_modifier == "<-") { + node->assignment_modifier = utils::AssignmentModifier::Move; + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(FunctionDeclaration* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + // ['decl'] ['interface'] name + if (parse_node.NthChild(0).GetValue() == "decl") { + node->is_in_interface = (parse_node.NthChild(1).GetValue() == "interface"); + } else { + node->is_in_interface = false; + } + + node->name = parse_node.ChildByFieldName("name").GetValue(); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 2) { + node->parameters.resize(child_count - 2); + for (size_t i = 0; i + 2 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + node->parameters[i] = std::make_unique(); + Visit(node->parameters.back().get()); + } + } + + current_node_ = parse_node.ChildByFieldName("type"); + node->type = std::make_unique(); + Visit(node->type.get()); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(FunctionDefinitionStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("definition"); + node->definition = std::make_unique(); + Visit(node->definition.get()); + + current_node_ = parse_node.ChildByFieldName("value"); + Visit(node->value); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TypeDefinitionStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + std::string modifier = parse_node.NthChild(0).GetValue(); + if (modifier == "class") { + node->modifier = utils::ClassModifier::Class; + } else if (modifier == "struct") { + node->modifier = utils::ClassModifier::Struct; + } + + node->is_in_interface = (parse_node.NthChild(1).GetValue() == "interface"); + + current_node_ = parse_node.ChildByFieldName("definition"); + node->definition = std::make_unique(); + Visit(node->definition.get()); + + current_node_ = parse_node.ChildByFieldName("value"); + Visit(node->value); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(AbstractTypeDefinitionStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + std::string modifier = parse_node.NthChild(0).GetValue(); + if (modifier == "basic") { + node->modifier = utils::AbstractTypeModifier::Basic; + } else if (modifier == "abstract") { + node->modifier = utils::AbstractTypeModifier::Abstract; + } + + current_node_ = parse_node.ChildByFieldName("type"); + node->type = std::make_unique(); + Visit(node->type.get()); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TypeclassDefinitionStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("definition"); + node->definition = std::make_unique(); + Visit(node->definition.get()); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->requirements.reserve(child_count - 1); + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + + std::string modifier_name = current_node_.PreviousSibling().GetValue(); + utils::ClassInternalsModifier modifier; + if (modifier_name == "const") { + modifier = utils::ClassInternalsModifier::Const; + } else if (modifier_name == "var") { + modifier = utils::ClassInternalsModifier::Var; + } else { + modifier = utils::ClassInternalsModifier::Static; + } + node->requirements.push_back({modifier, + std::make_unique()}); + Visit(node->requirements.back().second.get()); + } + + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(PartitionStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + std::string partition_modifier = parse_node.NthChild(0).GetValue(); + + if (partition_modifier == "exec") { + node->modifier = utils::PartitionModifier::Exec; + } else if (partition_modifier == "test") { + node->modifier = utils::PartitionModifier::Test; + } else { + // error + } + + current_node_ = parse_node.ChildByFieldName("name"); + Visit(&node->name); + + current_node_ = parse_node.ChildByFieldName("value"); + Visit(node->value); + + current_node_ = parse_node; +} + +// + +void BuildVisitor::Visit(NamespaceStatement& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::AliasDefinitionStatement) { // optimize ?? + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::FunctionDeclaration) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::FunctionDefinitionStatement) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::TypeDefinitionStatement) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::PartitionStatement) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::Namespace) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(SourceStatement& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::ImportStatement) { // optimize ?? + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::AbstractTypeDefinitionStatement) { // optimize ?? + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::TypeclassDefinitionStatement) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::NamespaceStatement) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else { + // error + } + + current_node_ = parse_node; +} + +// Definition parts + +void BuildVisitor::Visit(FunctionDefinition* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->name = parse_node.ChildByFieldName("name").GetValue(); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->arguments.resize(child_count - 1); + for (size_t i = 0; i + 1 < child_count; ++i) { + node->arguments[i] = parse_node.NthNamedChild(i + 1).GetValue(); + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TypeDefinition* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("type"); + node->type = std::make_unique(); + Visit(node->type.get()); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + node->parameters.push_back(std::make_unique()); + Visit(node->parameters.back().get()); + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(AnyAnnotatedType* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->type = parse_node.ChildByFieldName("type").GetValue(); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->typeclasses.resize(child_count - 1); + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + node->typeclasses[i] = std::make_unique(); + Visit(node->typeclasses[i].get()); + } + } + + current_node_ = parse_node; +} + +// Flow control ----------------- + +void BuildVisitor::Visit(TypeConstructorPatternParameter* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->name.value() = parse_node.ChildByFieldName("name").GetValue(); + } + + current_node_ = parse_node.ChildByFieldName("value"), + Visit(node->value); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TypeConstructorPattern* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("constructor"); + node->constructor = std::make_unique(); + Visit(node->constructor.get()); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->parameters.resize(child_count - 1); + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + Visit(&node->parameters[i]); + } + } + + current_node_ = parse_node; +} + + +void BuildVisitor::Visit(Pattern& node) { // <-> ScopedPattern + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::NameIdentifier) { // optimize ?? + 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)); + } else if (current_node_type == parser::tokens::TypeConstructorPattern) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(MatchCase* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("value"); + Visit(node->value); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + std::string prefix = parse_node.NthChild(2).GetValue(); + + if (child_count > 2 || prefix == "?") { + current_node_ = parse_node.ChildByFieldName("condition"); + node->condition.emplace(); + Visit(node->condition.value()); + } + + if (child_count > 2 || prefix == "->") { + current_node_ = parse_node.ChildByFieldName("statement"); + node->statement.emplace(); + Visit(node->statement.value()); + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(Match* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->is_consuming_value = (parse_node.NthChild(1).GetValue() == "<-"); + + current_node_ = parse_node.ChildByFieldName("value"); + Visit(node->value); + + size_t child_count = parse_node.NamedChildCount(); + + // if (child_count > 1) { // always true (repeat1) + node->matches.resize(child_count - 1); + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + Visit(&node->matches[i]); + } + // } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(Condition* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.NamedChildCount(); + + node->conditions.resize(child_count / 2); + node->statements.resize((child_count + 1) / 2); + + for (size_t i = 0; i < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + + if (i % 2 == 0 && i / 2 < node->conditions.size()) { + Visit(node->conditions[i / 2]); + } else { + Visit(node->statements[i / 2]); + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(DoWhileLoop* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("statement"); + Visit(node->statement); + + current_node_ = parse_node.ChildByFieldName("condition"); + Visit(node->condition); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(WhileLoop* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("condition"); + Visit(node->condition); + + current_node_ = parse_node.ChildByFieldName("statement"); + Visit(node->statement); + + current_node_ = parse_node; +} +void BuildVisitor::Visit(ForLoop* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + if (parse_node.ChildCount() < 7) { // no "var" node + node->variable_modifier = utils::IsConstModifier::Const; + } else { + node->variable_modifier = utils::IsConstModifier::Var; + } + + current_node_ = parse_node.ChildByFieldName("variable"); + Visit(node->variable); + + current_node_ = parse_node.ChildByFieldName("interval"); + Visit(node->interval); + + current_node_ = parse_node.ChildByFieldName("statement"); + Visit(node->statement); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(LoopLoop* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("statement"); + Visit(node->statement); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(FlowControl& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::Match) { // optimize ?? + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::Condition) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::DoWhileLoop) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::WhileLoop) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::ForLoop) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::LoopLoop) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +// Statements, expressions, blocks, etc. ----------------- + +void BuildVisitor::Visit(BlockStatement& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::Expression) { // optimize ?? + node = std::make_unique(); + Visit(*std::get>(node)); + } else if (current_node_type == parser::tokens::VariableDefinitionStatement) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::FlowControl) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else if (current_node_type == parser::tokens::PrefixedExpression) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(Block* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + size_t statement_count = parse_node.NamedChildCount(); + + node->statements.resize(statement_count); + + for (size_t i = 0; i < statement_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->statements[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(SubExpressionToken& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::NameExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::ScopedStatement) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } if (current_node_type == parser::tokens::AccessExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::Literal) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else if (current_node_type == parser::tokens::ReferenceExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(SubExpression& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::FunctionCallExpression) { // optimize ?? + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::BinaryOperatorExpression) { + node = std::make_unique(); + VisitBinaryOperatorExpression(std::get>(node).get()); + } else if (current_node_type == parser::tokens::SubExpressionToken) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(PrefixedExpression& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::ReturnExpression) { // optimize ?? + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::LoopControlExpression) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else if (current_node_type == parser::tokens::Block) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(Expression& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::LambdaFunction) { // optimize ?? + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::TypeConstructor) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::PrefixedExpression) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else if (current_node_type == parser::tokens::SubExpression) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(SuperExpression& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::FlowControl) { // optimize ?? + node = std::make_unique(); + Visit(*std::get>(node)); + } else if (current_node_type == parser::tokens::TupleExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::VariantExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::ArrayExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::Expression) { + node = std::make_unique(); + Visit(*std::get>(node)); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(ScopedStatement* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("statement"); + Visit(node->statement); + + current_node_ = parse_node; +} + +// Operators + +void BuildVisitor::VisitBinaryOperatorExpression(FunctionCallExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->is_binary_operator_expression = true; + node->arguments.resize(2); + + current_node_ = parse_node.ChildByFieldName("left_expression"); + Visit(node->arguments[0]); + + node->name = parse_node.ChildByFieldName("operator_name").GetValue(); + + { // remove operator precedence markers + size_t operator_size = 0; + for (; operator_size < node->name.size() && node->name[operator_size] != '.'; ++operator_size) {} + node->precedence = utils::MaxOperatorPrecedence - (node->name.size() - operator_size); + node->name = node->name.substr(0, operator_size); + } + + current_node_ = parse_node.ChildByFieldName("right_expression"); + Visit(node->arguments[1]); + + // ?? + for (size_t i = 0; i < node->arguments.size(); ++i) { + if (std::holds_alternative>(node->arguments[i])) { + FunctionCallExpression* argument_node = std::get>(node->arguments[i]).get(); + if (argument_node->is_binary_operator_expression + && argument_node->precedence.has_value() + && argument_node->precedence.value() == node->precedence.value()) { + error_handling::HandleParsingError("Operators can't be chained (left argument)", node->base.start_position, node->base.end_position); + } + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(ReferenceExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.ChildCount(); + + if (child_count > 1) { + std::string reference_name = parse_node.NthChild(0).GetValue(); + if (reference_name == "^") { + node->reference = utils::ReferenceModifier::Reference; + } else if (reference_name == "~") { + node->reference = utils::ReferenceModifier::Dereference; + } else if (reference_name == "@") { + node->reference = utils::ReferenceModifier::UniqueReference; // TODO: rename to move ?? + } else { + // error + } + } + + current_node_ = parse_node.ChildByFieldName("expression"); + node->expression = std::make_unique(); + Visit(node->expression.get()); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(AccessExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + current_node_ = parse_node.ChildByFieldName("name"); + node->name = std::make_unique(); + Visit(node->name.get()); + + current_node_ = parse_node.ChildByFieldName("id"); + Visit(node->id); + + current_node_ = parse_node; +} + +// Other expressions + +void BuildVisitor::Visit(FunctionCallExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t excluded_child_count = 0; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::SubExpressionToken) { + node->prefix = std::make_unique(); + Visit(*std::get>(node->prefix.value())); + ++excluded_child_count; + } else if (current_node_type == parser::tokens::TypeExpression) { + node->prefix = std::make_unique(); + Visit(std::get>(node->prefix.value()).get()); + ++excluded_child_count; + } else { + // no prefix + } + + node->name = parse_node.ChildByFieldName("name").GetValue(); + ++excluded_child_count; + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > excluded_child_count) { + bool parameters_ended = false; + + for (size_t i = 0; i + excluded_child_count < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + excluded_child_count); + + if (current_node_.GetType() != parser::tokens::TypeExpression) { + parameters_ended = true; + } + + if (!parameters_ended) { + node->parameters.push_back(std::make_unique()); + Visit(node->parameters.back().get()); + } else { + node->arguments.push_back(std::make_unique()); + Visit(*std::get>(node->arguments.back())); + } + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TupleExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t expressions_count = parse_node.NamedChildCount(); + + node->expressions.resize(expressions_count); + + for (size_t i = 0; i < expressions_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->expressions[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(VariantExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t expressions_count = parse_node.NamedChildCount(); + + node->expressions.resize(expressions_count); + + for (size_t i = 0; i < expressions_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->expressions[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(ReturnExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->is_from_definition = (parse_node.NthChild(0).GetValue() == "return"); // "return" to return from definition and "bring" to return from block + + current_node_ = parse_node.ChildByFieldName("expression"); + Visit(node->expression); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TypeConstructorParameter* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->name = parse_node.ChildByFieldName("name").GetValue(); + + std::string assignment_modifier = current_node_.NextSibling().GetValue(); + if (assignment_modifier == "=") { + node->asignment_modifier = utils::AssignmentModifier::Assign; + } else if (assignment_modifier == "<-") { + node->asignment_modifier = utils::AssignmentModifier::Move; + } + } + + current_node_ = parse_node.ChildByFieldName("value"); + Visit(node->value); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TypeConstructor* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->is_allocated_on_heap = (parse_node.NthChild(1).GetValue() == "@"); + + current_node_ = parse_node.ChildByFieldName("constructor"); + node->constructor = std::make_unique(); + Visit(node->constructor.get()); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->parameters.resize(child_count - 1); + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + Visit(&node->parameters[i]); + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(LambdaFunction* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + bool parameters_ended = false; + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + + if (current_node_.GetType() != parser::tokens::AnnotatedAbstractType) { + parameters_ended = true; + } + + if (!parameters_ended) { + node->parameters.push_back(std::make_unique()); + Visit(node->parameters.back().get()); + } else { + node->arguments.emplace_back(); + node->arguments.back() = current_node_.GetValue(); + } + } + } + + current_node_ = parse_node.ChildByFieldName("expression"); + Visit(node->expression); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(ArrayExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t elements_count = parse_node.NamedChildCount(); + + node->elements.resize(elements_count); + + for (size_t i = 0; i < elements_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->elements[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(LoopControlExpression& node) { + std::string value = current_node_.NthChild(0).GetValue(); + + if (value == "break") { + node = LoopControlExpression::Break; + } else if (value == "continue") { + node = LoopControlExpression::Continue; + } else { + // error + } +} + +// Name + +void BuildVisitor::Visit(PartitionName* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->path.resize(child_count - 1); + for (size_t i = 0; i + 1 < child_count; ++i) { + node->path[i] = parse_node.NthNamedChild(i).GetValue(); + } + } + + node->path.push_back(parse_node.ChildByFieldName("name").GetValue()); + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(NameExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.NamedChildCount(); + + node->names.resize(child_count); + for (size_t i = 0; i < child_count; ++i) { + node->names[i] = parse_node.NthNamedChild(i).GetValue(); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TupleName* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t names_count = parse_node.NamedChildCount(); + + node->names.resize(names_count); + + for (size_t i = 0; i < names_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + node->names[i] = std::make_unique(); + Visit(node->names[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(VariantName* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t names_count = parse_node.NamedChildCount(); + + node->names.resize(names_count); + + for (size_t i = 0; i < names_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + node->names[i] =std::make_unique(); + Visit(node->names[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(AnnotatedName* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->name = parse_node.ChildByFieldName("name").GetValue(); + + if (parse_node.NamedChildCount() > 1) { + current_node_ = parse_node.ChildByFieldName("type"); + node->type.emplace(); + Visit(node->type.value()); + + current_node_ = parse_node; + } +} + +void BuildVisitor::Visit(AnyName& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::AnnotatedName) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::TupleName) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::VariantName) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +// Type, typeclass, etc. ----------------- + +// Type + +void BuildVisitor::Visit(FunctionType* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t types_count = parse_node.NamedChildCount(); + + node->types.resize(types_count); + + for (size_t i = 0; i < types_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(node->types[i]); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TupleType* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t current_child = 0; + + current_node_ = parse_node.NthNamedChild(current_child); + + if (parse_node.NthChild(0).GetValue() != "&") { + node->type = current_node_.GetValue(); + + ++current_child; + current_node_ = parse_node.NthNamedChild(current_child); + } + + while (current_child < parse_node.NamedChildCount()) { + node->entities.emplace_back(); + + if (current_node_.GetType() == parser::tokens::NameIdentifier) { + node->entities.back().first = current_node_.GetValue(); + + ++current_child; + current_node_ = parse_node.NthNamedChild(current_child); + } + + node->entities.back().second = std::make_unique(); + Visit(node->entities.back().second.get()); + + ++current_child; + current_node_ = parse_node.NthNamedChild(current_child); + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(VariantType* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t excluded_child_count = 0; + + size_t child_count = parse_node.NamedChildCount(); + + if (parse_node.NthChild(0).GetValue() != "|") { + node->type = parse_node.NthNamedChild(0).GetValue(); + + ++excluded_child_count; + } + + + node->constructors.resize(child_count - excluded_child_count); + for (size_t i = 0; i < node->constructors.size(); ++i) { + current_node_ = parse_node.NthNamedChild(i + excluded_child_count); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::Constructor) { + node->constructors[i] = current_node_.GetValue(); + } else if (current_node_type == parser::tokens::TupleType) { + node->constructors[i] = std::make_unique(); + Visit(std::get>(node->constructors[i]).get()); + } else { + // error + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(TypeExpression* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t excluded_child_count = 0; + + size_t child_count = parse_node.NamedChildCount(); + + current_node_ = parse_node.ChildByFieldName("type"); + Visit(&node->type); + ++excluded_child_count; + + current_node_ = current_node_.NextSibling(); + + if (!current_node_.IsNull()) { + current_node_ = current_node_.NextSibling(); + if (!current_node_.IsNull()) { + NumberLiteral literal; + Visit(&literal); + node->array_size = literal.value; + ++excluded_child_count; + } else { + node->array_size = 0; + } + } + + if (child_count > excluded_child_count) { + node->path.resize(child_count - excluded_child_count); + + for (size_t i = 0; i + excluded_child_count < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i); + Visit(&node->path[i]); + } + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(AnyType& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::TypeExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::TupleType) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::VariantType) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::FunctionType) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +void BuildVisitor::Visit(ExtendedScopedAnyType* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + size_t child_count = parse_node.ChildCount(); + + if (child_count > 1) { + node->references.resize(child_count - 1); + for (size_t i = 0; i + 1 < child_count; ++i) { + std::string reference = parse_node.NthChild(i).GetValue(); + if (reference == "^") { + node->references[i] = utils::ReferenceModifier::Reference; + } else if (reference == "@") { + node->references[i] = utils::ReferenceModifier::UniqueReference; + } + } + } + + current_node_ = parse_node.ChildByFieldName("type"); + Visit(node->type); + + current_node_ = parse_node; +} + +// Typeclass + +void BuildVisitor::Visit(ParametrizedTypeclass* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + std::string prefixed_typeclass = parse_node.ChildByFieldName("typeclass").GetValue(); // prefix # removed + node->typeclass = prefixed_typeclass.substr(1, prefixed_typeclass.size() - 1); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->parameters.resize(child_count - 1); + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + node->parameters[i] = std::make_unique(); + Visit(node->parameters[i].get()); + } + } + + current_node_ = parse_node; +} + +// Typeclass & Type ----------------- + + +void BuildVisitor::Visit(ParametrizedType* node) { + SetPosition(node->base, current_node_); + + auto parse_node = current_node_; + + node->type = parse_node.ChildByFieldName("type").GetValue(); + + size_t child_count = parse_node.NamedChildCount(); + + if (child_count > 1) { + node->parameters.resize(child_count - 1); + + for (size_t i = 0; i + 1 < child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + 1); + node->parameters[i] = std::make_unique(); + Visit(node->parameters[i].get()); + } + } + + current_node_ = parse_node; +} + +// Identifiers, constants, etc. ----------------- + +// void BuildVisitor::Visit(AnyIdentifier* node) { // std::string +// *node = current_node_.GetValue(); +// } + +void BuildVisitor::Visit(FloatNumberLiteral* node) { + SetPosition(node->base, current_node_); + + node->value = std::stod(current_node_.GetValue()); +} + +void BuildVisitor::Visit(NumberLiteral* node) { + SetPosition(node->base, current_node_); + + node->value = std::stoll(current_node_.GetValue()); +} + +void BuildVisitor::Visit(StringLiteral* node) { // TODO: special symbols, etc. + SetPosition(node->base, current_node_); + + std::string literal = current_node_.GetValue(); + node->value = literal.substr(1, literal.size() - 2); +} + +void BuildVisitor::Visit(CharLiteral* node) { + SetPosition(node->base, current_node_); + + std::string literal = current_node_.GetValue(); + node->value = literal.substr(1, literal.size() - 2).back(); // TODO: special symbols, etc. +} + +void BuildVisitor::Visit(UnitLiteral* node) { + SetPosition(node->base, current_node_); +} + +void BuildVisitor::Visit(BoolLiteral* node) { + SetPosition(node->base, current_node_); + + std::string literal = current_node_.GetValue(); + node->value = (literal == "true"); // always "false" in other way +} + +void BuildVisitor::Visit(Literal& node) { + auto parse_node = current_node_; + + current_node_ = parse_node.NthNamedChild(0); + + std::string current_node_type = current_node_.GetType(); + + if (current_node_type == parser::tokens::FloatNumberLiteral) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::NumberLiteral) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::StringLiteral) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::CharLiteral) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::UnitLiteral) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else if (current_node_type == parser::tokens::BoolLiteral) { + node = std::make_unique(); + Visit(std::get>(node).get()); + } else { + // error + } + + current_node_ = parse_node; +} + +} // namespace interpreter diff --git a/src/execute_visitor.cpp b/src/execute_visitor.cpp new file mode 100644 index 0000000..9f0e74a --- /dev/null +++ b/src/execute_visitor.cpp @@ -0,0 +1,1262 @@ +#include +#include + +// for clangd +#include "../include/execute_visitor.hpp" +#include "../include/builtin_functions.hpp" + + +// TODO + +namespace interpreter { + +// Sources ----------------- + +void ExecuteVisitor::Visit(SourceFile* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.SourceFile", + &node->base); +} + +// Namespaces, partitions ----------------- + +void ExecuteVisitor::Visit(NamespaceSources* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.NamespaceSources", + &node->base); +} + +void ExecuteVisitor::Visit(Namespace* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.Namespace", + &node->base); +} + +// Definitions ----------------- + +void ExecuteVisitor::Visit(ImportStatement* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.ImportStatement", + &node->base); +} + +void ExecuteVisitor::Visit(AliasDefinitionStatement* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.AliasDefinitionStatement", + &node->base); +} + +void ExecuteVisitor::Visit(VariableDefinitionStatement* node) { + Visitor::Visit(node->value); + + is_const_definition_ = node->modifier; + Visitor::Visit(node->name); // current_type_ passed from value + is_const_definition_ = std::nullopt; +} + +void ExecuteVisitor::Visit(FunctionDeclaration* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.FunctionDeclaration", + &node->base); +} + +void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { // visited on function call + context_manager_.EnterContext(); + + size_t context_count = context_manager_.ContextCount(); + try { + Visitor::Visit(node->value); + } catch (utils::ValueReturnedMarker&) { + while (context_manager_.ContextCount() > context_count) { + context_manager_.ExitContext(); + } + } + + // TODO: sometimes return references, choose by declaration + current_value_ = context_manager_.ToTemporaryValue(current_value_); + + context_manager_.ExitContext(); +} + +void ExecuteVisitor::Visit(TypeDefinitionStatement* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.TypeDefinitionStatement", + &node->base); +} + +void ExecuteVisitor::Visit(AbstractTypeDefinitionStatement* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.AbstractTypeDefinitionStatement", + &node->base); +} + +void ExecuteVisitor::Visit(TypeclassDefinitionStatement* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.TypeclassDefinitionStatement", + &node->base); +} + +void ExecuteVisitor::Visit(PartitionStatement* node) { + Visitor::Visit(node->value); +} + +// Flow control ----------------- + +void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) { // handled in TypeConstructorPattern + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.TypeConstructorPatternParameter", + &node->base); +} + +// TODO: check +void ExecuteVisitor::Visit(TypeConstructorPattern* node) { + if (!node->constructor->constructor_id_.has_value()) { // checked in typeckeck visitor ?? + error_handling::HandleRuntimeError("Type constructor pattern constructor name not found", node->base); + } + + utils::IdType constructor_id = node->constructor->constructor_id_.value(); + + // only one has value inside + auto maybe_variant_value_info = context_manager_.GetValue(current_value_); + auto maybe_tuple_value_info = context_manager_.GetValue(current_value_); + + if (maybe_variant_value_info.has_value()) { + info::value::VariantValue* variant_value_info = maybe_variant_value_info.value(); + + if (constructor_id != variant_value_info->current_constructor) { + case_matched_ = false; + return; + } + + // extract named parameters ?? + for (size_t i = 0; i < node->parameters.size(); ++i) { // not visit if case not matched inside ?? + current_value_ = variant_value_info->value.fields[i].second; + Visitor::Visit(node->parameters[i].value); + } + } else if (maybe_tuple_value_info.has_value()) { + info::value::TupleValue* tuple_value_info = maybe_tuple_value_info.value(); + + // extract named parameters ?? + for (size_t i = 0; i < node->parameters.size(); ++i) { // not visit if case not matched inside ?? + current_value_ = tuple_value_info->fields[i].second; + Visitor::Visit(node->parameters[i].value); + } + } else { + error_handling::HandleRuntimeError("Wrong value type for type constructor pattern (not variant or tuple)", node->base); + } +} + +void ExecuteVisitor::Visit(MatchCase* node) { // handeled in Match + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.MatchCase", + &node->base); +} + +void ExecuteVisitor::Visit(Match* node) { + context_manager_.EnterContext(); + + Visitor::Visit(node->value); + + utils::IdType value = current_value_; + + bool case_choosen = false; + bool statement_visited = false; + for (auto& match_case : node->matches) { + if (case_choosen) { + if (match_case.statement.has_value()) { + Visitor::Visit(match_case.statement.value()); + statement_visited = true; + break; + } + } else { + current_value_ = value; + case_matched_ = true; + + context_manager_.EnterContext(); + Visitor::Visit(node->value); + + if (case_matched_ && (match_case.condition.has_value() ? HandleCondition(match_case.condition.value(), match_case.base) : true)) { + case_choosen = true; + if (match_case.statement.has_value()) { + Visitor::Visit(match_case.statement.value()); + statement_visited = true; + break; + } + } else { + context_manager_.ExitContext(); + } + } + } + + if (case_choosen) { + context_manager_.ExitContext(); + } + + if (!statement_visited) { + error_handling::HandleRuntimeError("Value match option not found", node->base); + } + + context_manager_.ExitContext(); +} + +void ExecuteVisitor::Visit(Condition* node) { + bool branch_visited = false; + for (size_t i = 0; i < node->conditions.size(); ++i) { + if (HandleCondition(node->conditions[i], node->base)) { + context_manager_.EnterContext(); + Visitor::Visit(node->statements[i]); + context_manager_.ExitContext(); + + if (node->statements.size() == node->conditions.size()) { + current_value_ = context_manager_.AddValue( // optional with "reference" to value + info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), + context_manager_.GetValueType(current_value_)); + } + branch_visited = true; + break; + } + } + + if (!branch_visited) { + if (node->statements.size() > node->conditions.size()) { + context_manager_.EnterContext(); + Visitor::Visit(node->statements[node->conditions.size()]); + context_manager_.ExitContext(); + } else { + current_value_ = context_manager_.AddValue( // optional with "reference" to value + info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()), + context_manager_.GetValueType(current_value_)); + } + } +} + +void ExecuteVisitor::Visit(DoWhileLoop* node) { + std::vector result; + do { + context_manager_.EnterContext(); + + Visitor::Visit(node->statement); + if (active_loop_control_expression_.has_value()) { + if (active_loop_control_expression_.value() == LoopControlExpression::Break) { + active_loop_control_expression_ = std::nullopt; + break; + } + active_loop_control_expression_ = std::nullopt; + continue; + + } + result.push_back(context_manager_.ToTemporaryValue(current_value_)); + + context_manager_.ExitContext(); + } while(HandleCondition(node->condition, node->base)); + + current_value_ = context_manager_.AddValue( + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(WhileLoop* node) { + std::vector result; + while(HandleCondition(node->condition, node->base)) { + context_manager_.EnterContext(); + + Visitor::Visit(node->statement); + if (active_loop_control_expression_.has_value()) { + if (active_loop_control_expression_.value() == LoopControlExpression::Break) { + active_loop_control_expression_ = std::nullopt; + break; + } + active_loop_control_expression_ = std::nullopt; + continue; + + } + result.push_back(context_manager_.ToTemporaryValue(current_value_)); + + context_manager_.ExitContext(); + } + + current_value_ = context_manager_.AddValue( + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), + utils::ValueType::Tmp); +} + +// TODO: extend to different interval types (not only array) +// TODO: assign to variable, instead of making new ?? +void ExecuteVisitor::Visit(ForLoop* node) { + std::vector result; + + Visitor::Visit(node->interval); + info::value::ArrayValue* interval = ExtractValue(current_value_, node->base); + + for (auto& value : interval->elements) { // TODO: reference to element + context_manager_.EnterContext(); + + current_value_ = value; + + is_const_definition_ = node->variable_modifier; + Visitor::Visit(node->variable); + is_const_definition_ = std::nullopt; + + Visitor::Visit(node->statement); + if (active_loop_control_expression_.has_value()) { + if (active_loop_control_expression_.value() == LoopControlExpression::Break) { + active_loop_control_expression_ = std::nullopt; + break; + } + active_loop_control_expression_ = std::nullopt; + continue; + + } + result.push_back(context_manager_.ToTemporaryValue(current_value_)); + + context_manager_.ExitContext(); + } + + current_value_ = context_manager_.AddValue( + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(LoopLoop* node) { + std::vector result; + while(true) { + context_manager_.EnterContext(); + + Visitor::Visit(node->statement); + if (active_loop_control_expression_.has_value()) { + if (active_loop_control_expression_.value() == LoopControlExpression::Break) { + active_loop_control_expression_ = std::nullopt; + break; + } + active_loop_control_expression_ = std::nullopt; + continue; + + } + result.push_back(context_manager_.ToTemporaryValue(current_value_)); + + context_manager_.ExitContext(); + } + + current_value_ = context_manager_.AddValue( + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), + utils::ValueType::Tmp); +} + +// Statements, expressions, blocks, etc. ----------------- + +void ExecuteVisitor::Visit(Block* node) { + context_manager_.EnterContext(); + + bool value_brought = false; + + for (auto& statement : node->statements) { + size_t context_count = context_manager_.ContextCount(); + try { + Visitor::Visit(statement); + } catch (utils::ValueBroughtMarker&) { // current_value_ passed from ReturnExpression + while (context_manager_.ContextCount() > context_count) { + context_manager_.ExitContext(); + } + value_brought = true; + break; + } + } + + context_manager_.ExitContext(); + + if (!value_brought) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } +} + +void ExecuteVisitor::Visit(ScopedStatement* node) { + Visitor::Visit(node->statement); // current_value_ passed from statement +} + +void ExecuteVisitor::Visit(LoopControlExpression& node) { + active_loop_control_expression_ = node; + + current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); +} + +// Operators + +void ExecuteVisitor::Visit(ReferenceExpression* node) { + // TODO: check, that there is no references to "Tmp"?? + Visit(node->expression.get()); + + utils::ValueType value_type = context_manager_.GetValueType(current_value_); + + current_value_ = context_manager_.AddValue( // "reference" to type (save const / var) + info::value::ReferenceToValue({node->reference}, current_value_, context_manager_.GetValueManager()), + value_type); +} + +// TODO: extend to other types +// TODO: string should be array +void ExecuteVisitor::Visit(AccessExpression* node) { + Visit(node->name.get()); + utils::IdType array_value = current_value_; + utils::ValueType value_type = context_manager_.GetValueType(array_value); + + Visitor::Visit(node->id); + int64_t index = *ExtractInternalValue(current_value_, node->base); // TODO: size_t + + if (index < 0) { + error_handling::HandleRuntimeError("Access index is negative", node->base); + } + + if (node->is_string_access_) { + std::string* string_value_info = ExtractInternalValue(current_value_, node->base); + + if (index >= (int64_t)string_value_info->size()) { + error_handling::HandleRuntimeError("Access index is out of range (string)", node->base); + } + + current_value_ = context_manager_.ToModifiedValue((*string_value_info)[index], utils::ValueType::Tmp); + } else { + info::value::ArrayValue* array_value_info = ExtractValue(current_value_, node->base); + + if (index >= (int64_t)array_value_info->elements.size()) { + error_handling::HandleRuntimeError("Access index is out of range (array)", node->base); + } + + current_value_ = context_manager_.ToModifiedValue(array_value_info->elements[index], value_type); + } +} + +// Other Expressions + +// TODO: refactor, separate to several functions +void ExecuteVisitor::Visit(FunctionCallExpression* node) { + context_manager_.EnterContext(); + + if (node->prefix.has_value()) { + if (std::holds_alternative>(node->prefix.value())) { + Visitor::Visit(*std::get>(node->prefix.value())); + + if (context_manager_.GetValueType(current_value_) == utils::ValueType::Tmp) { + // temporary value can't be modified inside + context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + } + if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) { + error_handling::HandleRuntimeError("Variable redefinition (mathod caller var)", node->base); + } + } else if (std::holds_alternative>(node->prefix.value())) { + TypeExpression& prefix = *std::get>(node->prefix.value()); + + // TODO: abstract types, local abstract types, abstract types, ... as path entities + for (auto& path_type : prefix.path) { + CollectTypeContext(path_type); + } + + CollectTypeContext(prefix.type); + } else { + error_handling::HandleInternalError("Unexpected prefix type", + "ExecuteVisitor.FunctionCallExpression", + &node->base); + } + } else { + if (node->is_method_of_first_argument_) { + Visitor::Visit(node->arguments[0]); + + if (context_manager_.GetValueType(current_value_) == utils::ValueType::Tmp) { + // temporary value can't be modified inside + context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + } + if (!context_manager_.DefineVariable(utils::ClassInternalVarName, current_value_)) { + error_handling::HandleRuntimeError("Variable redefinition (self var)", node->base); + } + } + } + + FunctionDeclaration* function_declaration = nullptr; + FunctionDefinitionStatement* function_definition = nullptr; + + if (node->function_id_.has_value()) { + auto maybe_function_declaration_info = global_info_.GetFunctionInfo(node->function_id_.value()).declaration; + + if (!maybe_function_declaration_info.has_value()) { + error_handling::HandleRuntimeError("Function declaration not found (for namespace function)", node->base); + } + + function_declaration = maybe_function_declaration_info.value().node; + + auto maybe_function_definition_info = global_info_.GetFunctionInfo(node->function_id_.value()).definition; + + if (!maybe_function_definition_info.has_value()) { + if (HandleBuiltinFunctionCall(node)) { + context_manager_.ExitContext(); + return; // TODO: return from end of function + } + + error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base); + } + + function_definition = maybe_function_definition_info.value().node; + + } else if (node->graph_id_.has_value()) { + + utils::IdType defined_type_graph_id; // try to find defined or basic type + if (typeclass_graph_.GetVertex(node->graph_id_.value()).type_id.has_value() + || (node->abstract_type_name_.has_value() + && info::type::ToInternalType(node->abstract_type_name_.value()).has_value())) { + defined_type_graph_id = node->graph_id_.value(); + } + else { + auto maybe_defined_type_graph_id = context_manager_.FindLocalType(node->abstract_type_name_.value()); + if (!maybe_defined_type_graph_id.has_value()) { + error_handling::HandleRuntimeError("Function's defined / basic abstract type not found (by abstract_type_name_ and in typeclass graph)", node->base); + } + defined_type_graph_id = maybe_defined_type_graph_id.value(); + } + + + std::optional maybe_function_definition; + + auto maybe_function_graph_info = typeclass_graph_.GetFunctionInfo(node->name, + defined_type_graph_id); + + if (!maybe_function_graph_info.has_value()) { + error_handling::HandleRuntimeError("Function info not found (by graph_id_)", node->base); + } + + function_declaration = maybe_function_graph_info.value()->declaration; + maybe_function_definition = maybe_function_graph_info.value()->definition; + + if (!maybe_function_definition.has_value()) { + if (typeclass_graph_.GetVertex(defined_type_graph_id).modifier == info::TypeclassGraph::Modifier::Type) { + auto maybe_internal_type = info::type::ToInternalType(typeclass_graph_.GetVertex(defined_type_graph_id).name); + + if (maybe_internal_type.has_value()) { + if (HandleBuiltinTypeFunctionCall(node, maybe_internal_type.value())) { + context_manager_.ExitContext(); + return; // TODO: return from end of function + } + error_handling::HandleRuntimeError("Type function definition not found (builtin type)", node->base); + } + + error_handling::HandleRuntimeError("Type function definition not found (by graph_id_)", node->base); + } + error_handling::HandleRuntimeError("Function definition not found (by graph_id_)", node->base); + } + + function_definition = maybe_function_definition.value(); + + auto dependency_graph_ids = typeclass_graph_.GetDependenciesSet(node->graph_id_.value()); + dependency_graph_ids.insert(node->graph_id_.value()); // TODO: ?? + for (auto& dependency_graph_id : dependency_graph_ids) { + context_manager_.DefineLocalType(typeclass_graph_.GetVertex(dependency_graph_id).name, defined_type_graph_id); + } + } + + // handle choosen type typclasses + + // handle parameters + for (size_t i = 0; i < node->parameters.size(); ++i) { + utils::IdType graph_id = 0; + + if (node->parameters[i]->type_id_.has_value()) { + graph_id = GraphIdByTypeId(node->parameters[i]->type_id_.value()); + } else { + auto maybe_parameter_graph_id = context_manager_.FindLocalType(node->parameters[i]->type.type); + + if (!maybe_parameter_graph_id.has_value()) { + error_handling::HandleInternalError("Parameter type not found", + "ExecuteVisitor.FunctionCallExpression", + &node->base); + } + + graph_id = maybe_parameter_graph_id.value(); + } + + if (!context_manager_.DefineLocalType(function_declaration->parameters[i]->type, graph_id)) { + error_handling::HandleRuntimeError("Type redefinition (function argument)", node->base); + } + } + + size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0); + + // handle arguments + for (size_t i = index_shift; i < node->arguments.size(); ++i) { + Visitor::Visit(node->arguments[i]); + + // function arguments can't be changed inside function + current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const); + if (!context_manager_.DefineVariable(function_definition->definition->arguments[i - index_shift], + current_value_)) { + error_handling::HandleRuntimeError("Variable redefinition (function argument)", node->base); + } + } + + context_manager_.ChangeHidingOfCurrentContextTo(true); + Visit(function_definition); + + context_manager_.ExitContext(); +} + +void ExecuteVisitor::Visit(TupleExpression* node) { + std::vector, utils::IdType>> fields; + fields.reserve(node->expressions.size()); + for (auto& expression : node->expressions) { + Visitor::Visit(expression); + fields.push_back({std::nullopt, context_manager_.ToTemporaryValue(current_value_)}); + } + + current_value_ = context_manager_.AddValue( + info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), + utils::ValueType::Tmp); +} + +// TODO: handle tuples separately ?? +void ExecuteVisitor::Visit(VariantExpression* node) { + for (size_t i = 0; i < node->expressions.size(); ++i) { + Visitor::Visit(node->expressions[i]); + current_value_ = context_manager_.ToTemporaryValue(current_value_); + + info::value::OptionalValue* expression_value = ExtractValue(current_value_, node->base); + if (expression_value->value.has_value()) { + std::vector, utils::IdType>> fields + {{std::nullopt, expression_value->value.value()}}; // TODO: any type instead tuple in variant type ?? + + info::value::TupleValue variant_tuple = + info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()); + + current_value_ = context_manager_.AddValue( + info::value::VariantValue(std::move(variant_tuple), i), + utils::ValueType::Tmp); + + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + return; + } + } + + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(ReturnExpression* node) { + Visitor::Visit(node->expression); + if (node->is_from_definition) { + throw utils::ValueReturnedMarker(); + } + + throw utils::ValueBroughtMarker(); +} + + +void ExecuteVisitor::Visit(TypeConstructorParameter* node) { // handled in TypeConstructor + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.TypeConstructorParameter", + &node->base); +} + +void ExecuteVisitor::Visit(TypeConstructor* node) { + std::vector, utils::IdType>> fields; + + if (!node->constructor->constructor_id_.has_value()) { + error_handling::HandleRuntimeError("Type constructor name not found", node->base); + } + + utils::IdType constructor_id = node->constructor->constructor_id_.value(); + info::definition::Constructor constructor_info = global_info_.GetConstructorInfo(constructor_id); + + fields.reserve(node->parameters.size()); + for (auto& parameter : node->parameters) { + Visitor::Visit(parameter.value); + fields.push_back( + { parameter.name.has_value() ? std::optional(parameter.name.value()) : std::nullopt, + context_manager_.ToTemporaryValue(current_value_) }); + } + + if (constructor_info.order.has_value()) { // => variant + current_value_ = context_manager_.AddValue( + info::value::VariantValue( + info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), + constructor_info.order.value()), + utils::ValueType::Tmp); + } else { // => tuple + current_value_ = context_manager_.AddValue( + info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), + utils::ValueType::Tmp); + } +} + +// TODO +void ExecuteVisitor::Visit(LambdaFunction* node) { + error_handling::HandleInternalError("Lambda function are not implemented yet", + "ExecuteVisitor.LambdaFunction", + &node->base); +} + +void ExecuteVisitor::Visit(ArrayExpression* node) { + std::vector elements; + + elements.reserve(node->elements.size()); + for (auto& element : node->elements) { + Visitor::Visit(element); + elements.push_back(context_manager_.ToTemporaryValue(current_value_)); + } + + current_value_ = context_manager_.AddValue( + info::value::ArrayValue(std::move(elements), true, context_manager_.GetValueManager()), // maybe size not fixed?? + utils::ValueType::Tmp); +} + +// Name + +void ExecuteVisitor::Visit(NameExpression* node) { // TODO: check + if (node->names.empty()) { + error_handling::HandleInternalError("Names array is empty", + "ExecuteVisitor.NameExpression", + &node->base); + } + + std::optional maybe_variable_value = + context_manager_.FindVariable(node->names[0]); + + if (!maybe_variable_value.has_value()) { + error_handling::HandleRuntimeError("Variable not found", node->base); + } + + current_value_ = maybe_variable_value.value(); + + if (node->names.size() > 1) { + utils::ValueType variable_value_type = context_manager_.GetValueType(current_value_); + + for (size_t i = 1; i < node->names.size(); ++i) { + std::optional maybe_field_value = context_manager_.GetAnyValue(current_value_)->GetFieldValue(node->names[i]); + if (!maybe_field_value.has_value()) { + error_handling::HandleRuntimeError("Variable field not found", node->base); + } + + current_value_ = maybe_field_value.value(); + } + + current_value_ = context_manager_.ToModifiedValue(current_value_, variable_value_type); + } +} + +void ExecuteVisitor::Visit(TupleName* node) { + utils::IdType value = current_value_; + + std::optional maybe_tuple_value = context_manager_.GetValue(value); + + if (maybe_tuple_value.has_value()) { + error_handling::HandleRuntimeError("Mismatched value types in tuple variable definition", node->base); + } + + if (maybe_tuple_value.value()->fields.size() != node->names.size()) { + error_handling::HandleRuntimeError("Mismatched field count in tuple variable definition", node->base); + } + + for (size_t i = 0; i < node->names.size(); ++i) { + current_value_ = maybe_tuple_value.value()->fields[i].second; + + Visitor::Visit(node->names[i]); + } + + current_value_ = value; +} + +// TODO +// TODO: make variant of TupleValue +void ExecuteVisitor::Visit(VariantName* node) { + utils::IdType value = current_value_; + + auto value_type = context_manager_.GetValueType(value); + + std::optional maybe_variant_value = context_manager_.GetValue(value); + + if (!maybe_variant_value.has_value()) { + error_handling::HandleRuntimeError("Mismatched value types in variant variable definition", node->base); + } + + for (size_t i = 0; i < node->names.size(); ++i) { + if (i == maybe_variant_value.value()->current_constructor) { + if (maybe_variant_value.value()->value.fields.empty()) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + current_value_ = context_manager_.AddValue( + maybe_variant_value.value()->value, + value_type); + } + + current_value_ = context_manager_.AddValue( // make optional value "reference" + info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), + value_type); + } else { + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(std::nullopt, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + } + + Visitor::Visit(node->names[i]); + } + + current_value_ = value; +} + +// TODO: move, etc. +void ExecuteVisitor::Visit(AnnotatedName* node) { + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.AnnotatedName", + &node->base); + } + + auto value_type = context_manager_.GetValueType(current_value_); + + if (value_type == utils::ValueType::Tmp) { + // consume temporary value + context_manager_.ModifiyValue(current_value_, IsConstModifierToValueType(is_const_definition_.value())); + } else { + // make value copy + current_value_ = context_manager_.ToModifiedValueCopy(current_value_, IsConstModifierToValueType(is_const_definition_.value())); + } + + if (!context_manager_.DefineVariable(node->name, current_value_)) { + error_handling::HandleRuntimeError("Variable name already present in context", node->base); + } +} + +// Type, typeclass, etc. ----------------- + +// Type + +void ExecuteVisitor::Visit(FunctionType* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.FunctionType", + &node->base); +} + +void ExecuteVisitor::Visit(TupleType* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.TupleType", + &node->base); +} + +void ExecuteVisitor::Visit(VariantType* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.VariantType", + &node->base); +} + +void ExecuteVisitor::Visit(TypeExpression* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.TypeExpression", + &node->base); +} + +void ExecuteVisitor::Visit(ExtendedScopedAnyType* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.ExtendedScopedAnyType", + &node->base); +} + +// Typeclass + +void ExecuteVisitor::Visit(ParametrizedTypeclass* node) { + error_handling::HandleInternalError("Should be unreachable", + "TypeCheckVisitor.ParametrizedTypeclass", + &node->base); +} + +// Typeclass & Type ----------------- + +void ExecuteVisitor::Visit(ParametrizedType*) {} // no value + +// Identifiers, constants, etc. ----------------- + +void ExecuteVisitor::Visit(FloatNumberLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(NumberLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(StringLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(CharLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(UnitLiteral*) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); +} + +void ExecuteVisitor::Visit(BoolLiteral* node) { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(node->value), + utils::ValueType::Tmp); +} + +// + +bool ExecuteVisitor::HandleCondition(Expression& node, const BaseNode& base_node) { + Visitor::Visit(node); + return *ExtractInternalValue(current_value_, base_node); +} + +// TODO: handle abstract types, handle local abstract types, etc. // partially done (check needed) +void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { + utils::IdType type_id = 0; + + if (!type.type_id_.has_value()) { + // abstract types have no parameters + return; + } else { + type_id = type.type_id_.has_value(); + } + + auto maybe_type_info = global_info_.GetTypeInfo(type_id); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("CollectTypeContext implemented only for AnyType", + "ExecuteVisitor.CollectTYpeContext", + std::nullopt); + } + + info::definition::AnyType& type_info = *maybe_type_info.value(); // check, that has value ?? + + for (size_t i = 0; i < type.parameters.size(); ++i) { + if (type.parameters[i]->type_id_.has_value()) { + context_manager_.DefineLocalType(type_info.parameters[i].type, + GraphIdByTypeId(type.parameters[i]->type_id_.value())); + } + } +} + +void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { + utils::IdType value = current_value_; + + switch (node.index()) { + case 0: + // always copy, because case can not match value + value = context_manager_.ToModifiedValueCopy(value, utils::ValueType::Const); + if (!context_manager_.DefineVariable(*std::get>(node), + value)) { + error_handling::HandleRuntimeError("Can't redifine variable", base_node); + } + break; + case 1: + Visitor::Visit(*std::get>(node)); + if (!context_manager_.EqualValues(current_value_, value)) { + case_matched_ = false; + } + break; + case 2: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +// + +bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) { + if (node->name == "print") { + Visitor::Visit(node->arguments[0]); + info::builtin::Print(*ExtractInternalValue(current_value_, node->base)); + + current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (node->name == "scan") { + current_value_ = context_manager_.AddValue(info::value::InternalValue(info::builtin::Read()), + utils::ValueType::Tmp); + } else if (node->name == "random") { // TODO: different types, better random, seed, etc. + current_value_ = context_manager_.AddValue(info::value::InternalValue(rand()), + utils::ValueType::Tmp); + } else { + return false; + } + + return true; +} + +bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node, + info::type::InternalType type) { + const std::string& name = node->name; + + if (utils::IsBuiltinFunction(name)) { + std::vector arguments; + arguments.reserve(node->arguments.size()); + + if (node->prefix.has_value() && std::holds_alternative>(node->prefix.value())) { + Visitor::Visit(*std::get>(node->prefix.value())); + arguments.push_back(ExtractValue(current_value_, node->base)); + } + + for (auto& argument : node->arguments) { + Visitor::Visit(argument); + arguments.push_back(ExtractValue(current_value_, node->base)); + } + + switch (type) { + case info::type::InternalType::Float: + if (name == "show") { + try { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::to_string(*arguments[0]->GetValue().value())), + utils::ValueType::Tmp); + } catch(...) { + error_handling::HandleRuntimeError("Can't read Float", node->base); + } + } else if (name == "read") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::stod(*arguments[0]->GetValue().value())), + utils::ValueType::Tmp); + } else if (name == "<") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "zero") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(0.0), + utils::ValueType::Tmp); + } else if (name == "one") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(1.0), + utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "+=") { + *arguments[0]->GetValue().value() += *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "-=") { + *arguments[0]->GetValue().value() -= *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "*=") { + *arguments[0]->GetValue().value() *= *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "/=") { + *arguments[0]->GetValue().value() /= *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Int: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::to_string(*arguments[0]->GetValue().value())), + utils::ValueType::Tmp); + } else if (name == "read") { + try { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::stoi(*arguments[0]->GetValue().value())), + utils::ValueType::Tmp); + } catch(...) { + error_handling::HandleRuntimeError("Can't read Int", node->base); + } + } else if (name == "<") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "div") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() / *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "mod") { // TODO: better implementation of mod (read "%" specification) + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() % *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "zero") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(0), + utils::ValueType::Tmp); + } else if (name == "one") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(1), + utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "+=") { + *arguments[0]->GetValue().value() += *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "-=") { + *arguments[0]->GetValue().value() -= *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "*=") { + *arguments[0]->GetValue().value() *= *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::String: + if (name == "show") { // do not copy ?? + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "read") { // do not copy ?? + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "<") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "size") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(static_cast(arguments[0]->GetValue().value()->size())), + utils::ValueType::Tmp); + } else if (name == "at") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue((*arguments[0]->GetValue().value())[*arguments[1]->GetValue().value()]), + utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Char: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(std::string{*arguments[0]->GetValue().value()}), + utils::ValueType::Tmp); + } else if (name == "read") { + if (arguments[0]->GetValue().value()->size() != 1) { + error_handling::HandleRuntimeError("Can't read Char", node->base); + } else { + current_value_ = context_manager_.AddValue( + info::value::InternalValue((*arguments[0]->GetValue().value())[0]), + utils::ValueType::Tmp); + } + } else if (name == "<") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() < *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "==") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() == *arguments[1]->GetValue().value()), + utils::ValueType::Tmp); + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Bool: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(*arguments[0]->GetValue().value() ? "true" : "false"), + utils::ValueType::Tmp); + } else if (name == "read") { + if (*arguments[0]->GetValue().value() == "true") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(true), + utils::ValueType::Tmp); + } else if (*arguments[0]->GetValue().value() == "false") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(false), + utils::ValueType::Tmp); + } else { + error_handling::HandleRuntimeError("Can't read Bool", node->base); + } + } else if (name == "=") { + *arguments[0]->GetValue().value() = *arguments[1]->GetValue().value(); + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + case info::type::InternalType::Unit: + if (name == "show") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue("()"), + utils::ValueType::Tmp); + } else if (name == "read") { + if (*arguments[0]->GetValue().value() != "()") { + error_handling::HandleRuntimeError("Can't read Unit", node->base); + } + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else if (name == "=") { + current_value_ = context_manager_.AddValue( + info::value::InternalValue(info::value::Unit()), + utils::ValueType::Tmp); + } else { + return false; + } + break; + default: + error_handling::HandleInternalError("Unknown basic type", + "ExecuteVisitor.HandleBuiltinTypeFunctionCall", + &node->base); + break; + } + + return true; + } + + return false; +} + +} // namespace interpreter + diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp new file mode 100644 index 0000000..ba5417c --- /dev/null +++ b/src/find_symbols_visitor.cpp @@ -0,0 +1,218 @@ +#include + +// for clangd +#include "../include/error_handling.hpp" +#include "../include/find_symbols_visitor.hpp" + +namespace interpreter { + +// Sources ----------------- + +// Namespaces, partitions ----------------- + +void FindSymbolsVisitor::Visit(Namespace* node) { + if (namespace_visitor_.GetCurrentNamespace()->modifier != utils::ClassInternalsModifier::Static) { + // other type of error?? + error_handling::HandleParsingError("Can't use const /var namespace inside const / var namespace", + node->base.start_position, + node->base.end_position); + } + + namespace_visitor_.AddEnterNamespace(node->type, node->modifier, node, node->base); + + Visitor::Visit(&node->scope); + + namespace_visitor_.ExitNamespace(); +} + +// Definitions ----------------- + +// TODO: add imported symbols to symbol table (global info) +void FindSymbolsVisitor::Visit(ImportStatement* node) { + info::definition::Import info; + info.module_name = node->module_name; + info.symbols = node->symbols; + namespace_visitor_.AddImport(std::move(info), node->name); +} + +void FindSymbolsVisitor::Visit(AliasDefinitionStatement* node) { + info::definition::Type info; + + info::definition::AliasType alias_info; + + alias_info.modifier = node->modifier; + + alias_info.parameters = node->parameters; + alias_info.value.node = node->value.get(); + alias_info.node = node; + + info.type = std::move(alias_info); + + node->type_id_ = namespace_visitor_.AddType(node->type, std::move(info), node->base); + + Visitor::Visit(node->value.get()); // to visit all tree +} + +void FindSymbolsVisitor::Visit(FunctionDeclaration* node) { + info::definition::FunctionDeclaration info; + + info.parameters.resize(node->parameters.size()); + for (size_t i = 0; i < node->parameters.size(); ++i) { + Visit(node->parameters[i].get()); + info.parameters[i] = std::move(std::any_cast(current_info_)); + current_info_.reset(); + } + + info.argument_types.resize(node->type->types.size()); + for (size_t i = 0; i < node->type->types.size(); ++i) { + info.argument_types[i] = &node->type->types[i]; + } + + info.node = node; + + node->function_id_ = namespace_visitor_.AddFunctionDeclaration(node->name, std::move(info), node->base); + + Visitor::Visit(node->type.get()); // to visit all tree +} + +void FindSymbolsVisitor::Visit(FunctionDefinitionStatement* node) { + info::definition::FunctionDefinition info; + + auto definition = node->definition.get(); + + info.argument_names.resize(definition->arguments.size()); + for (size_t i = 0; i < definition->arguments.size(); ++i) { + info.argument_names[i] = definition->arguments[i]; + } + + info.node = node; + + node->function_id_ = namespace_visitor_.AddFunctionDefinition(definition->name, std::move(info), node->base); + + Visitor::Visit(definition); // to visit all tree + Visitor::Visit(node->value); // to visit all tree +} + +void FindSymbolsVisitor::Visit(TypeDefinitionStatement* node) { + info::definition::Type info; + + auto definition = node->definition.get(); + + info::definition::AnyType any_type_info; + + Visit(definition->type.get()); + any_type_info.type = std::move(std::any_cast(current_info_)); + current_info_.reset(); + + any_type_info.parameters.resize(definition->parameters.size()); + for (size_t i = 0; i < definition->parameters.size(); ++i) { + Visit(definition->parameters[i].get()); + any_type_info.parameters[i] = std::move(std::any_cast(current_info_)); + current_info_.reset(); + } + + any_type_info.node = node; + any_type_info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId(); + any_type_info.modifier = node->modifier; + + std::string type = any_type_info.type.type; + + info.type = std::move(any_type_info); + + node->type_id_ = namespace_visitor_.AddType(type, std::move(info), node->base); + + auto maybe_graph_type_vertex = namespace_visitor_.GetTypeclassGraph()->GetTypeVertex(node->definition->type->graph_id_); + + if (!maybe_graph_type_vertex.has_value()) { + error_handling::HandleInternalError("Type vertex in TypeclassGraph is not type vertex", + "FindSymbolsVisitor.FunctionDefinitionStatement", + &node->base); + } + + maybe_graph_type_vertex.value()->type_id = node->type_id_; + + // definition visited earlier + Visitor::Visit(node->value); // to visit all tree +} + +void FindSymbolsVisitor::Visit(AbstractTypeDefinitionStatement* node) { + info::definition::AbstractType info; + + Visit(node->type.get()); + info.type = std::move(std::any_cast(current_info_)); + current_info_.reset(); + + info.modifier = node->modifier; + info.node = node; + + std::string type = info.type.type; + + node->type_id_ = namespace_visitor_.AddAbstractType(type, std::move(info), node->base); +} + +void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { + info::definition::Typeclass info; + + auto definition = node->definition.get(); + + std::string& typeclass_name = definition->type.get()->type; + + info.parameters.resize(definition->parameters.size()); + for (size_t i = 0; i < definition->parameters.size(); ++i) { + Visit(definition->parameters[i].get()); + info.parameters[i] = std::move(std::any_cast(current_info_)); + current_info_.reset(); + } + + for (size_t i = 0; i < node->requirements.size(); ++i) { + namespace_visitor_.AddEnterNamespace(typeclass_name, node->requirements[i].first, std::nullopt, node->base); + Visit(node->requirements[i].second.get()); + namespace_visitor_.ExitNamespace(); + } + + info.node = node; + info.parent_namespace = namespace_visitor_.GetCurrentNamespaceId(); + + node->typeclass_id_ = namespace_visitor_.AddTypeclass(typeclass_name, std::move(info), node->base); + + // no need to visit definition->type, because it is typeclass +} + +void FindSymbolsVisitor::Visit(PartitionStatement* node) { + node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node, node->base); + + Visitor::Visit(node->value); // to visit all tree +} + +// Definition parts + +void FindSymbolsVisitor::Visit(AnyAnnotatedType* node) { + info::definition::Parameter info; + + info.type = node->type; + + info.typeclass_nodes.resize(node->typeclasses.size()); + for (size_t i = 0; i < node->typeclasses.size(); ++i) { + info.typeclass_nodes[i] = node->typeclasses[i].get(); + } + + for (auto& typeclass : node->typeclasses) { + Visitor::Visit(typeclass.get()); // to visit all tree + } + + info.node = node; + + auto maybe_typeclass_graph_id = namespace_visitor_.GetGlobalInfo()->AddAnnotatedTypeToGraph(node); // definitions and declarations should be added latter + + if (!maybe_typeclass_graph_id.has_value()) { + error_handling::HandleInternalError("Can't add annotated type to typeclass graph", + "FindSymbolsVisitor.AnyAnnotatedType", + &node->base); + } + + node->graph_id_ = maybe_typeclass_graph_id.value(); + + current_info_ = std::move(info); +} + +} // namespace interpreter diff --git a/src/global_info.cpp b/src/global_info.cpp new file mode 100644 index 0000000..7a71961 --- /dev/null +++ b/src/global_info.cpp @@ -0,0 +1,601 @@ +#include + +// for clangd +#include "../include/global_info.hpp" +#include "../include/types.hpp" +#include "../include/error_handling.hpp" + + +namespace info { + +void GlobalInfo::NamespaceVisitor::AddImport(definition::Import&& import_info, + const std::optional& name) { + if (name.has_value()) { + global_info_.usages_[name.value()] = std::move(import_info); + } else { + global_info_.imports_.push_back(std::move(import_info)); + } +} + +void GlobalInfo::NamespaceVisitor::AddEnterNamespace(const std::string& name, + utils::ClassInternalsModifier modifier, + std::optional node, + const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(name).has_value()) { + error_handling::HandleNamesError("Can't define basic type namespace", base_node); + } + + auto current_namespaces = + global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[namespace_stack_.back()]); + + utils::IdType id = 0; + + auto namespace_iter = current_namespaces->find(name); + if (namespace_iter == current_namespaces->end()) { + id = global_info_.namespaces_.size(); + (*current_namespaces)[name] = id; + global_info_.namespaces_.emplace_back(); + + global_info_.namespaces_.back().modifier = modifier; + } else { + id = namespace_iter->second; + } + + definition::Namespace* namespace_info = &global_info_.namespaces_[id]; + + if (!namespace_info->any_node.has_value()) { // ?? + namespace_info->any_node = node; + } + + namespace_info->parent_namespace = namespace_stack_.back(); + + namespace_info->type_name = name; + + namespace_stack_.push_back(id); + current_path_.push_back(name); +} + +void GlobalInfo::NamespaceVisitor::EnterNamespace(const std::string& name, + utils::ClassInternalsModifier modifier) { + for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { + auto current_namespaces = + global_info_.ChooseNamespaces(modifier, &global_info_.namespaces_[i]); + auto namespace_iter = current_namespaces->find(name); + if (namespace_iter != current_namespaces->end()) { + namespace_stack_.push_back(namespace_iter->second); + current_path_.push_back(name); + return; + } + } + + error_handling::HandleInternalError("Can't find namespace " + name, + "GlobalInfo.NamespaceVisitor.EnterNamespace", + std::nullopt); +} + +void GlobalInfo::NamespaceVisitor::ExitNamespace() { + if (namespace_stack_.size() <= 1) { + error_handling::HandleInternalError("Can't exit from global namespace", + "GlobalInfo.NamespaceVisitor.ExitNamespace", + std::nullopt); + return; + } + + namespace_stack_.pop_back(); + current_path_.pop_back(); +} + +void GlobalInfo::NamespaceVisitor::ToGlobalNamespace() { + namespace_stack_.clear(); + current_path_.clear(); + + namespace_stack_.push_back(global_info_.GlobalNamespaceId); +} + +utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDeclaration( + const std::string& name, + definition::FunctionDeclaration&& function_declaration_info, + const interpreter::tokens::BaseNode& base_node) { + utils::IdType id = 0; + + auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); + if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { + id = global_info_.functions_.size(); + global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; + global_info_.functions_.emplace_back(); + global_info_.functions_.back().argument_count = function_declaration_info.argument_types.size(); // add return type + } else { + id = function_id_iter->second; + if (global_info_.functions_[id].argument_count != function_declaration_info.argument_types.size()) { + error_handling::HandleNamesError("Function declaration: not same argument count in function definition and declaration", base_node); + } + } + + if (global_info_.functions_[id].declaration.has_value()) { + error_handling::HandleNamesError("Second function declaration", base_node); + } + global_info_.functions_[id].declaration = std::move(function_declaration_info); + + return id; +} + +utils::IdType GlobalInfo::NamespaceVisitor::AddFunctionDefinition( + const std::string& name, + definition::FunctionDefinition&& function_definition_info, + const interpreter::tokens::BaseNode& base_node) { + utils::IdType id = 0; + + auto function_id_iter = global_info_.namespaces_[namespace_stack_.back()].functions.find(name); + if (function_id_iter == global_info_.namespaces_[namespace_stack_.back()].functions.end()) { + id = global_info_.functions_.size(); + global_info_.namespaces_[namespace_stack_.back()].functions[name] = id; + global_info_.functions_.emplace_back(); + global_info_.functions_.back().argument_count = function_definition_info.argument_names.size() + 1; + } else { + id = function_id_iter->second; + if (global_info_.functions_[id].argument_count != function_definition_info.argument_names.size() + 1) { + error_handling::HandleNamesError("Function definition: not same argument count in function definition and declaration", base_node); + } + } + + if (global_info_.functions_[id].definition.has_value()) { + error_handling::HandleNamesError("Second function definition", base_node); + } + global_info_.functions_[id].definition = std::move(function_definition_info); + + return id; +} + +// TODO: internal types, etc. +// TODO: extended constructor names (point separated names) +utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, + definition::Type&& type_info, + const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(type).has_value()) { + error_handling::HandleNamesError("Can't redefine basic type", base_node); + } + + utils::IdType id = 0; + + auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type); + + if (type_id_iter == global_info_.namespaces_[namespace_stack_.back()].types.end()) { + id = global_info_.types_.size(); + global_info_.namespaces_[namespace_stack_.back()].types[type] = id; + global_info_.types_.push_back(std::move(type_info)); + } else { + error_handling::HandleNamesError("More then one type with the same name in namespace", base_node); + } + + definition::Type& moved_type_info = global_info_.types_.back(); + + if (!std::holds_alternative(moved_type_info.type)) { + error_handling::HandleInternalError("Not AnyType constructor search is not implemented yet", + "GlobalInfo.NamespaceVisitor.AddType", + &base_node); + } + + definition::AnyType& any_type_info = std::get(moved_type_info.type); + if (std::holds_alternative>(any_type_info.node->value)) { + interpreter::tokens::VariantType& variant_type_info = *std::get>(any_type_info.node->value); + for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) { + std::string constructor_name; + definition::Constructor constructor_info; + + constructor_info.type_id = id; + constructor_info.order = i; + + if (std::holds_alternative(variant_type_info.constructors[i])) { + constructor_name = std::get(variant_type_info.constructors[i]); + } else if (std::holds_alternative< + std::unique_ptr>(variant_type_info.constructors[i])) { + constructor_info.constructor_tuple_node = + std::get>(variant_type_info.constructors[i]).get(); + + auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type; + + if (maybe_constructor_name.has_value()) { + constructor_name = maybe_constructor_name.value(); + } else { + constructor_name = type; + } + } else { + error_handling::HandleInternalError("Unexprected VariantType constructor node type", + "GlobalInfo.NamespaceVisitor.AddType", + &base_node); + } + + constructor_info.name = constructor_name; + + AddConstructor(constructor_name, std::move(constructor_info), base_node); + } + } else if (std::holds_alternative>(any_type_info.node->value)) { + definition::Constructor constructor_info; + constructor_info.type_id = id; + // constructor_info.order = std::nullopt; + constructor_info.name = type; + constructor_info.constructor_tuple_node = std::get>(any_type_info.node->value).get(); + + AddConstructor(type, std::move(constructor_info), base_node); + } else { + // TODO: constructors for function types (??), array types (??), ... + error_handling::HandleInternalError("Not VariantType constructor search is not implemented yet", + "GlobalInfo.NamespaceVisitor.AddType", + &base_node); + } + + return id; +} + +// TODO: link abstract type with let definitions +utils::IdType GlobalInfo::NamespaceVisitor::AddAbstractType(const std::string& abstract_type, + definition::AbstractType&& abstract_type_info, + const interpreter::tokens::BaseNode& base_node) { + // if (type::ToInternalType(abstract_type).has_value()) { + // error_handling::HandleNamesError("Can't redefine basic type as abstract type", base_node); + // } + + if (FindAbstractType(abstract_type).has_value()) { + error_handling::HandleNamesError("More then one abstract type with the same name in namespace", base_node); + } + + utils::IdType id = global_info_.abstract_types_.size(); + global_info_.name_to_abstract_type_[abstract_type] = id; + global_info_.abstract_types_.push_back(std::move(abstract_type_info)); + + return id; +} + +// TODO: which info needed ?? +utils::IdType GlobalInfo::NamespaceVisitor::AddTypeclass(const std::string& typeclass, + definition::Typeclass&& typeclass_info, + const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(typeclass).has_value()) { + error_handling::HandleNamesError("Can't redefine basic type as typeclass", base_node); + } + + if (FindTypeclass(typeclass).has_value()) { + error_handling::HandleNamesError("More then one typeclass with the same name", base_node); + } + + utils::IdType id = global_info_.typeclasses_.size(); + global_info_.name_to_typeclass_[typeclass] = id; + global_info_.typeclasses_.push_back(std::move(typeclass_info)); + + return id; +} + +utils::IdType GlobalInfo::NamespaceVisitor::AddConstructor(const std::string& constructor, + definition::Constructor&& constructor_info, + const interpreter::tokens::BaseNode& base_node) { + if (type::ToInternalType(constructor).has_value()) { + error_handling::HandleNamesError("Can't redefine basic type as constructor", base_node); + } + + auto constructor_id_iter = global_info_.namespaces_[namespace_stack_.back()].constructors.find(constructor); + + if (constructor_id_iter != global_info_.namespaces_[namespace_stack_.back()].constructors.end()) { + error_handling::HandleNamesError("More then one constructor with the same name in namespace", base_node); + } + + utils::IdType id = global_info_.constructors_.size(); + global_info_.namespaces_[namespace_stack_.back()].constructors[constructor] = id; + global_info_.constructors_.push_back(std::move(constructor_info)); + + return id; +} + +utils::IdType GlobalInfo::NamespaceVisitor::AddPartition(const std::vector& path, + interpreter::tokens::PartitionStatement* node, + const interpreter::tokens::BaseNode& base_node) { + PartitionInfo partition; + + partition.path.reserve(current_path_.size() + path.size()); + partition.path = current_path_; + + for (auto& path_name : path) { + partition.path.push_back(path_name); + } + + partition.node = node; + + utils::IdType id = global_info_.partitions_.size(); + + global_info_.partitions_.push_back(partition); + if (!global_info_.partitions_trie_.Insert(partition.path, id)) { + error_handling::HandleNamesError("Partition with this name already exists", base_node); + } + + return id; +} + +std::optional GlobalInfo::NamespaceVisitor::FindNamespaceId(const std::optional>& path) { + return FindSomething(path, + [] (utils::IdType current_namespace) -> std::optional { + return current_namespace; + }); +} + +std::optional GlobalInfo::NamespaceVisitor::FindFunctionId( + const std::optional>& path, + const std::string& name) { + return FindSomething(path, + [name, this] (utils::IdType current_namespace) -> std::optional { + + auto function_info_iter = global_info_.namespaces_[current_namespace].functions.find(name); + if (function_info_iter == global_info_.namespaces_[current_namespace].functions.end()) { + return std::nullopt; + } + + return function_info_iter->second; + }); +} + +std::optional GlobalInfo::NamespaceVisitor::FindMethodId( + const std::optional>& path, + const std::string& type, + const std::string& name, + utils::IsConstModifier modifier) { + return GlobalInfo::NamespaceVisitor::FindSomething(path, + [type, name, modifier, this] (utils::IdType current_namespace) -> std::optional { + + + auto variable_namespace_iter = + (modifier == utils::IsConstModifier::Const + ? global_info_.namespaces_[current_namespace].const_namespaces.find(type) + : global_info_.namespaces_[current_namespace].var_namespaces.find(type)); + if (variable_namespace_iter == + (modifier == utils::IsConstModifier::Const + ? global_info_.namespaces_[current_namespace].const_namespaces.end() + : global_info_.namespaces_[current_namespace].var_namespaces.end())) { + return std::nullopt; + } + + auto method_iter = global_info_.namespaces_[variable_namespace_iter->second].functions.find(name); + if (method_iter == global_info_.namespaces_[variable_namespace_iter->second].functions.end()) { + return std::nullopt; + } + + return method_iter->second; + }); +} + +std::optional GlobalInfo::NamespaceVisitor::FindTypeId( + const std::optional>& path, + const std::string& type) { + return FindSomething(path, + [type, this] (utils::IdType current_namespace) -> std::optional { + + auto type_info_iter = global_info_.namespaces_[current_namespace].types.find(type); + if (type_info_iter == global_info_.namespaces_[current_namespace].types.end()) { + return std::nullopt; + } + + return type_info_iter->second; + }); +} + +std::optional GlobalInfo::NamespaceVisitor::FindLocalTypeId(const std::string& type) { + auto type_id_iter = global_info_.namespaces_[namespace_stack_.back()].types.find(type); + + if (type_id_iter != global_info_.namespaces_[namespace_stack_.back()].types.end()) { + return type_id_iter->second; + } + + return std::nullopt; +} + +std::optional GlobalInfo::NamespaceVisitor::FindAbstractTypeId(const std::string& abstract_type) { + auto abstract_type_id_iter = global_info_.name_to_abstract_type_.find(abstract_type); + + if (abstract_type_id_iter != global_info_.name_to_abstract_type_.end()) { + return abstract_type_id_iter->second; + } + + return std::nullopt; +} + +std::optional GlobalInfo::NamespaceVisitor::FindTypeclassId(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 GlobalInfo::NamespaceVisitor::FindConstructorId( + const std::optional>& path, + const std::string& constructor) { + return FindSomething(path, + [constructor, this] (utils::IdType current_namespace) -> std::optional { + + auto constructor_info_iter = global_info_.namespaces_[current_namespace].constructors.find(constructor); + if (constructor_info_iter == global_info_.namespaces_[current_namespace].constructors.end()) { + return std::nullopt; + } + + return constructor_info_iter->second; + }); +} + +template +std::optional GlobalInfo::NamespaceVisitor::FindSomething( + const std::optional>& path, + std::function(utils::IdType)> search_func) { + for (ssize_t i = (ssize_t)namespace_stack_.size() - 1; i >= 0; --i) { + utils::IdType current_namespace = 0; + if (path.has_value()) { + auto maybe_namespace = FindNamespaceIn(namespace_stack_[i], path.value()); + + if (!maybe_namespace.has_value()) { + continue; + } + + current_namespace = maybe_namespace.value(); + } else { + current_namespace = namespace_stack_[i]; + } + + std::optional result = search_func(current_namespace); + + if (result.has_value()) { + return result.value(); + } + } + + return std::nullopt; +} + +std::optional GlobalInfo::NamespaceVisitor::FindNamespaceIn( + utils::IdType current_namespace, + const std::vector& path) { + utils::IdType next_namespace = current_namespace; + for (auto& name : path) { + auto next_namespace_iter = global_info_.namespaces_[next_namespace].namespaces.find(name); + if (next_namespace_iter == global_info_.namespaces_[next_namespace].namespaces.end()) { + return std::nullopt; + } + next_namespace = next_namespace_iter->second; + } + + return next_namespace; +} + +// + +std::optional GlobalInfo::GetTypeNamespace(utils::IdType id, + utils::ClassInternalsModifier modifier) { + auto maybe_type_info = GetTypeInfo(id); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Only AnyType is supported now", + "GlobalInfo.GetTypeNamespace", + std::nullopt); + } + + std::string& name = maybe_type_info.value()->type.type; + + auto namespaces = ChooseNamespaces(modifier, &GetNamespaceInfo(maybe_type_info.value()->parent_namespace)); + + auto namespace_iter = namespaces->find(name); + + return namespace_iter == namespaces->end() ? std::optional(std::nullopt) : &GetNamespaceInfo(namespace_iter->second); +} + +std::unordered_map* + GlobalInfo::ChooseNamespaces(utils::ClassInternalsModifier modifier, + definition::Namespace* current_namespace) { + std::unordered_map* current_namespaces = nullptr; + switch (modifier) { + case utils::ClassInternalsModifier::Const: + current_namespaces = ¤t_namespace->const_namespaces; + break; + case utils::ClassInternalsModifier::Var: + current_namespaces = ¤t_namespace->var_namespaces; + break; + case utils::ClassInternalsModifier::Static: + current_namespaces = ¤t_namespace->namespaces; + break; + } + + return current_namespaces; +} + +std::optional GlobalInfo::AddTypeclassToGraph(utils::IdType typeclass) { + definition::Typeclass* typeclass_info = &GetTypeclassInfo(typeclass); + definition::Namespace* parent_namespace = &GetNamespaceInfo(typeclass_info->parent_namespace); + + std::string name = typeclass_info->node->definition->type->type; + interpreter::tokens::BaseNode* base_node = &typeclass_info->node->base; + std::vector dependencies; + std::vector>> function_declarations; + std::vector> function_definitions; + + for (auto& dependency_node : typeclass_info->node->definition->type->typeclasses) { + std::string dependency = dependency_node->typeclass; + if (dependency_node->parameters.size() > 0) { + error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", + "GlobalInfo.AddTypeclassToGraph", + std::nullopt); + } + dependencies.push_back(dependency); + } + + auto namespace_iter = parent_namespace->namespaces.find(name); + if (namespace_iter != parent_namespace->namespaces.end()) { + CollectFunctionInfo(namespace_iter->second, + utils::ClassInternalsModifier::Static, + function_declarations, + function_definitions); + } + + auto const_namespace_iter = parent_namespace->const_namespaces.find(name); + if (const_namespace_iter != parent_namespace->const_namespaces.end()) { + CollectFunctionInfo(const_namespace_iter->second, + utils::ClassInternalsModifier::Const, + function_declarations, + function_definitions); + } + + auto var_namespace_iter = parent_namespace->var_namespaces.find(name); + if (var_namespace_iter != parent_namespace->var_namespaces.end()) { + CollectFunctionInfo(var_namespace_iter->second, + utils::ClassInternalsModifier::Var, + function_declarations, + function_definitions); + } + + return typeclass_graph_.AddVertex(name, + dependencies, + function_declarations, + function_definitions, + base_node, + TypeclassGraph::Modifier::Typeclass); +} + +std::optional GlobalInfo::AddAnnotatedTypeToGraph(interpreter::tokens::AnnotatedType* node) { + std::string name = node->type; + interpreter::tokens::BaseNode* base_node = &node->base; + std::vector dependencies; + + for (auto& dependency_node : node->typeclasses) { + std::string dependency = dependency_node->typeclass; + if (dependency_node->parameters.size() > 0) { + error_handling::HandleInternalError("Paramtrized typeclass requirements are not implemented yet", + "GlobalInfo.AddAnnotatedTypeToGraph", + &node->base); + } + dependencies.push_back(dependency); + } + + return typeclass_graph_.AddVertex(name, + dependencies, + {}, + {}, + base_node, + TypeclassGraph::Modifier::Type); +} + +void GlobalInfo::CollectFunctionInfo( + utils::IdType current_namespace, + utils::ClassInternalsModifier modifier, + std::vector>>& function_declarations, + std::vector>& function_definitions) { + for (auto& function : GetNamespaceInfo(current_namespace).functions) { + definition::Function function_info = GetFunctionInfo(function.second); + + if (function_info.declaration.has_value()) { + function_declarations.push_back( + {function.first, + {modifier, function_info.declaration.value().node}}); + } + + if (function_info.definition.has_value()) { + function_definitions.push_back({function.first, function_info.definition.value().node}); + } + } +} + +} // namespace info diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp new file mode 100644 index 0000000..37454fc --- /dev/null +++ b/src/link_symbols_visitor.cpp @@ -0,0 +1,218 @@ +#include +#include + +// for clangd +#include "../include/link_symbols_visitor.hpp" +#include "../include/error_handling.hpp" +#include "../include/types.hpp" + +namespace interpreter { + +// Namespaces, partitions ----------------- + +void LinkSymbolsVisitor::Visit(Namespace* node) { + // Visitor::Visit(&node->type); // not needed + + std::optional maybe_type = namespace_visitor_.FindLocalTypeId(node->type); + + std::optional maybe_typeclass; + if (namespace_visitor_.IsInGlobalNamespace()) { + maybe_typeclass = namespace_visitor_.FindTypeclassId(node->type); + } + + if (maybe_type.has_value() && maybe_typeclass.has_value()) { + error_handling::HandleNamesError("Ambigious namespace name (typeclass or type)", node->base); + } + + if (maybe_type.has_value()) { + node->link_type_id_ = maybe_type.value(); + } + + if (maybe_typeclass.has_value()) { + node->link_typeclass_id_ = maybe_typeclass.value(); + if (!namespace_visitor_.IsInGlobalNamespace()) { + // other type of error?? + error_handling::HandleParsingError("Can't use typeclass namespace in other namespace", + node->base.start_position, + node->base.end_position); + } + } + + namespace_visitor_.EnterNamespace(node->type, node->modifier); + + Visitor::Visit(&node->scope); + + namespace_visitor_.ExitNamespace(); +} + +// Definitions ----------------- + +void LinkSymbolsVisitor::Visit(TypeDefinitionStatement* node) { + Visitor::Visit(node->definition.get()); + Visitor::Visit(node->value); + + utils::IdType graph_id = node->definition->type->graph_id_; + + AddTypeFunctionsToTypeclassGraph(node->type_id_, + graph_id, + utils::ClassInternalsModifier::Static, + node->base); + + AddTypeFunctionsToTypeclassGraph(node->type_id_, + graph_id, + utils::ClassInternalsModifier::Const, + node->base); + + AddTypeFunctionsToTypeclassGraph(node->type_id_, + graph_id, + utils::ClassInternalsModifier::Var, + node->base); +} + +void LinkSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) { + Visitor::Visit(node->definition.get()); + for (auto& function_requirement : node->requirements) { + namespace_visitor_.EnterNamespace(node->definition->type->type, function_requirement.first); + Visitor::Visit(function_requirement.second.get()); + namespace_visitor_.ExitNamespace(); + } + + auto maybe_graph_id = global_info_.AddTypeclassToGraph(node->typeclass_id_); + if (!maybe_graph_id.has_value()) { + error_handling::HandleNamesError("Can't add typeclass to graph", node->base); + } + global_info_.GetTypeclassInfo(node->typeclass_id_).graph_id_ = maybe_graph_id.value(); +} + +// Type, typeclass, etc. ----------------- + +// Type + +void LinkSymbolsVisitor::Visit(TypeExpression* node) { + std::vector path; + path.reserve(node->path.size()); + + for (auto& path_type : node->path) { + path.push_back(path_type.type); + } + + node->type_id_ = namespace_visitor_.FindTypeId(path, node->type.type); + node->constructor_id_ = namespace_visitor_.FindConstructorId(path, node->type.type); + + // internal type + if (info::type::ToInternalType(node->type.type).has_value()) { + if (!node->path.empty()) { + error_handling::HandleNamesError("Internal type is not in namespace", node->base); + } + + if (!node->type.parameters.empty()) { + error_handling::HandleNamesError("Can't parametrize internal type", node->base); + } + return; + } + + if (!node->type_id_.has_value() && !node->constructor_id_.has_value()) { + // check made in typecheck visitor + return; + } + + if (node->constructor_id_.has_value()) { + utils::IdType constructor_type_id = global_info_.GetConstructorInfo(node->constructor_id_.value()).type_id; + + if (node->type_id_.has_value() && node->type_id_.value() != constructor_type_id) { + error_handling::HandleNamesError("Contructor and type with same name have different types", node->base); + } + + node->type_id_ = constructor_type_id; + } + + if (node->type_id_.has_value()) { + node->type.type_id_ = node->type_id_.value(); + } + + std::optional maybe_type_namespace = namespace_visitor_.FindNamespace(path); + if (maybe_type_namespace.has_value()) { + info::definition::Namespace* type_namespace = maybe_type_namespace.value(); + + for (ssize_t i = (ssize_t)node->path.size(); i >= 0; --i) { + info::definition::Namespace* parent_namespace = &global_info_.GetNamespaceInfo(type_namespace->parent_namespace); + + auto type_iter = parent_namespace->types.find(type_namespace->type_name); + if (type_iter != parent_namespace->types.end()) { + node->path[i].type_id_ = type_iter->second; + } + + type_namespace = parent_namespace; + } + } +} + +// Typeclass + +void LinkSymbolsVisitor::Visit(ParametrizedTypeclass* node) { + std::optional maybe_typeclass = namespace_visitor_.FindTypeclassId(node->typeclass); + + if (maybe_typeclass.has_value()) { + node->typeclass_id_ = maybe_typeclass.value(); + } else { + error_handling::HandleNamesError("Typeclass not found", node->base); + } + + if (node->parameters.size() > 0) { + error_handling::HandleNamesError("Parametrized typeclasses not implemented yet", node->base); + } +} + +// + +void LinkSymbolsVisitor::AddTypeFunctionsToTypeclassGraph(utils::IdType type_id, + utils::IdType graph_id, + utils::ClassInternalsModifier namespace_modifier, + const BaseNode& base_node) { + auto maybe_type_graph_info = typeclass_graph_.GetTypeVertex(graph_id); + if (!maybe_type_graph_info.has_value()) { + error_handling::HandleInternalError("Type in typeclass graph is not marked as type", + "LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph", + &base_node); + } + auto type_graph_info = maybe_type_graph_info.value(); + + auto maybe_namespace = + global_info_.GetTypeNamespace(type_id, namespace_modifier); + + if (maybe_namespace.has_value()) { + for (auto& function : maybe_namespace.value()->functions) { + auto function_info = global_info_.GetFunctionInfo(function.second); + + auto function_graph_iter = type_graph_info->functions.find(function.first); + if (function_graph_iter == type_graph_info->functions.end()) { + info::TypeclassGraph::FunctionInfo function_graph_info; + + // can be found after graph calculation + if (function_info.declaration.has_value()) { + function_graph_info.declaration = function_info.declaration.value().node; + } + + // can be found after graph calculation + if (function_info.definition.has_value()) { + function_graph_info.definition = function_info.definition.value().node; + function_graph_info.is_defined_in_owner = true; + } + + function_graph_info.modifier = namespace_modifier; + + type_graph_info->functions[function.first] = function_graph_info; + } else { + if (namespace_modifier != function_graph_iter->second.modifier) { + error_handling::HandleTypecheckError("Type function \"" + function.first + "\" has definitions / declarations with different modifiers (static / const /var)", base_node); + } + + error_handling::HandleInternalError("This code should be unreachable", + "LinkSymbolsVisitor.AddTypeFunctionsToTypeclassGraph", + &base_node); + } + } + } +} + +} // namespace interpreter diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6b4a7d0 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,85 @@ +#include +#include +#include + +// for clangd +#include "../include/parse_tree.hpp" +#include "../include/global_info.hpp" +#include "../include/interpreter_tree.hpp" +#include "../include/build_visitor.hpp" +#include "../include/print_visitor.hpp" +#include "../include/find_symbols_visitor.hpp" +#include "../include/link_symbols_visitor.hpp" +#include "../include/type_check_visitor.hpp" +#include "../include/typed_print_visitor.hpp" +#include "../include/execute_visitor.hpp" +#include "../include/error_handling.hpp" + +int main(int argc, char** argv) { // TODO, only test version + if (argc < 2 || argc > 2) { + std::cout << "Wrong argument count (provide one argument - source file)\n"; + return 0; + } + + std::string filename = argv[1]; + + std::ifstream in; + in.open(filename); // TODO handle errors + + std::stringstream source_stream; + + source_stream << in.rdbuf(); + + in.close(); + + std::string source = source_stream.str(); + + parser::ParseTree parse_tree(source); + + if (!parse_tree.IsProperlyParsed()) { + error_handling::HandleParsingError("There are some parsing errors in file", {0, 0}, {0, 0}); + } + + std::unique_ptr source_file = + std::make_unique(); + + info::GlobalInfo global_info; + info::ContextManager type_context_manager; + info::ContextManager context_manager; + + interpreter::BuildVisitor build_visitor(parse_tree); + // interpreter::PrintVisitor print_visitor(std::cout); + interpreter::FindSymbolsVisitor find_symbols_visitor(global_info); + interpreter::LinkSymbolsVisitor link_symbols_visitor(global_info); + interpreter::TypeCheckVisitor type_check_visitor(global_info, type_context_manager); + // interpreter::TypedPrintVisitor typed_print_visitor(std::cout, type_context_manager); + + build_visitor.VisitSourceFile(source_file.get()); + + // std::cout << "\n---------------------------------- Untyped -------------------------------------\n\n"; + // print_visitor.VisitSourceFile(source_file.get()); + + find_symbols_visitor.VisitSourceFile(source_file.get()); + link_symbols_visitor.VisitSourceFile(source_file.get()); + type_check_visitor.VisitSourceFile(source_file.get()); + + std::optional maybe_main_partition_id = global_info.FindPartition({"main"}); + + if (!maybe_main_partition_id.has_value()) { + error_handling::HandleGeneralError("No main partition found"); + } + + const info::GlobalInfo::PartitionInfo& main_partition = + global_info.GetPartitionInfo(maybe_main_partition_id.value()); + + std::cout << "\n---------------------------------- Execution -------------------------------------\n\n"; + + interpreter::ExecuteVisitor execute_visitor(global_info, + type_context_manager, + context_manager); + + execute_visitor.ExecutePartition(main_partition.node); + + // std::cout << "\n---------------------------------- Typed -------------------------------------\n\n"; + // typed_print_visitor.VisitSourceFile(source_file.get()); +} diff --git a/src/print_visitor.cpp b/src/print_visitor.cpp new file mode 100644 index 0000000..077d233 --- /dev/null +++ b/src/print_visitor.cpp @@ -0,0 +1,746 @@ +// for clangd +#include "../include/print_visitor.hpp" + +namespace interpreter { + +// Sources ----------------- + +void PrintVisitor::Visit(SourceFile* node) { + out_ << "[SourceFile] (\n\n"; + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + out_ << "\n)\n"; +} + +// Namespaces, partitions ----------------- + +void PrintVisitor::Visit(NamespaceSources* node) { + out_ << "[NamespaceSources](\n"; + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + out_ << ")\n"; +} + +void PrintVisitor::Visit(Namespace* node) { + out_ << "[Namespace] "; + switch (node->modifier) { + case utils::ClassInternalsModifier::Const: + out_ << "const "; + break; + case utils::ClassInternalsModifier::Var: + out_ << "var "; + break; + case utils::ClassInternalsModifier::Static: + break; + } + Visit(&node->type); + out_ << "{\n"; + Visit(&node->scope); + out_ << "}\n"; +} + +// Definitions ----------------- + +void PrintVisitor::Visit(ImportStatement* node) { + if (node->name.has_value()) { + out_ << "[Use " << node->name.value() << "] = "; + } + out_ << "[Import " << node->module_name << "]"; + if (!node->symbols.empty()) { + out_ << " (\n"; + for (auto& symbol : node->symbols) { + Visit(&symbol); + out_ << '\n'; + } + out_ << ')'; + } + out_ << '\n'; +} + +void PrintVisitor::Visit(AliasDefinitionStatement* node) { + out_ << "[Alias "; + switch (node->modifier) { + case utils::AliasModifier::Alias: + out_ << "alias"; + break; + case utils::AliasModifier::Type: + out_ << "type"; + break; + case utils::AliasModifier::Let: + out_ << "let"; + break; + } + out_ << ' '; + Visit(&node->type); + out_ << "] = ("; + Visit(node->value.get()); + out_ << ")\n"; +} + +void PrintVisitor::Visit(VariableDefinitionStatement* node) { + out_ << "[Variable "; + switch (node->modifier) { + case utils::IsConstModifier::Const: + out_ << "const"; + break; + case utils::IsConstModifier::Var: + out_ << "var"; + break; + } + out_ << ' '; + Visitor::Visit(node->name); + out_ << "] = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +void PrintVisitor::Visit(FunctionDeclaration* node) { + out_ << "[FunctionDeclaration "; + if (node->is_in_interface) { + out_ << "interface "; + } + Visit(&node->name); + out_ << "] ("; + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + out_ << ") : ("; + Visit(node->type.get()); + out_ << ")\n"; +} + +void PrintVisitor::Visit(FunctionDefinitionStatement* node) { + out_ << "[Function] ("; + Visit(node->definition.get()); + out_ << ") = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +void PrintVisitor::Visit(TypeDefinitionStatement* node) { + out_ << "[Type "; + switch (node->modifier) { + case utils::ClassModifier::Struct: + out_ << "struct"; + break; + case utils::ClassModifier::Class: + out_ << "class"; + break; + } + if (node->is_in_interface) { + out_ << " interface"; + } + out_ << "] ("; + Visit(node->definition.get()); + out_ << ") = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +void PrintVisitor::Visit(AbstractTypeDefinitionStatement* node) { + out_ << "[AbstractType "; + switch (node->modifier) { + case utils::AbstractTypeModifier::Basic: + out_ << "basic"; + break; + case utils::AbstractTypeModifier::Abstract: + out_ << "abstract"; + break; + } + out_ << "] ("; + Visit(node->type.get()); + out_ << ")\n"; +} + +void PrintVisitor::Visit(TypeclassDefinitionStatement* node) { + out_ << "[Typeclass] ("; + Visit(node->definition.get()); + if (!node->requirements.empty()) { + out_ << ") : (\n"; + } + for (auto& requirement : node->requirements) { + out_ << "& "; + switch (requirement.first) { + case utils::ClassInternalsModifier::Const: + out_ << "const "; + break; + case utils::ClassInternalsModifier::Var: + out_ << "var "; + break; + case utils::ClassInternalsModifier::Static: + break; + } + Visit(requirement.second.get()); + out_ << "\n"; + } + out_ << ")\n"; +} + +void PrintVisitor::Visit(PartitionStatement* node) { + out_ << "[Partition "; + switch (node->modifier) { + case utils::PartitionModifier::Exec: + out_ << "exec "; + break; + case utils::PartitionModifier::Test: + out_ << "test "; + break; + } + Visit(&node->name); + out_ << "] = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +// Definition parts + +void PrintVisitor::Visit(FunctionDefinition* node) { + out_ << "[FunctionDefinition "; + Visit(&node->name); + out_ << "]"; + if (!node->arguments.empty()) { + out_ << " : ("; + for (auto& argument : node->arguments) { + Visit(&argument); + } + out_ << ')'; + } + out_ << ' '; +} + +void PrintVisitor::Visit(TypeDefinition* node) { + out_ << "[TypeDefinition] ("; + Visit(node->type.get()); + out_ << ')'; + if (!node->parameters.empty()) { + out_ << '('; + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + out_ << ')'; + } + out_ << ' '; +} + +void PrintVisitor::Visit(AnyAnnotatedType* node) { + out_ << "[Annotated (Abstract) Type "; + Visit(&node->type); + out_ << ']'; + if (!node->typeclasses.empty()) { + out_ << " ("; + for (auto& typeclass : node->typeclasses) { + Visit(typeclass.get()); + } + out_ << ')'; + } + out_ << ' '; +} + +// Flow control ----------------- + +void PrintVisitor::Visit(TypeConstructorPatternParameter* node) { + out_ << "[TypeConstructorPatternParameter "; + if (node->name.has_value()) { + Visit(&node->name.value()); + out_ << " = "; + } + Visitor::Visit(node->value); + out_ << "]"; +} + +void PrintVisitor::Visit(TypeConstructorPattern* node) { + out_ << "[TypeConstructorPattern "; + Visit(node->constructor.get()); + out_ << "]\n("; + + bool is_first = true; + for (auto& parameter : node->parameters) { + if (!is_first) { + out_ << ")\n"; + } + is_first = false; + out_ << '('; + Visit(¶meter); + } + out_ << ")\n"; +} + +void PrintVisitor::Visit(MatchCase* node) { + out_ << "[MatchCase | "; + Visitor::Visit(node->value); + if (node->condition.has_value()) { + out_ << " ? "; + Visitor::Visit(node->condition.value()); + } + if (node->statement.has_value()) { + out_ << " -> "; + Visitor::Visit(node->statement.value()); + } + out_ << "]\n"; +} + +void PrintVisitor::Visit(Match* node) { + out_ << "[Match"; + if (node->is_consuming_value) { + out_ << " <- "; + } + out_ << "] ("; + Visitor::Visit(node->value); + out_ << ") [with] (\n"; + for (auto& match_case : node->matches) { + Visit(&match_case); + } + out_ << ")\n"; +} + +void PrintVisitor::Visit(Condition* node) { + out_ << "[If] ("; + Visitor::Visit(node->conditions[0]); + out_ << ") [then] (\n"; + Visitor::Visit(node->statements[0]); + out_ << ')'; + for (size_t i = 1; i < node->conditions.size(); ++i) { + out_ << " [elif] ("; + Visitor::Visit(node->conditions[i]); + out_ << ") [then] (\n"; + Visitor::Visit(node->statements[i]); + out_ << ')'; + } + if (node->statements.size() > node->conditions.size()) { + out_ << " [else] (\n"; + Visitor::Visit(node->statements[node->conditions.size()]); + out_ << ')'; + } + out_ << '\n'; +} + +void PrintVisitor::Visit(DoWhileLoop* node) { + out_ << "[Do] (\n"; + Visitor::Visit(node->statement); + out_ << ") [while] ("; + Visitor::Visit(node->condition); + out_ << ")\n"; +} + +void PrintVisitor::Visit(WhileLoop* node) { + out_ << "[While] ("; + Visitor::Visit(node->condition); + out_ << ") [do] (\n"; + Visitor::Visit(node->statement); + out_ << ")\n"; +} +void PrintVisitor::Visit(ForLoop* node) { + out_ << "[For "; + switch (node->variable_modifier) { + case utils::IsConstModifier::Const: + break; + case utils::IsConstModifier::Var: + out_ << "var"; + break; + } + out_ << "] ("; + Visitor::Visit(node->variable); + out_ << ") [in] ("; + Visitor::Visit(node->interval); + out_ << ") [do] (\n"; + Visitor::Visit(node->statement); + out_ << ")\n"; +} + +void PrintVisitor::Visit(LoopLoop* node) { + out_ << "[Loop] (\n"; + Visitor::Visit(node->statement); + out_ << ")\n"; +} + +// Statements, expressions, blocks, etc. ----------------- + +void PrintVisitor::Visit(Block* node) { + out_ << "[Block] {\n"; + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + out_ << "}\n"; +} + +void PrintVisitor::Visit(ScopedStatement* node) { + out_ << "[Scoped] ( "; + Visitor::Visit(node->statement); + out_ << ")\n"; +} + +void PrintVisitor::Visit(LoopControlExpression& node) { // enum + switch (node) { + case LoopControlExpression::Break: + out_ << "[Break]\n"; + break; + case LoopControlExpression::Continue: + out_ << "[Continue]\n"; + break; + } +} + +// Operators + +void PrintVisitor::Visit(ReferenceExpression* node) { + out_ << "[ReferenceExpression "; + switch (node->reference) { + case utils::ReferenceModifier::Reference: + out_ << '^'; + break; + case utils::ReferenceModifier::UniqueReference: + out_ << '@'; + break; + case utils::ReferenceModifier::Dereference: + out_ << '~'; + break; + } + out_ << "] ("; + Visit(node->expression.get()); + out_ << ')'; +} + +void PrintVisitor::Visit(AccessExpression* node) { + out_ << "[AccessExpression] ("; + Visit(node->name.get()); + out_ << ") ` ("; + Visitor::Visit(node->id); + out_ << ')'; +} + +// Other Expressions + +void PrintVisitor::Visit(FunctionCallExpression* node) { + out_ << "[FunctionCall "; + + if (node->is_binary_operator_expression) { + out_ << "(binary operation) "; + } + + if (node->prefix.has_value()) { + out_ << '('; + if (std::holds_alternative>(node->prefix.value())) { + Visitor::Visit(*std::get>(node->prefix.value())); + } else if (std::holds_alternative>(node->prefix.value())) { + Visit(std::get>(node->prefix.value()).get()); + } else { + // error + } + out_ << ")."; + } + + Visit(&node->name); + + out_ << "] ("; + + bool is_first = true; + for (auto& parameter : node->parameters) { + if (!is_first) { + out_ << ", "; + } + is_first = false; + + Visit(parameter.get()); + } + + out_ << ") : ("; + + is_first = true; + for (auto& argument : node->arguments) { + if (!is_first) { + out_ << ", "; + } + is_first = false; + + Visitor::Visit(argument); + } + out_ << ")"; +} + +void PrintVisitor::Visit(TupleExpression* node) { + out_ << "[TupleExpression] ("; + for (auto& expression : node->expressions) { + out_ << "&"; + Visitor::Visit(expression); + } + out_ << ")"; +} + +void PrintVisitor::Visit(VariantExpression* node) { + out_ << "[VariantExpression] ("; + for (auto& expression : node->expressions) { + out_ << "|"; + Visitor::Visit(expression); + } + out_ << ")"; +} + +void PrintVisitor::Visit(ReturnExpression* node) { + if (node->is_from_definition) { + out_ << "[Return] ("; + } else { + out_ << "[Bring] ("; + } + + Visitor::Visit(node->expression); + out_ << ")\n"; +} + +void PrintVisitor::Visit(TypeConstructorParameter* node) { + out_ << "[TypeConstructorParameter "; + if (node->name.has_value()) { + Visit(&node->name.value()); + switch (node->asignment_modifier.value()) { + case utils::AssignmentModifier::Assign: + out_ << " = "; + break; + case utils::AssignmentModifier::Move: + out_ << " <- "; + break; + } + } + Visitor::Visit(node->value); + out_ << "]"; +} + +void PrintVisitor::Visit(TypeConstructor* node) { + out_ << "[TypeConstructor "; + Visit(node->constructor.get()); + out_ << "]\n("; + + bool is_first = true; + for (auto& parameter : node->parameters) { + if (!is_first) { + out_ << ")\n"; + } + is_first = false; + out_ << '('; + Visit(¶meter); + } + out_ << ")\n"; +} + +void PrintVisitor::Visit(LambdaFunction* node) { + out_ << "[LambdaFunction] ("; + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + if (!node->parameters.empty()) { + out_ << ") : ("; + } + for (auto& argument : node->arguments) { + Visit(&argument); + } + out_ << ") -> (\n"; + Visitor::Visit(node->expression); + out_ << ")\n"; +} + +void PrintVisitor::Visit(ArrayExpression* node) { + out_ << "[ArrayExpression] ( ,"; + for (auto& element : node->elements) { + Visitor::Visit(element); + out_ << " ,"; + } + out_ << ")"; +} + +// Name + +void PrintVisitor::Visit(PartitionName* node) { + out_ << "[PartitionName] ("; + for (size_t i = 0; i < node->path.size(); ++i) { + Visit(&node->path[i]); + if (i + 1 < node->path.size()) { + out_ << "::"; + } + } + out_ << ')'; +} + +void PrintVisitor::Visit(NameExpression* node) { + out_ << "[NameExpression] ("; + for (size_t i = 0; i < node->names.size(); ++i) { + Visit(&node->names[i]); + if (i + 1 < node->names.size()) { + out_ << "::"; + } + } + out_ << ')'; +} + +void PrintVisitor::Visit(TupleName* node) { + out_ << "[TupleName] ("; + for (auto& name : node->names) { + out_ << "& "; + Visitor::Visit(name); + } + out_ << ')'; +} + +void PrintVisitor::Visit(VariantName* node) { + out_ << "[VariantName] ("; + for (auto& name : node->names) { + out_ << "| "; + Visitor::Visit(name); + } + out_ << ')'; +} + +void PrintVisitor::Visit(AnnotatedName* node) { + out_ << "[AnnotatedName "; + Visit(&node->name); + out_ << ']'; + if (node->type.has_value()) { + out_ << " : ("; + Visitor::Visit(node->type.value()); + out_ << ')'; + } +} + +// Type, typeclass, etc. ----------------- + +// Type + +void PrintVisitor::Visit(FunctionType* node) { + out_ << "[FunctionType] ("; + bool is_first = true; + for (auto& type : node->types) { + if (!is_first || node->types.size() == 1) { + out_ << " -> "; + } + is_first = false; + Visitor::Visit(type); + } + out_ << ')'; +} + +void PrintVisitor::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_ << " : "; + } + Visit(entity.second.get()); + } + out_ << ')'; +} + +void PrintVisitor::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 PrintVisitor::Visit(TypeExpression* node) { + out_ << "[TypeExpression "; + + if (node->array_size.has_value()) { + out_ << "[array size: " << node->array_size.value() << ']'; + } + + out_ << "] ("; + for (auto& type : node->path) { + Visit(&type); + out_ << "::"; + } + Visit(&node->type); + out_ << ')'; +} + +void PrintVisitor::Visit(ExtendedScopedAnyType* node) { + out_ << "[ExtendedScopedAnyType "; + for (auto& reference : node->references) { + switch (reference) { + case utils::ReferenceModifier::Reference: + out_ << '^'; + break; + case utils::ReferenceModifier::UniqueReference: + out_ << '@'; + break; + case utils::ReferenceModifier::Dereference: + out_ << '~'; + break; + } + } + out_ << "] ("; + Visitor::Visit(node->type); + out_ << ')'; +} + +// Typeclass + +void PrintVisitor::Visit(ParametrizedTypeclass* node) { + out_ << "[ParametrizedTypeclass] ("; + Visit(&node->typeclass); + for (auto& parameter : node->parameters) { + out_ << ' '; + Visit(parameter.get()); + } + out_ << ')'; +} + +// Typeclass & Type ----------------- + +void PrintVisitor::Visit(ParametrizedType* node) { + out_ << "[ParametrizedType] ("; + Visit(&node->type); + for (auto& parameter : node->parameters) { + out_ << ' '; + Visit(parameter.get()); + } + out_ << ')'; +} + +// Identifiers, constants, etc. ----------------- + +void PrintVisitor::Visit(std::string* node) { // std::string + out_ << "[Identifier " << *node << "] "; +} + +void PrintVisitor::Visit(FloatNumberLiteral* node) { + out_ << "[FloatNumber " << node->value << "] "; +} + +void PrintVisitor::Visit(NumberLiteral* node) { + out_ << "[Number " << node->value << "] "; +} + +void PrintVisitor::Visit(StringLiteral* node) { + out_ << "[String " << node->value << "] "; +} + +void PrintVisitor::Visit(CharLiteral* node) { + out_ << "[Char " << node->value << "] "; +} + +void PrintVisitor::Visit(UnitLiteral*) { + out_ << "[Unit ()] "; +} + +void PrintVisitor::Visit(BoolLiteral* node) { + out_ << "[Bool " << (node->value ? "true" : "false") << "] "; +} + +} // namespace interpreter diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp new file mode 100644 index 0000000..74087e7 --- /dev/null +++ b/src/type_check_visitor.cpp @@ -0,0 +1,1685 @@ +#include +#include +#include +#include +#include +#include + +// for clangd +#include "../include/type_check_visitor.hpp" +#include "../include/error_handling.hpp" + +namespace interpreter { + +// Sources ----------------- + +void TypeCheckVisitor::Visit(SourceFile* node) { + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + node->base.type_ = current_type_; +} + +// Namespaces, partitions ----------------- + +void TypeCheckVisitor::Visit(NamespaceSources* node) { + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(Namespace* node) { + context_manager_.EnterContext(); + + if (node->link_typeclass_id_.has_value()) { + utils::IdType graph_id = global_info_.GetTypeclassInfo(node->link_typeclass_id_.value()).graph_id_; + + utils::IdType abstract_type = AddGraphIdLocalAbstractTypes(graph_id); + abstract_type = context_manager_.ToModifiedValue(abstract_type, + ClassInternalsModifierToValueType(node->modifier)); + + if (node->modifier != utils::ClassInternalsModifier::Static) { + context_manager_.DefineVariable(utils::ClassInternalVarName, + abstract_type); + } + + AddGraphIdLocalAbstractTypes(graph_id); + } else if (node->link_type_id_.has_value()) { + auto maybe_type_info = global_info_.GetTypeInfo(node->link_type_id_.value()); + + if (!maybe_type_info.has_value()) { + error_handling::HandleTypecheckError("Namespace type is not AnyType", node->base); + } + + info::definition::AnyType* type_info = maybe_type_info.value(); + + Visitor::Visit(type_info->node->value); + utils::IdType type = context_manager_.AddValue( + info::type::DefinedType(node->link_type_id_.value(), + current_type_, + type_info->modifier, + context_manager_.GetValueManager()), + ClassInternalsModifierToValueType(node->modifier)); + + if (node->modifier != utils::ClassInternalsModifier::Static) { + context_manager_.DefineVariable(utils::ClassInternalVarName, type); + } + + type = context_manager_.ToModifiedValue(type, utils::ValueType::Tmp); + AddGraphIdLocalTypes(type_info->type.node->graph_id_, type); + + if (type_namespaces_.count(node->link_type_id_.value()) != 0) { + error_handling::HandleTypecheckError("Namespaces of one type are one in another", node->base); + } + type_namespaces_.insert(node->link_type_id_.value()); + } + + namespace_visitor_.EnterNamespace(node->type, node->modifier); + + Visit(&node->scope); + + namespace_visitor_.ExitNamespace(); + context_manager_.ExitContext(); + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + if (node->link_type_id_.has_value()) { + type_namespaces_.erase(node->link_type_id_.value()); + } + + node->base.type_ = current_type_; +} + +// Definitions ----------------- + +void TypeCheckVisitor::Visit(ImportStatement*) {} + +// TODO +void TypeCheckVisitor::Visit(AliasDefinitionStatement* node) { + error_handling::HandleInternalError("Unimplemented", + "TypeCheckVisitor.AliasDefinitionStatement", + &node->base); +} + +// TODO: move, etc. +void TypeCheckVisitor::Visit(VariableDefinitionStatement* node) { + is_in_statement_ = true; + + Visitor::Visit(node->value); + // current_type from value automatically passed to name definitions + + is_const_definition_ = node->modifier; + Visitor::Visit(node->name); + is_const_definition_ = std::nullopt; + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + is_in_statement_ = false; + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(FunctionDeclaration* node) { // function declaration check needed ?? + bool was_in_statement = is_in_statement_; + is_in_statement_ = true; + + if (!was_in_statement) { + if (namespace_visitor_.GetCurrentNamespaceTypeclassId().has_value()) { + error_handling::HandleTypecheckError("Can't declare functions in typeclass namespace", node->base); + } + if (typeclass_graph_.FindFunctionTypeclass(node->name).has_value()) { + error_handling::HandleTypecheckError("Can't redeclare functions, that are declared as typeclass functions", node->base); + } + } + + context_manager_.EnterContext(); + for (auto& parameter : node->parameters) { + current_type_ = context_manager_.AddValue( + info::type::AbstractType(utils::AbstractTypeModifier::Abstract, + parameter->graph_id_, + typeclass_graph_), + utils::ValueType::Tmp); + context_manager_.DefineLocalType(parameter->type, current_type_); + } + Visit(node->type.get()); + context_manager_.ExitContext(); + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + if (!was_in_statement) { + is_in_statement_ = false; + } + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { + is_in_statement_ = true; + + std::string& function_name = node->definition->name; + + info::definition::Function& function_info = global_info_.GetFunctionInfo(node->function_id_); + + interpreter::tokens::FunctionDeclaration* declaration = nullptr; + if (function_info.declaration.has_value()) { + declaration = function_info.declaration.value().node; + } else { + auto maybe_typeclass_graph_id = typeclass_graph_.FindFunctionTypeclass(function_name); + + if (!maybe_typeclass_graph_id.has_value()) { + error_handling::HandleTypecheckError("Function defined, but not declared", node->base); + } + + auto maybe_curent_type = namespace_visitor_.GetCurrentNamespaceType(); // TODO: aliases + auto maybe_current_typeclass = namespace_visitor_.GetCurrentNamespaceTypeclass(); + + if (maybe_curent_type.has_value() && maybe_current_typeclass.has_value()) { + error_handling::HandleInternalError("Current namespace is belong to type and typeclass in same time", + "TypeCheckVisitor.FunctionDefinitionStatement", + &node->base); + } + + if (!maybe_curent_type.has_value() && !maybe_current_typeclass.has_value()) { + error_handling::HandleTypecheckError("Function defined, but declared in typeclass and not belong to type or typeclass namespace", node->base); + } + + bool method_found_in_typeclass = false; + if (maybe_curent_type.has_value()) { // optiomize?? + auto typeclasses = typeclass_graph_.GetDependenciesSet(maybe_curent_type.value()->type.node->graph_id_); + + method_found_in_typeclass = (typeclasses.count(maybe_typeclass_graph_id.value()) != 0); + + } else if (maybe_current_typeclass.has_value()) { + method_found_in_typeclass = + typeclass_graph_.IsFunctionInVertex(function_name, maybe_current_typeclass.value()->graph_id_); + } + + if (!method_found_in_typeclass) { + error_handling::HandleTypecheckError("Function defined, but declared in different typeclass", node->base); + } + + auto maybe_function_info = typeclass_graph_.GetFunctionInfo(function_name, std::nullopt); + if (!maybe_function_info.has_value()) { + error_handling::HandleInternalError("FunctionInfo not found", + "TypeCheckVisitor.FunctionDefinitionStatement", + &node->base); + } + + declaration = maybe_function_info.value()->declaration; + } + + context_manager_.EnterContext(); + + if (declaration->type->types.size() != node->definition->arguments.size() + 1) { // + return type + error_handling::HandleTypecheckError("Wrong argument count in function definition", node->base); + } + + for (auto& parameter : declaration->parameters) { + current_type_ = context_manager_.AddValue(info::type::AbstractType(utils::AbstractTypeModifier::Abstract, + parameter->graph_id_, + typeclass_graph_), + utils::ValueType::Tmp); + if (!context_manager_.DefineLocalType(parameter->type, current_type_)) { + error_handling::HandleTypecheckError("Can't define function parameter type: abstract type redefinition", node->base); + } + } + + for (size_t i = 0; i < node->definition->arguments.size(); ++i) { + Visitor::Visit(declaration->type->types[i]); + current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const); + if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) { + error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base); + } + } + + Visitor::Visit(declaration->type->types.back()); + utils::IdType returned_type = current_type_; + + returned_type_ = std::nullopt; + all_branches_returned_value_ = true; + Visitor::Visit(node->value); + + if (!all_branches_returned_value_) { + error_handling::HandleTypecheckError("Not all branches return value", node->base); + } + + if (!returned_type_.has_value()) { + returned_type_ = current_type_; + } + if (!context_manager_.EqualValues(returned_type, returned_type_.value())) { + error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type)->ToString()); + error_handling::DebugPrint(context_manager_.GetAnyValue(returned_type_.value())->ToString()); + error_handling::HandleTypecheckError("Wrong function return type", node->base); + } + returned_type_ = std::nullopt; + + context_manager_.ExitContext(); + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + is_in_statement_ = false; + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(TypeDefinitionStatement* node) { + is_in_statement_ = true; + + const std::unordered_map& required_functions = + typeclass_graph_.GetVertexFunctions(node->definition->type->graph_id_); + + std::string& type_name = node->definition->type->type; + + for (auto& function : required_functions) { + if (function.second.definition.has_value()) { + continue; + } + + std::unordered_map* current_namespaces = + global_info_.ChooseNamespaces(function.second.modifier, namespace_visitor_.GetCurrentNamespace()); + + auto& type_functions = global_info_.GetNamespaceInfo((*current_namespaces)[type_name]).functions; + + auto function_iter = type_functions.find(function.first); + + if (function_iter == type_functions.end() || !global_info_.GetFunctionInfo(function_iter->second).definition.has_value()) { + error_handling::HandleTypecheckError("Type is not satisfy typeclass requirements: " + function.first + " is not defined", node->base); + } + } + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + is_in_statement_ = false; + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(AbstractTypeDefinitionStatement* node) { + is_in_statement_ = true; + + auto maybe_internal_type = info::type::ToInternalType(node->type->type); + + if (maybe_internal_type.has_value() + && internal_to_abstract_type_.count(maybe_internal_type.value()) != 0) { + return; + } + + auto requirements = typeclass_graph_.GetDependenciesSet(node->type->graph_id_); + + current_type_ = context_manager_.AddValue(info::type::AbstractType(node->modifier, + node->type->graph_id_, + typeclass_graph_), + utils::ValueType::Tmp); + + if (maybe_internal_type.has_value()) { + internal_to_abstract_type_[maybe_internal_type.value()] = current_type_; + } + + if (!context_manager_.DefineLocalType(node->type->type, current_type_)) { + error_handling::HandleTypecheckError("Can't define basic / abstract type: abstract type redefinition", node->base); + } + + is_in_statement_ = false; + + // otherwise function called from VisitSourceFile + if (!maybe_internal_type.has_value()) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + node->base.type_ = current_type_; + } +} + +void TypeCheckVisitor::Visit(TypeclassDefinitionStatement* node) { + is_in_statement_ = true; + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + is_in_statement_ = false; + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(PartitionStatement* node) { + is_in_statement_ = true; + context_manager_.EnterContext(); + + Visitor::Visit(node->value); + + context_manager_.ExitContext(); + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + is_in_statement_ = false; + + node->base.type_ = current_type_; +} + +// Definition parts + +void TypeCheckVisitor::Visit(FunctionDefinition* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(TypeDefinition* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(AnyAnnotatedType* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + node->base.type_ = current_type_; +} + +// Flow control ----------------- + +void TypeCheckVisitor::Visit(TypeConstructorPatternParameter*) {} // Handled in TypeConstructorPattern + +// TODO: check ?? +void TypeCheckVisitor::Visit(TypeConstructorPattern* node) { // TODO: match named constructor + if (!node->constructor->constructor_id_.has_value()) { + error_handling::HandleTypecheckError("Type constructor pattern constructor name not found", node->base); + } + + if (!node->constructor->type_id_.has_value()) { + error_handling::HandleInternalError("Type constructor pattern without type", + "TypeCheckVisitor.TypeConstructorPattern", + &node->base); + } + + utils::IdType constructor_id = node->constructor->constructor_id_.value(); + + info::definition::Constructor constructor_info = global_info_.GetConstructorInfo(constructor_id); + + utils::IdType type_id = constructor_info.type_id; + + std::unordered_map context; + CollectTypeExpressionContext(*node->constructor, context); + + std::optional maybe_type_info = + global_info_.GetTypeInfo(type_id); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Implemented only for AnyType", + "TypeCheckVisitor.TypeConstructorPattern", + &node->base); + } + + info::definition::AnyType& type_info = *maybe_type_info.value(); + + if (constructor_info.constructor_tuple_node.has_value()) { + + TupleType* constructor_fields = constructor_info.constructor_tuple_node.value(); + + if (constructor_fields->entities.size() != node->parameters.size()) { + error_handling::HandleTypecheckError("Type constructor pattern parameters count mismatch", node->base); + } + + for (size_t i = 0; i < node->parameters.size(); ++i) { + if (node->parameters[i].name.has_value()) { // TODO: needed?? + if (!constructor_fields->entities[i].first.has_value() + || constructor_fields->entities[i].first.value() != node->parameters[i].name.value()) { + error_handling::HandleTypecheckError("Type constructor pattern: name of parameter and name in constructor don't match each other", node->base); + } + } else { + if (constructor_fields->entities[i].first.has_value()) { + error_handling::HandleTypecheckError("Type constructor pattern: unnamed parameter corresponds named field", node->base); + } + } + + Visitor::Visit(constructor_fields->entities[i].second.get()); + current_type_ = TypeInContext(current_type_, context); + + CheckPattern(node->parameters[i].value, node->base); // current_type_ passed to parameter + } + + } else { + if (node->parameters.size() > 0) { + error_handling::HandleTypecheckError("Parameters for untyped type constructor pattern", node->base); + } + } + + Visitor::Visit(type_info.node->value); + current_type_ = TypeInContext(current_type_, context); + current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(MatchCase* node) { + // value type passed as current_type_ + is_const_definition_ = utils::IsConstModifier::Const; + Visitor::Visit(node->value); + + current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Tmp); + + CheckPattern(node->value, node->base); + + is_const_definition_ = std::nullopt; + + if (node->condition.has_value()) { + Visitor::Visit(node->condition.value()); + } + if (!context_manager_.EqualValues( + internal_to_abstract_type_.at(info::type::InternalType::Bool), + current_type_)) { + error_handling::HandleTypecheckError("Match case condition is not bool expression", node->base); + } + + // IMPORTANT: statement visited in Match + + node->base.type_ = current_type_; +} + +// TODO: move, etc. +void TypeCheckVisitor::Visit(Match* node) { + // TODO: types can be different in block statement + context_manager_.EnterContext(); + + utils::IdType type; + + bool is_type_found = false; + + Visitor::Visit(node->value); + utils::IdType value_type = current_type_; + + std::optional nearest_statement; + for (ssize_t i = (ssize_t)node->matches.size() - 1; i >= 0; --i) { + ResetReturnedAndBroughtTypes(); + + current_type_ = value_type; + + context_manager_.EnterContext(); + Visit(&node->matches[i]); + + if (node->matches[i].statement.has_value()) { + nearest_statement = &node->matches[i].statement.value(); + } + + if (!nearest_statement.has_value()) { + continue; + } + + Visitor::Visit(*nearest_statement.value()); + + context_manager_.ExitContext(); + + if (!is_type_found) { + type = current_type_; + is_type_found = true; + } else { + if (!context_manager_.EqualValues(type, current_type_)) { + error_handling::HandleTypecheckError("Match statement cases have different types", node->base); + } + } + } + + if (!is_type_found) { + error_handling::HandleTypecheckError("Can't find match expression type", node->base); + // type = internal_to_abstract_type_.at(info::type::InternalType::Unit); + } + + current_type_ = type; + + // --- instead of optional return value or throw runtime error --- + // current_type_ = context_manager_.AddValue( + // info::type::OptionalType(current_type_, context_manager_.GetValueManager()), + // utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(Condition* node) { + context_manager_.EnterContext(); + + // TODO: types can be different in statement + utils::IdType type; + + for (size_t i = 0; i < node->conditions.size(); ++i) { + ResetReturnedAndBroughtTypes(); + + Visitor::Visit(node->conditions[i]); + if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Bool), current_type_)) { + error_handling::HandleTypecheckError("Condition statement condition is not bool expression", node->base); + } + + Visitor::Visit(node->statements[i]); + + if (i == 0) { + type = current_type_; + } else { + if (!context_manager_.EqualValues(type, current_type_)) { + error_handling::HandleTypecheckError("Condition statement cases have different types", node->base); + } + } + } + + if (node->statements.size() > node->conditions.size()) { + ResetReturnedAndBroughtTypes(); + + Visitor::Visit(node->statements[node->conditions.size()]); + + if (!context_manager_.EqualValues(type, current_type_)) { + error_handling::HandleTypecheckError("Condition statement else have different type from other cases", node->base); + } + current_type_ = type; + } else { + current_type_ = context_manager_.AddValue( + info::type::OptionalType(type, context_manager_.GetValueManager()), + context_manager_.GetValueType(type)); // optional with "reference" to result type + } + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(DoWhileLoop* node) { + context_manager_.EnterContext(); + + Visitor::Visit(node->condition); + if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Bool), current_type_)) { + error_handling::HandleTypecheckError("Do while loop statement condition is not bool expression", node->base); + } + + Visitor::Visit(node->statement); + + current_type_ = context_manager_.AddValue( + info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(WhileLoop* node) { + context_manager_.EnterContext(); + + Visitor::Visit(node->condition); + if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Bool), current_type_)) { + error_handling::HandleTypecheckError("While loop statement condition is not bool expression", node->base); + } + + Visitor::Visit(node->statement); + + current_type_ = context_manager_.AddValue( + info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; +} + +// TODO: variable with reference to interval element + check +void TypeCheckVisitor::Visit(ForLoop* node) { + context_manager_.EnterContext(); + + Visitor::Visit(node->interval); + std::optional maybe_interval_type = context_manager_.GetValue(current_type_); + + if (!maybe_interval_type.has_value()) { + error_handling::HandleTypecheckError("For loop interval type mismatch", node->base); + } + + current_type_ = context_manager_.ToModifiedValue(maybe_interval_type.value()->GetElementsType(), + utils::IsConstModifierToValueType(node->variable_modifier)); + + is_const_definition_ = node->variable_modifier; + Visitor::Visit(node->variable); // type passed to variable definition throught current_type_ + is_const_definition_ = std::nullopt; + + Visitor::Visit(node->statement); + + current_type_ = context_manager_.AddValue( + info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(LoopLoop* node) { + context_manager_.EnterContext(); + + Visitor::Visit(node->statement); + + current_type_ = context_manager_.AddValue( + info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; +} + +// Statements, expressions, blocks, etc. ----------------- + +void TypeCheckVisitor::Visit(Block* node) { + // TODO: types can be different in statement + + all_branches_brought_value_ = true; + brought_type_ = std::nullopt; + + context_manager_.EnterContext(); + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + context_manager_.ExitContext(); + + if (!all_branches_brought_value_) { + error_handling::HandleTypecheckError("Different brought types in block", node->base); + } + + if (brought_type_.has_value()) { + current_type_ = brought_type_.value(); + } else { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + } + + brought_type_ = std::nullopt; + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(ScopedStatement* node) { + Visitor::Visit(node->statement); + // current_type_ is type of statement + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(LoopControlExpression&) { // enum + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); +} + +// Operators + +void TypeCheckVisitor::Visit(ReferenceExpression* node) { + Visit(node->expression.get()); + + current_type_ = context_manager_.AddValue( + info::type::ReferenceToType({node->reference}, + current_type_, + context_manager_.GetValueManager()), + context_manager_.GetValueType(current_type_)); +} + +// TODO: redifinitions for other types and tuples (with const index) ?? +// TODO: string should be array +void TypeCheckVisitor::Visit(AccessExpression* node) { + Visitor::Visit(node->id); + if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Int), current_type_)) { + error_handling::HandleTypecheckError("Access index has wrong type (not Int)", node->base); + } + + Visitor::Visit(node->name.get()); + + auto maybe_type_value = context_manager_.GetValue(current_type_); + + if (maybe_type_value.has_value()) { + current_type_ = maybe_type_value.value()->GetElementsType(); // "reference" to element + } else { + auto maybe_internal_type_value = context_manager_.GetValue(current_type_); + + if (!maybe_internal_type_value.has_value() || *maybe_internal_type_value.value() != info::type::InternalType::String) { + error_handling::HandleTypecheckError("Access type is not array", node->base); + } + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Char); + node->is_string_access_ = true; + } + + node->base.type_ = current_type_; +} + +// Other Expressions + +void TypeCheckVisitor::Visit(FunctionCallExpression* node) { + context_manager_.EnterContext(); + + std::optional maybe_function_declaration; + + std::unordered_map context; + + if (node->name.empty()) { + error_handling::HandleInternalError("Empty name", + "TypeCheckVisitor.FunctionCallExpression", + &node->base); + } + + if (node->name[0] == '_') { + error_handling::HandleTypecheckError("Only builtin functions can start with _. This function is not found", node->base); + } + + // try to find function declaration + if (node->prefix.has_value()) { + if (std::holds_alternative>(node->prefix.value())) { + Visitor::Visit(*std::get>(node->prefix.value())); + utils::IdType expression_type = current_type_; + maybe_function_declaration = FindExpressionMethodAndUpdate(node, expression_type); + } else if (std::holds_alternative>(node->prefix.value())) { + maybe_function_declaration = FindTypeFunctionAndUpdate( + node, + std::get>(node->prefix.value()).get(), + context); + } else { + error_handling::HandleInternalError("Unexpected prefix type", + "TypeCheckVisitor.FunctionCallExpression", + &node->base); + } + } else { + maybe_function_declaration = FindFunctionAndUpdate(node); + } + + // function declaration check + if (!maybe_function_declaration.has_value()) { + error_handling::HandleTypecheckError("No function declaration found for function in call expression", node->base); + } + FunctionDeclaration* function_declaration = maybe_function_declaration.value(); + + // check & collect parmeters + if (function_declaration->parameters.size() != node->parameters.size()) { + error_handling::HandleTypecheckError("Mismatched parameter count in function call expression", node->base); + } + for (size_t i = 0; i < node->parameters.size(); ++i) { + Visit(node->parameters[i].get()); + + std::string parameter_name = function_declaration->parameters[i]->type; + + if (context.count(parameter_name) != 0) { + error_handling::HandleInternalError("Local abstract types with same name in one context", + "TypeCheckVisitor.FunctionCallExpresssion", + &node->base); + } + context[parameter_name] = current_type_; + } + + size_t index_shift = (node->is_method_of_first_argument_ ? 1 : 0); + + // check arguments + if (function_declaration->type->types.size() != node->arguments.size() + 1 - index_shift) { + error_handling::HandleTypecheckError("Mismatched argument count in function call expression", node->base); + } + + for (size_t i = index_shift; i < node->arguments.size(); ++i) { + Visitor::Visit(function_declaration->type->types[i - index_shift]); + utils::IdType argument_type = TypeInContext(current_type_, context); + + Visitor::Visit(node->arguments[i]); + if (!context_manager_.AddValueRequirement(current_type_, argument_type)) { + error_handling::HandleTypecheckError("Wrong argument type (argument " + std::to_string(i - index_shift + 1) + ")", node->base); + } + } + + if (!utils::IsBuiltinFunction(node->name)) { + if (node->function_id_.has_value()) { + if (!global_info_.GetFunctionInfo(node->function_id_.value()).definition.has_value()) { + error_handling::HandleTypecheckError("No function definition found (namespace function)", node->base); + } + } else if (node->graph_id_.has_value()) { + if (typeclass_graph_.GetVertex(node->graph_id_.value()).modifier != info::TypeclassGraph::Modifier::Typeclass) { + auto maybe_graph_function_info = typeclass_graph_.GetFunctionInfo(node->name, node->graph_id_.value()); + + if (!maybe_graph_function_info.has_value()) { + error_handling::HandleInternalError("FunctionInfo by graph_id_ not found", + "TypeCheckVisitor.FunctionCallExpression", + &node->base); + } + + if (!maybe_graph_function_info.value()->definition.has_value()) { + error_handling::HandleTypecheckError("No function definition found (type function)", node->base); + } + } + } else { + error_handling::HandleInternalError("No function_id_ and graph_id_ found", + "TypeCheckVisitor.FunctionCallExpression", + &node->base); + } + } + + Visitor::Visit(function_declaration->type->types.back()); + current_type_ = TypeInContext(current_type_, context); + + node->base.type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Tmp); +} + +void TypeCheckVisitor::Visit(TupleExpression* node) { + std::vector, utils::IdType>> fields; + fields.reserve(node->expressions.size()); + for (auto& expression : node->expressions) { + Visitor::Visit(expression); + fields.push_back({std::nullopt, current_type_}); + } + + current_type_ = context_manager_.AddValue( + info::type::TupleType(std::nullopt, fields, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(VariantExpression* node) { + std::vector constructors; + + for (auto& expression : node->expressions) { + Visitor::Visit(expression); + + // TODO: deal with expression tuple types, etc, ?? + std::vector, utils::IdType>> constructor_fields {{std::nullopt, current_type_}}; + constructors.push_back(info::type::TupleType(std::nullopt, constructor_fields, context_manager_.GetValueManager())); + } + + + current_type_ = context_manager_.AddValue(info::type::VariantType(std::nullopt, + constructors, + std::nullopt), + utils::ValueType::Tmp); + + current_type_ = context_manager_.AddValue( + info::type::OptionalType(current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(ReturnExpression* node) { + Visitor::Visit(node->expression); + if (node->is_from_definition) { + if (returned_type_.has_value()) { + if (!context_manager_.EqualValues(returned_type_.value(), current_type_)) { + error_handling::HandleTypecheckError("Different returned types", node->base); + } + } else { + returned_type_ = current_type_; + } + all_branches_returned_value_ = true; + } else { + if (brought_type_.has_value()) { + if (!context_manager_.EqualValues(brought_type_.value(), current_type_)) { + error_handling::HandleTypecheckError("Different brought types", node->base); + } + } else { + brought_type_ = current_type_; + } + all_branches_brought_value_ = true; + } + + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(TypeConstructorParameter*) {} // Handeled in TypeConstructor visit + +// TODO: check for tuples +// TODO: move, etc. +void TypeCheckVisitor::Visit(TypeConstructor* node) { + if (!node->constructor->constructor_id_.has_value()) { + error_handling::HandleTypecheckError("Type constructor name not found", node->base); + } + + if (!node->constructor->type_id_.has_value()) { + error_handling::HandleInternalError("Type constructor without type", + "TypeCheckVisitor.TypeConstructor", + &node->base); + } + + utils::IdType constructor_id = node->constructor->constructor_id_.value(); + + info::definition::Constructor constructor_info = global_info_.GetConstructorInfo(constructor_id); + + utils::IdType type_id = constructor_info.type_id; + + std::unordered_map context; + CollectTypeExpressionContext(*node->constructor, context); + + std::optional maybe_type_info = + global_info_.GetTypeInfo(type_id); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Implemented only for AnyType", + "TypeCheckVisitor.TypeConstructor", + &node->base); + } + + info::definition::AnyType& type_info = *maybe_type_info.value(); + + if (constructor_info.constructor_tuple_node.has_value()) { + + TupleType* constructor_fields = constructor_info.constructor_tuple_node.value(); + + if (constructor_fields->entities.size() != node->parameters.size()) { + error_handling::HandleTypecheckError("Type constructor parameters count mismatch", node->base); + } + + for (size_t i = 0; i < node->parameters.size(); ++i) { + if (node->parameters[i].name.has_value()) { + if (!constructor_fields->entities[i].first.has_value() + || constructor_fields->entities[i].first.value() != node->parameters[i].name.value()) { + error_handling::HandleTypecheckError("Type constructor: name of parameter and name in constructor don't match each other", node->base); + } + } else { + if (constructor_fields->entities[i].first.has_value()) { + error_handling::HandleTypecheckError("Type constructor: unnamed parameter corresponds named field", node->base); + } + } + + Visitor::Visit(constructor_fields->entities[i].second.get()); + utils::IdType parameter_type = TypeInContext(current_type_, context); + + Visitor::Visit(node->parameters[i].value); + + if (!context_manager_.EqualValues(parameter_type, current_type_)) { + error_handling::HandleTypecheckError("Type constructor: wrong parameter type", node->base); + } + } + + } else { + if (node->parameters.size() > 0) { + error_handling::HandleTypecheckError("Parameters for untyped type constructor", node->base); + } + } + + Visitor::Visit(type_info.node->value); + + std::optional maybe_variant_type = + context_manager_.GetValue(current_type_); + + if (maybe_variant_type.has_value()) { + if (!constructor_info.order.has_value()) { + error_handling::HandleInternalError("No order found in constructor of VariantType", + "TypeCheckVisitor.TypeConstructor", + &node->base); + } + maybe_variant_type.value()->SetCurrentConstructor(constructor_info.order.value()); + } + + // if it is tuple, order not required + + current_type_ = TypeInContext(current_type_, context); + + current_type_ = context_manager_.AddValue( + info::type::DefinedType(type_id, + current_type_, + type_info.modifier, + context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +// TODO +void TypeCheckVisitor::Visit(LambdaFunction* node) { + error_handling::HandleInternalError("Unimplemented (unsolved type deduction problems)", + "TypeCheckVisitor.LambdaFunction", + &node->base); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(ArrayExpression* node) { + utils::IdType elements_type = 0; + + for (size_t i = 0; i < node->elements.size(); ++i) { + Visitor::Visit(node->elements[i]); + if (i == 0) { + elements_type = current_type_; + } else { + if (!context_manager_.EqualValues(elements_type, current_type_)) { + error_handling::HandleTypecheckError("Different element types in array expression", node->base); + } + } + } + + if (node->elements.empty()) { + error_handling::HandleInternalError("Element size is 0", + "TypeCheckVisitor.ArrayExpression", + &node->base); + } + + current_type_ = context_manager_.AddValue( + info::type::ArrayType(node->elements.size(), elements_type, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +// Name + +void TypeCheckVisitor::Visit(PartitionName*) {} // Handled in partition ( executable / test ) + +void TypeCheckVisitor::Visit(NameExpression* node) { + // TODO: move, etc. + if (node->names.empty()) { + error_handling::HandleInternalError("Name expression with zero names", + "TypeCheckVisitor.NameExpression", + &node->base); + } + + auto maybe_variable_type = context_manager_.FindVariable(node->names[0]); + + if (!maybe_variable_type.has_value()) { + error_handling::HandleTypecheckError("Variable not found", node->base); + } + + current_type_ = maybe_variable_type.value(); + + if (node->names.size() > 1) { + utils::ValueType variable_value_type = context_manager_.GetValueType(current_type_); + + for (size_t i = 1; i < node->names.size(); ++i) { + std::optional maybe_type_value = + context_manager_.GetAnyValue(current_type_)->GetFieldType(node->names[i], type_namespaces_); + if (!maybe_type_value.has_value()) { + error_handling::HandleTypecheckError("Variable field not found", node->base); + } + + current_type_ = maybe_type_value.value(); + } + + current_type_ = context_manager_.ToModifiedValue(current_type_, variable_value_type); + } + + node->base.type_ = current_type_; +} + +// TODO: move, etc. +void TypeCheckVisitor::Visit(TupleName* node) { + utils::IdType type = current_type_; + + std::optional maybe_defined_type_value = context_manager_.GetValue(type); + if (maybe_defined_type_value.has_value()) { + type = maybe_defined_type_value.value()->GetType(); + } + + auto maybe_type_value = context_manager_.GetValue(type); + if (!maybe_type_value.has_value()) { + error_handling::HandleTypecheckError("Mismatched types in tuple variable definition", node->base); + } + info::type::TupleType* type_value = maybe_type_value.value(); + + if (type_value->GetFields().size() != node->names.size()) { + error_handling::HandleTypecheckError("Mismatched field count in tuple variable definition", node->base); + } + + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.TupleName", + &node->base); + } + + utils::ValueType value_type = context_manager_.GetValueType(type); + + for (size_t i = 0; i < node->names.size(); ++i) { + current_type_ = type_value->GetFields()[i].second; + + if (value_type == utils::ValueType::Tmp) { // TODO: instead of recusive modification ?? + current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Tmp); + } + + Visitor::Visit(node->names[i]); + } + + current_type_ = type; + + node->base.type_ = current_type_; +} + +// TODO: move, etc. +void TypeCheckVisitor::Visit(VariantName* node) { + utils::IdType type = current_type_; + + std::optional maybe_defined_type_value = context_manager_.GetValue(type); + if (maybe_defined_type_value.has_value()) { + type = maybe_defined_type_value.value()->GetType(); + } + + auto maybe_type_value = context_manager_.GetValue(type); + if (!maybe_type_value.has_value()) { + error_handling::HandleTypecheckError("Mismatched types in variant variable definition", node->base); + } + info::type::VariantType* type_value = maybe_type_value.value(); + + if (type_value->GetConstructors().size() != node->names.size()) { + error_handling::HandleTypecheckError("Mismatched variant count in variant variable definition", node->base); + } + + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.VariantName", + &node->base); + } + + for (size_t i = 0; i < node->names.size(); ++i) { + if (type_value->GetConstructors()[i].GetFields().empty()) { + current_type_ = context_manager_.AddValue( + info::type::OptionalType( + internal_to_abstract_type_.at(info::type::InternalType::Unit), + context_manager_.GetValueManager()), + utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? + } else { + info::type::TupleType constructor_type_value = type_value->GetConstructors()[i]; + + utils::IdType constructor_type = + context_manager_.AddValue(std::move(constructor_type_value), + utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? + current_type_ = context_manager_.AddValue( + info::type::OptionalType(constructor_type, context_manager_.GetValueManager()), + utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? + } + + Visitor::Visit(node->names[i]); + } + + current_type_ = type; + + node->base.type_ = current_type_; +} + +// TODO: move, etc. +void TypeCheckVisitor::Visit(AnnotatedName* node) { + utils::IdType type = current_type_; + + if (!is_const_definition_.has_value()) { + error_handling::HandleInternalError("No value in is_const_definition_", + "TypeCheckVisitor.AnnotatedName", + &node->base); + } + + type = context_manager_.ToModifiedValue(type, utils::IsConstModifierToValueType(is_const_definition_.value())); + if (!context_manager_.DefineVariable(node->name, type)) { + error_handling::HandleTypecheckError("Variable name already present in context", node->base); + } + if (node->type.has_value()) { + Visitor::Visit(node->type.value()); + if (!context_manager_.EqualValues(type, current_type_)) { // TODO ?? + error_handling::HandleTypecheckError("Wrong type annotation in annotated name", node->base); + } + } + + node->base.type_ = current_type_; +} + +// Type, typeclass, etc. ----------------- + +// Type + +void TypeCheckVisitor::Visit(FunctionType* node) { + std::vector argument_types(node->types.size()); + + for (auto& argument_type : node->types) { + Visitor::Visit(argument_type); + argument_types.push_back(current_type_); + } + + utils::IdType return_type = argument_types.back(); + argument_types.pop_back(); + + current_type_ = context_manager_.AddValue( + info::type::FunctionType(argument_types, return_type, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(TupleType* node) { + std::vector, utils::IdType>> fields; + + fields.reserve(node->entities.size()); + for (auto& entity : node->entities) { + Visit(entity.second.get()); + if (entity.first.has_value()) { + fields.push_back({entity.first.value(), current_type_}); + } else { + fields.push_back({std::nullopt, current_type_}); + } + } + + current_type_ = context_manager_.AddValue( + info::type::TupleType(node->type, fields, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(VariantType* node) { + std::vector constructors; + + constructors.reserve(node->constructors.size()); + for (auto& constructor : node->constructors) { + if (std::holds_alternative(constructor)) { + std::vector, utils::IdType>> constructor_fields; + constructors.push_back(info::type::TupleType(std::get(constructor), constructor_fields, context_manager_.GetValueManager())); + } else if (std::holds_alternative>(constructor)) { + Visit(std::get>(constructor).get()); + std::optional maybe_constructor = context_manager_.GetValue(current_type_); + if (!maybe_constructor.has_value()) { + error_handling::HandleInternalError("Entity of VariantType is not TupleType", + "TypeCheckVisitor.VariantType", + &node->base); + } + constructors.push_back(*maybe_constructor.value()); + } else { + // error + } + } + + current_type_ = context_manager_.AddValue(info::type::VariantType(node->type, + constructors, + std::nullopt), + utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(TypeExpression* node) { + std::unordered_map context; + CollectTypeExpressionContext(*node, context); + + // TODO: -------- remove, unneeded ------ + // auto maybe_internal_type = info::type::ToInternalType(node->type.type); + // + // if (maybe_internal_type.has_value()) { // TODO: ??? + // // checks made in link_symbols_visitor + // current_type_ = + // context_manager_.AddValue( + // maybe_internal_type.value(), + // utils::ValueType::Tmp); + // } else { + std::optional maybe_local_abstract_type = + context_manager_.FindLocalType(node->type.type); + if (node->path.empty() && maybe_local_abstract_type.has_value()) { + current_type_ = maybe_local_abstract_type.value(); + } else if (node->type.type_id_.has_value()) { // TODO: check that names are different (always true ??) + std::optional maybe_type_info = + global_info_.GetTypeInfo(node->type.type_id_.value()); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("No AnyType found (alias types, ... not implemented)", + "TypeCheckVisitor.TypeExpression", + &node->base); + } + + VisitDefinedType(maybe_type_info.value(), context); + } else { + error_handling::HandleTypecheckError("Type not found", node->base); + } + // } + + if (node->array_size.has_value()) { + current_type_ = context_manager_.AddValue( + info::type::ArrayType(node->array_size.value(), current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + } + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(ExtendedScopedAnyType* node) { + Visitor::Visit(node->type); + + current_type_ = context_manager_.AddValue( + info::type::ReferenceToType(node->references, current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + node->base.type_ = current_type_; +} + +// Typeclass + +void TypeCheckVisitor::Visit(ParametrizedTypeclass* node) { + if (node->parameters.size()) { + error_handling::HandleInternalError("Typeclasses with parameters are not implemented", + "TypeCheckVisitor.ParametrizedTypeclass", + &node->base); + } + + error_handling::HandleInternalError("ParametizedTypeclass shouldn't be visited (?)", + "TypeCheckVisitor.ParametrizedTypeclass", + &node->base); +} + +// Typeclass & Type ----------------- + +void TypeCheckVisitor::Visit(ParametrizedType*) {} // Handled in TypeExpression + +// Identifiers, constants, etc. ----------------- + +void TypeCheckVisitor::Visit(FloatNumberLiteral* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Float); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(NumberLiteral* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Int); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(StringLiteral* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::String); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(CharLiteral* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Char); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(UnitLiteral* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Unit); + + node->base.type_ = current_type_; +} + +void TypeCheckVisitor::Visit(BoolLiteral* node) { + current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Bool); + + node->base.type_ = current_type_; +} + +// + +void TypeCheckVisitor::CollectTypeContext(const ParametrizedType& type, + std::unordered_map& context) { + if (!type.type_id_.has_value()) { + return; + } + + std::optional maybe_type_info = + global_info_.GetTypeInfo(type.type_id_.value()); + + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Wrong type id", + "TypeCheckVisitor.CollectTypeContext", + std::nullopt); + } + + info::definition::AnyType& type_info = *maybe_type_info.value(); + + if (type_info.parameters.size() != type.parameters.size()) { + error_handling::HandleTypecheckError("Wrong type parameters count", type.base); + } + + for (size_t i = 0; i < type.parameters.size(); ++i) { + Visit(type.parameters[i].get()); + + if (context.count(type_info.parameters[i].type) != 0) { + error_handling::HandleInternalError("Same parameter type names", + "TypeCheckVisitor.CollectTypeContext", + std::nullopt); + } + + context[type_info.parameters[i].type] = current_type_; + } +} + +void TypeCheckVisitor::CollectTypeExpressionContext(const TypeExpression& type_expression, + std::unordered_map& context) { + for (auto& path_type : type_expression.path) { + CollectTypeContext(path_type, context); + } + CollectTypeContext(type_expression.type, context); +} + +utils::IdType TypeCheckVisitor::TypeInContext(utils::IdType type, + const std::unordered_map& context) { + info::type::Type type_in_context = *context_manager_.GetAnyValue(type); + type_in_context.InContext(context); + return context_manager_.AddValue(std::move(type_in_context), utils::ValueType::Tmp); +} + +void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { // <-> ScopedPattern + utils::IdType value_type = current_type_; + + switch (node.index()) { + case 0: + value_type = context_manager_.ToModifiedValue(value_type, utils::ValueType::Const); // ?? + if (!context_manager_.DefineVariable(*std::get>(node), + value_type)) { + error_handling::HandleTypecheckError("Can't redifine variable", base_node); + } + break; + case 1: + Visitor::Visit(*std::get>(node)); + if (!context_manager_.EqualValues(current_type_, value_type)) { + error_handling::HandleTypecheckError("Literal and value have different types", base_node); + } + break; + case 2: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +// TODO: internal types ?? +std::optional + TypeCheckVisitor::FindExpressionMethodAndUpdate(FunctionCallExpression* node, + utils::IdType expression_type) { + std::optional maybe_function_declaration; + + auto maybe_abstract_type_info = context_manager_.GetValue(expression_type); + + if (maybe_abstract_type_info.has_value()) { + maybe_function_declaration = FindAbstractTypeTypeclassFunctionAndUpdate(node, + maybe_abstract_type_info.value(), + true); + } else { + auto maybe_defined_type_info = context_manager_.GetValue(expression_type); + if (!maybe_defined_type_info.has_value()) { + error_handling::HandleTypecheckError("There is no non-builtin methods for not defined type", node->base); + } + + utils::IdType type_id = maybe_defined_type_info.value()->GetTypeId(); + auto maybe_type_info = global_info_.GetTypeInfo(type_id); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("Functions / Methods implemented only for AnyType", + "TypeCheckVisitor.FindExpressionMethodAndUpdate", + &node->base); + } + info::definition::AnyType* type_info = maybe_type_info.value(); + + maybe_function_declaration = FindDefinedTypeFunctionAndUpdate(node, + type_info, + expression_type, + true); + } + return maybe_function_declaration; +} + +// TODO: internal types ?? +// TODO: handle abstract defined types ?? +std::optional + TypeCheckVisitor::FindTypeFunctionAndUpdate(FunctionCallExpression* node, + TypeExpression* type_node, + std::unordered_map& context) { + std::optional maybe_function_declaration; + + if (type_node->array_size.has_value()) { + error_handling::HandleTypecheckError("Can't call function from array type namespace", node->base); + } + + std::optional maybe_local_abstract_type = context_manager_.FindLocalType(type_node->type.type); + + if (maybe_local_abstract_type.has_value()) { + auto maybe_abstract_type_info = + context_manager_.GetValue(maybe_local_abstract_type.value()); + + if (!maybe_abstract_type_info.has_value()) { + error_handling::HandleInternalError("Local abstract type contains not abstract type", + "TypeCheckVisitor.FindTypeFunctionAndUpdate", + &node->base); + } + + maybe_function_declaration = FindAbstractTypeTypeclassFunctionAndUpdate(node, + maybe_abstract_type_info.value(), + false); + } else { + std::vector path; + path.reserve(type_node->path.size() + 1); + + for (auto& path_type : type_node->path) { + path.push_back(path_type.type); + } + path.push_back(type_node->type.type); + + CollectTypeExpressionContext(*type_node, context); + + if (type_node->type_id_.has_value()) { + auto maybe_type_info = global_info_.GetTypeInfo(type_node->type_id_.value()); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType", + "TypeCheckVisitor.FindTypeFunctionAndUpdate", + &node->base); + } + + VisitDefinedType(maybe_type_info.value(), context); + maybe_function_declaration = + FindDefinedTypeFunctionAndUpdate(node, + maybe_type_info.value(), + current_type_, + false); + } else { + std::optional maybe_function_id = namespace_visitor_.FindFunctionId(path, node->name); + + if (maybe_function_id.has_value()) { + node->function_id_ = maybe_function_id.value(); + + auto maybe_function_declaration_info = + global_info_.GetFunctionInfo(maybe_function_id.value()).declaration; + + maybe_function_declaration = + (maybe_function_declaration_info.has_value() + ? maybe_function_declaration_info.value().node + : std::optional()); + } + } + } + return maybe_function_declaration; +} + +std::optional TypeCheckVisitor::FindFunctionAndUpdate(FunctionCallExpression* node) { + std::optional maybe_function_declaration; + + + const std::vector& path_namespaces = namespace_visitor_.GetCurrentPathNamespaces(); + auto path_types = namespace_visitor_.GetCurrentPathTypes(); + for (ssize_t i = (ssize_t)path_types.size() - 1; i >= 0; --i) { // optimize ?? + if (path_types[i].has_value()) { + auto maybe_type_info = global_info_.GetTypeInfo(path_types[i].value()); + if (!maybe_type_info.has_value()) { + error_handling::HandleInternalError("typeclass functions / methods implemented only for AnyType", + "TypeCheckVisitor.FindTypeFunctionAndUpdate", + &node->base); + } + + VisitDefinedType(maybe_type_info.value(), {}); // TODO: context ?? + maybe_function_declaration = + FindDefinedTypeFunctionAndUpdate(node, + maybe_type_info.value(), + current_type_, + false); + } else if (global_info_.GetNamespaceInfo(path_namespaces[i]).modifier == utils::ClassInternalsModifier::Static) { + auto function_iter = global_info_.GetNamespaceInfo(path_namespaces[i]).functions.find(node->name); + if (function_iter != global_info_.GetNamespaceInfo(path_namespaces[i]).functions.end()) { + auto& maybe_declaration_info = global_info_.GetFunctionInfo(function_iter->second).declaration; + + if (maybe_declaration_info.has_value()) { + node->function_id_ = function_iter->second; + maybe_function_declaration = maybe_declaration_info.value().node; + } + } + } + + if (maybe_function_declaration.has_value()) { + break; + } + } + + if (!maybe_function_declaration.has_value() && node->is_binary_operator_expression && node->arguments.size() > 0) { + Visitor::Visit(node->arguments[0]); + maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_); + if (maybe_function_declaration.has_value()) { + node->is_method_of_first_argument_ = true; + } + } + + return maybe_function_declaration; +} + +std::optional + TypeCheckVisitor::FindAbstractTypeTypeclassFunctionAndUpdate( + FunctionCallExpression* node, + info::type::AbstractType* abstract_type_info, + bool is_method) { + std::optional maybe_function_declaration; + + utils::IdType graph_id = abstract_type_info->GetGraphId(); + + if (!typeclass_graph_.IsFunctionInVertex(node->name, graph_id)) { + return std::nullopt; + } + + auto maybe_typeclass_function_info = typeclass_graph_.GetFunctionInfo(node->name, graph_id); + + if (!maybe_typeclass_function_info.has_value()) { + error_handling::HandleTypecheckError("Function not present in typeclass (abstract type)", node->base); + } + + // TODO: check that const functions not called on var expressions ?? + if ((maybe_typeclass_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) { + error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); + } + + node->graph_id_ = graph_id; + AddGraphIdLocalAbstractTypes(node->graph_id_.value()); // check + + node->abstract_type_name_ = typeclass_graph_.GetVertex(node->graph_id_.value()).name; + maybe_function_declaration = maybe_typeclass_function_info.value()->declaration; + + return maybe_function_declaration; +} + +std::optional + TypeCheckVisitor::FindDefinedTypeFunctionAndUpdate( + FunctionCallExpression* node, + info::definition::AnyType* defined_type, + utils::IdType type, + bool is_method) { + std::optional maybe_function_declaration; + + auto maybe_type_function_info = typeclass_graph_.GetFunctionInfo(node->name, defined_type->type.node->graph_id_); + + if (!maybe_type_function_info.has_value()) { + return std::nullopt; + // error_handling::HandleTypecheckError("Function is not declared in type", node->base); + } + + // TODO: check that const functions not called on var expressions ?? + if ((maybe_type_function_info.value()->modifier != utils::ClassInternalsModifier::Static) != is_method) { + error_handling::HandleTypecheckError("Typeclass function has wrong modifier (abstract type)", node->base); + } + + node->graph_id_ = defined_type->type.node->graph_id_; + + AddGraphIdLocalTypes(node->graph_id_.value(), type); + + + // type defined -> abstract type name not needed + maybe_function_declaration = maybe_type_function_info.value()->declaration; + + return maybe_function_declaration; +} + +} // namespace interpreter diff --git a/src/typeclass_graph.cpp b/src/typeclass_graph.cpp new file mode 100644 index 0000000..8cef103 --- /dev/null +++ b/src/typeclass_graph.cpp @@ -0,0 +1,162 @@ +// for clangd +#include "../include/typeclass_graph.hpp" +#include "../include/error_handling.hpp" + +namespace info { + +utils::IdType TypeclassGraph::AddVertex( + const std::string& name, + const std::vector& dependencies, // TODO: parameters + const std::vector>>& function_declarations, + const std::vector>& function_definitions, + interpreter::tokens::BaseNode* base_node, + Modifier modifier) { + + if (name_to_typeclass_.count(name) != 0) { + error_handling::HandleTypecheckError("Typeclass \"" + name + "\" already defined (other type / typeclass can't have this name)", *base_node); + } + + if (modifier == Modifier::Typeclass) { + for (auto& method : function_declarations) { + if (method_to_vertex_.count(method.first) != 0) { + error_handling::HandleTypecheckError("Typeclass \"" + name + "\" method \"" + method.first + "\" already declaret in another typeclass", *base_node); + } + } + } + + is_calculated_ = false; + + utils::IdType id = verticles_.size(); + + verticles_.emplace_back(); + Vertex& vertex = verticles_.back(); + vertex.name = name; + vertex.base_node = base_node; + vertex.modifier = modifier; + + for (auto& dependency : dependencies) { + vertex.dependencies.insert(dependency); + } + + for (auto& method : function_declarations) { + FunctionInfo function_info; + function_info.modifier = method.second.first; + function_info.declaration = method.second.second; + + vertex.functions[method.first] = function_info; + + if (modifier == Modifier::Typeclass) { + method_to_vertex_[method.first] = id; + } + } + if (modifier == Modifier::Typeclass) { + name_to_typeclass_[name] = id; + } + + for (auto& method : function_definitions) { + FunctionInfo& function_info = vertex.functions[method.first]; + function_info.definition = method.second; + function_info.is_defined_in_owner = true; + } + + return id; +} + +std::optional TypeclassGraph::FindFunctionTypeclass(const std::string& name) { + auto function_iter = method_to_vertex_.find(name); + if (function_iter == method_to_vertex_.end()) { + return std::nullopt; + } + return function_iter->second; +} + +std::optional TypeclassGraph::GetFunctionInfo(const std::string& name, + std::optional vertex_id) { + if (vertex_id.has_value()) { + auto function_info_iter = verticles_[vertex_id.value()].functions.find(name); + return function_info_iter != + verticles_[vertex_id.value()].functions.end() + ? std::optional(&function_info_iter->second) + : std::nullopt; + } + + auto maybe_function_typeclass_id = FindFunctionTypeclass(name); + + if (!maybe_function_typeclass_id.has_value()) { + return std::nullopt; + } + + return &verticles_[maybe_function_typeclass_id.value()].functions[name]; +} + +std::unordered_set TypeclassGraph::GetDependenciesSet(utils::IdType id) { + std::unordered_set dependencies; + + dependencies.reserve(verticles_.at(id).dependencies.size()); + for (auto& dependency : verticles_[id].dependencies) { + dependencies.insert(name_to_typeclass_[dependency]); + } + + return dependencies; +} + +std::vector TypeclassGraph::GetDependenciesVector(utils::IdType id) { + std::vector dependencies; + + dependencies.reserve(verticles_.at(id).dependencies.size()); + for (auto& dependency : verticles_[id].dependencies) { + dependencies.push_back(name_to_typeclass_[dependency]); + } + + return dependencies; +} + +void TypeclassGraph::CalculateGraph() { + if (is_calculated_) { + return; + } + + std::vector> edges(verticles_.size()); + + for (size_t i = 0; i < verticles_.size(); ++i) { + edges[i].reserve(verticles_[i].dependencies.size()); + for (auto& dependency : verticles_[i].dependencies) { + auto dependency_iter = name_to_typeclass_.find(dependency); + + if (dependency_iter == name_to_typeclass_.end()) { + error_handling::HandleTypecheckError("Dependency typeclass \"" + dependency + "\" not found", *verticles_[i].base_node); + } + + edges[i].push_back(dependency_iter->second); + } + } + + std::vector sorted_verticles = utils::BackTopSort(edges); + // std::reverse(sorted_verticles.begin(), sorted_verticles.end()); + + for (auto& id : sorted_verticles) { + for (auto& dependency : verticles_[id].dependencies) { + for (auto& method : verticles_[name_to_typeclass_[dependency]].functions) { + auto function_iter = verticles_[id].functions.find(method.first); + if (function_iter == verticles_[id].functions.end()) { + verticles_[id].functions[method.first] = method.second; + } else { + if (!function_iter->second.definition.has_value()) { + function_iter->second.definition = method.second.definition; + } else { + if (!function_iter->second.is_defined_in_owner) { + error_handling::HandleTypecheckError("Method \"" + method.first + "\" defined in more then one dependency of type / typeclass \"" + verticles_[id].name + "\"", *verticles_[id].base_node); + } + } + } + } + for (auto& inherited_dependency : verticles_[name_to_typeclass_[dependency]].dependencies) { + verticles_[id].dependencies.insert(inherited_dependency); + } + } + } + + is_calculated_ = true; +} + +} // namespace info diff --git a/src/typed_print_visitor.cpp b/src/typed_print_visitor.cpp new file mode 100644 index 0000000..c92bc83 --- /dev/null +++ b/src/typed_print_visitor.cpp @@ -0,0 +1,1059 @@ +// for clangd +#include "../include/typed_print_visitor.hpp" + +namespace interpreter { + +// Sources ----------------- + +void TypedPrintVisitor::Visit(SourceFile* node) { + out_ << "[SourceFile : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] (\n\n"; + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + out_ << "\n)\n"; +} + +// Namespaces, partitions ----------------- + +void TypedPrintVisitor::Visit(NamespaceSources* node) { + out_ << "[NamespaceSources : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "](\n"; + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(Namespace* node) { + out_ << "[Namespace : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] "; + switch (node->modifier) { + case utils::ClassInternalsModifier::Const: + out_ << "const "; + break; + case utils::ClassInternalsModifier::Var: + out_ << "var "; + break; + case utils::ClassInternalsModifier::Static: + break; + } + Visit(&node->type); + out_ << "{\n"; + Visit(&node->scope); + out_ << "}\n"; +} + +// Definitions ----------------- + +void TypedPrintVisitor::Visit(ImportStatement* node) { + if (node->name.has_value()) { + out_ << "[Use " << node->name.value() << "] = "; + } + out_ << "[Import " << node->module_name << "]"; + if (!node->symbols.empty()) { + out_ << " (\n"; + for (auto& symbol : node->symbols) { + Visit(&symbol); + out_ << '\n'; + } + out_ << ')'; + } + out_ << '\n'; +} + +void TypedPrintVisitor::Visit(AliasDefinitionStatement* node) { + out_ << "[Alias : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + switch (node->modifier) { + case utils::AliasModifier::Alias: + out_ << "alias"; + break; + case utils::AliasModifier::Type: + out_ << "type"; + break; + case utils::AliasModifier::Let: + out_ << "let"; + break; + } + out_ << ' '; + Visit(&node->type); + out_ << "] = ("; + Visit(node->value.get()); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(VariableDefinitionStatement* node) { + out_ << "[Variable : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + switch (node->modifier) { + case utils::IsConstModifier::Const: + out_ << "const"; + break; + case utils::IsConstModifier::Var: + out_ << "var"; + break; + } + out_ << ' '; + Visitor::Visit(node->name); + out_ << "] = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(FunctionDeclaration* node) { + out_ << "[FunctionDeclaration "; + if (node->is_in_interface) { + out_ << "interface "; + } + out_ << ": ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + Visit(&node->name); + out_ << "] ("; + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + out_ << ") : ("; + Visit(node->type.get()); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(FunctionDefinitionStatement* node) { + out_ << "[Function : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visit(node->definition.get()); + out_ << ") = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(TypeDefinitionStatement* node) { + out_ << "[Type : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + switch (node->modifier) { + case utils::ClassModifier::Struct: + out_ << "struct"; + break; + case utils::ClassModifier::Class: + out_ << "class"; + break; + } + if (node->is_in_interface) { + out_ << " interface"; + } + out_ << "] ("; + Visit(node->definition.get()); + out_ << ") = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(AbstractTypeDefinitionStatement* node) { + out_ << "[AbstractType : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + switch (node->modifier) { + case utils::AbstractTypeModifier::Basic: + out_ << "basic"; + break; + case utils::AbstractTypeModifier::Abstract: + out_ << "abstract"; + break; + } + out_ << "] ("; + Visit(node->type.get()); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(TypeclassDefinitionStatement* node) { + out_ << "[Typeclass : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visit(node->definition.get()); + if (!node->requirements.empty()) { + out_ << ") : (\n"; + } + for (auto& requirement : node->requirements) { + out_ << "& "; + switch (requirement.first) { + case utils::ClassInternalsModifier::Const: + out_ << "const "; + break; + case utils::ClassInternalsModifier::Var: + out_ << "var "; + break; + case utils::ClassInternalsModifier::Static: + break; + } + Visit(requirement.second.get()); + out_ << "\n"; + } + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(PartitionStatement* node) { + out_ << "[Partition : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + switch (node->modifier) { + case utils::PartitionModifier::Exec: + out_ << "exec "; + break; + case utils::PartitionModifier::Test: + out_ << "test "; + break; + } + Visit(&node->name); + out_ << "] = ("; + Visitor::Visit(node->value); + out_ << ")\n"; +} + +// Definition parts + +void TypedPrintVisitor::Visit(FunctionDefinition* node) { + out_ << "[FunctionDefinition : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + Visit(&node->name); + out_ << "]"; + if (!node->arguments.empty()) { + out_ << " : ("; + for (auto& argument : node->arguments) { + Visit(&argument); + } + out_ << ')'; + } + out_ << ' '; +} + +void TypedPrintVisitor::Visit(TypeDefinition* node) { + out_ << "[TypeDefinition : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visit(node->type.get()); + out_ << ')'; + if (!node->parameters.empty()) { + out_ << '('; + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + out_ << ')'; + } + out_ << ' '; +} + +void TypedPrintVisitor::Visit(AnyAnnotatedType* node) { + out_ << "[Annotated (Abstract) Type : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + Visit(&node->type); + out_ << ']'; + if (!node->typeclasses.empty()) { + out_ << " ("; + for (auto& typeclass : node->typeclasses) { + Visit(typeclass.get()); + } + out_ << ')'; + } + out_ << ' '; +} + +// Flow control ----------------- + +void TypedPrintVisitor::Visit(TypeConstructorPatternParameter* node) { + out_ << "[TypeConstructorPatternParameter : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + if (node->name.has_value()) { + Visit(&node->name.value()); + out_ << " = "; + } + Visitor::Visit(node->value); + out_ << "]"; +} + +void TypedPrintVisitor::Visit(TypeConstructorPattern* node) { + out_ << "[TypeConstructorPattern : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + Visit(node->constructor.get()); + out_ << "]\n("; + + bool is_first = true; + for (auto& parameter : node->parameters) { + if (!is_first) { + out_ << ")\n"; + } + is_first = false; + out_ << '('; + Visit(¶meter); + } + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(MatchCase* node) { + out_ << "[MatchCase | : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + Visitor::Visit(node->value); + if (node->condition.has_value()) { + out_ << " ? "; + Visitor::Visit(node->condition.value()); + } + if (node->statement.has_value()) { + out_ << " -> "; + Visitor::Visit(node->statement.value()); + } + out_ << "]\n"; +} + +void TypedPrintVisitor::Visit(Match* node) { + out_ << "[Match"; + + if (node->is_consuming_value) { + out_ << " <-"; + } + + out_ << " : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visitor::Visit(node->value); + out_ << ") [with] (\n"; + for (auto& match_case : node->matches) { + Visit(&match_case); + } + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(Condition* node) { + out_ << "[If : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visitor::Visit(node->conditions[0]); + out_ << ") [then] (\n"; + Visitor::Visit(node->statements[0]); + out_ << ')'; + for (size_t i = 1; i < node->conditions.size(); ++i) { + out_ << " [elif] ("; + Visitor::Visit(node->conditions[i]); + out_ << ") [then] (\n"; + Visitor::Visit(node->statements[i]); + out_ << ')'; + } + if (node->statements.size() > node->conditions.size()) { + out_ << " [else] (\n"; + Visitor::Visit(node->statements[node->conditions.size()]); + out_ << ')'; + } + out_ << '\n'; +} + +void TypedPrintVisitor::Visit(DoWhileLoop* node) { + out_ << "[Do : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] (\n"; + Visitor::Visit(node->statement); + out_ << ") [while] ("; + Visitor::Visit(node->condition); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(WhileLoop* node) { + out_ << "[While : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visitor::Visit(node->condition); + out_ << ") [do] (\n"; + Visitor::Visit(node->statement); + out_ << ")\n"; +} +void TypedPrintVisitor::Visit(ForLoop* node) { + out_ << "[For : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + switch (node->variable_modifier) { + case utils::IsConstModifier::Const: + break; + case utils::IsConstModifier::Var: + out_ << "var"; + break; + } + out_ << "] ("; + Visitor::Visit(node->variable); + out_ << ") [in] ("; + Visitor::Visit(node->interval); + out_ << ") [do] (\n"; + Visitor::Visit(node->statement); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(LoopLoop* node) { + out_ << "[Loop : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] (\n"; + Visitor::Visit(node->statement); + out_ << ")\n"; +} + +// Statements, expressions, blocks, etc. ----------------- + +void TypedPrintVisitor::Visit(Block* node) { + out_ << "[Block : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] {\n"; + for (auto& statement : node->statements) { + Visitor::Visit(statement); + } + out_ << "}\n"; +} + +void TypedPrintVisitor::Visit(ScopedStatement* node) { + out_ << "[Scoped : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ( "; + Visitor::Visit(node->statement); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(LoopControlExpression& node) { // enum + switch (node) { + case LoopControlExpression::Break: + out_ << "[Break]\n"; + break; + case LoopControlExpression::Continue: + out_ << "[Continue]\n"; + break; + } +} + +// Operators + +void TypedPrintVisitor::Visit(ReferenceExpression* node) { + out_ << "[ReferenceExpression : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + switch (node->reference) { + case utils::ReferenceModifier::Reference: + out_ << '^'; + break; + case utils::ReferenceModifier::UniqueReference: + out_ << '@'; + break; + case utils::ReferenceModifier::Dereference: + out_ << '~'; + break; + } + out_ << "] ("; + Visit(node->expression.get()); + out_ << ')'; +} + +void TypedPrintVisitor::Visit(AccessExpression* node) { + out_ << "[AccessExpression : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visit(node->name.get()); + out_ << ") ` ("; + Visitor::Visit(node->id); + out_ << ')'; +} + +// Other Expressions + +void TypedPrintVisitor::Visit(FunctionCallExpression* node) { + out_ << "[FunctionCall : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + + if (node->is_binary_operator_expression) { + out_ << "(binary operation) "; + } + + if (node->prefix.has_value()) { + out_ << '('; + if (std::holds_alternative>(node->prefix.value())) { + Visitor::Visit(*std::get>(node->prefix.value())); + } else if (std::holds_alternative>(node->prefix.value())) { + Visit(std::get>(node->prefix.value()).get()); + } else { + // error + } + out_ << ")."; + } + + Visit(&node->name); + + out_ << "] ("; + + bool is_first = true; + for (auto& parameter : node->parameters) { + if (!is_first) { + out_ << ", "; + } + is_first = false; + + Visit(parameter.get()); + } + + out_ << ") : ("; + + is_first = true; + for (auto& argument : node->arguments) { + if (!is_first) { + out_ << ", "; + } + is_first = false; + + Visitor::Visit(argument); + } + out_ << ")"; +} + +void TypedPrintVisitor::Visit(TupleExpression* node) { + out_ << "[TupleExpression : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (auto& expression : node->expressions) { + out_ << "&"; + Visitor::Visit(expression); + } + out_ << ")"; +} + +void TypedPrintVisitor::Visit(VariantExpression* node) { + out_ << "[VariantExpression : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (auto& expression : node->expressions) { + out_ << "|"; + Visitor::Visit(expression); + } + out_ << ")"; +} + +void TypedPrintVisitor::Visit(ReturnExpression* node) { + if (node->is_from_definition) { + out_ << "[Return : "; + } else { + out_ << "[Bring : "; + } + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visitor::Visit(node->expression); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(TypeConstructorParameter* node) { + out_ << "[TypeConstructorParameter : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + if (node->name.has_value()) { + Visit(&node->name.value()); + switch (node->asignment_modifier.value()) { + case utils::AssignmentModifier::Assign: + out_ << " = "; + break; + case utils::AssignmentModifier::Move: + out_ << " <- "; + break; + } + } + Visitor::Visit(node->value); + out_ << "]"; +} + +void TypedPrintVisitor::Visit(TypeConstructor* node) { + out_ << "[TypeConstructor : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + Visit(node->constructor.get()); + out_ << "]\n("; + + bool is_first = true; + for (auto& parameter : node->parameters) { + if (!is_first) { + out_ << ")\n"; + } + is_first = false; + out_ << '('; + Visit(¶meter); + } + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(LambdaFunction* node) { + out_ << "[LambdaFunction : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (auto& parameter : node->parameters) { + Visit(parameter.get()); + } + if (!node->parameters.empty()) { + out_ << ") : ("; + } + for (auto& argument : node->arguments) { + Visit(&argument); + } + out_ << ") -> (\n"; + Visitor::Visit(node->expression); + out_ << ")\n"; +} + +void TypedPrintVisitor::Visit(ArrayExpression* node) { + out_ << "[ArrayExpression : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ( ,"; + for (auto& element : node->elements) { + Visitor::Visit(element); + out_ << " ,"; + } + out_ << ")"; +} + +// Name + +void TypedPrintVisitor::Visit(PartitionName* node) { + out_ << "[PartitionName : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (size_t i = 0; i < node->path.size(); ++i) { + Visit(&node->path[i]); + if (i + 1 < node->path.size()) { + out_ << "::"; + } + } + out_ << ')'; +} + +void TypedPrintVisitor::Visit(NameExpression* node) { + out_ << "[NameExpression : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (size_t i = 0; i < node->names.size(); ++i) { + Visit(&node->names[i]); + if (i + 1 < node->names.size()) { + out_ << "::"; + } + } + out_ << ')'; +} + +void TypedPrintVisitor::Visit(TupleName* node) { + out_ << "[TupleName : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (auto& name : node->names) { + out_ << "& "; + Visitor::Visit(name); + } + out_ << ')'; +} + +void TypedPrintVisitor::Visit(VariantName* node) { + out_ << "[VariantName : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + for (auto& name : node->names) { + out_ << "| "; + Visitor::Visit(name); + } + out_ << ')'; +} + +void TypedPrintVisitor::Visit(AnnotatedName* node) { + out_ << "[AnnotatedName : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + Visit(&node->name); + out_ << ']'; + if (node->type.has_value()) { + out_ << " : ("; + Visitor::Visit(node->type.value()); + out_ << ')'; + } +} + +// Type, typeclass, etc. ----------------- + +// Type + +void TypedPrintVisitor::Visit(FunctionType* node) { + out_ << "[FunctionType : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + bool is_first = true; + for (auto& type : node->types) { + if (!is_first || node->types.size() == 1) { + out_ << " -> "; + } + is_first = false; + Visitor::Visit(type); + } + out_ << ')'; +} + +void TypedPrintVisitor::Visit(TupleType* node) { + out_ << "[TupleType : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + 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_ << " : "; + } + Visit(entity.second.get()); + } + out_ << ')'; +} + +void TypedPrintVisitor::Visit(VariantType* node) { + out_ << "[VariantType : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + 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 TypedPrintVisitor::Visit(TypeExpression* node) { + out_ << "[TypeExpression : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + if (node->array_size.has_value()) { + out_ << "[array size: " << node->array_size.value() << ']'; + } + + out_ << "] ("; + for (auto& type : node->path) { + Visit(&type); + out_ << "::"; + } + Visit(&node->type); + out_ << ')'; +} + +void TypedPrintVisitor::Visit(ExtendedScopedAnyType* node) { + out_ << "[ExtendedScopedAnyType : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") "; + for (auto& reference : node->references) { + switch (reference) { + case utils::ReferenceModifier::Reference: + out_ << '^'; + break; + case utils::ReferenceModifier::UniqueReference: + out_ << '@'; + break; + case utils::ReferenceModifier::Dereference: + out_ << '~'; + break; + } + } + out_ << "] ("; + Visitor::Visit(node->type); + out_ << ')'; +} + +// Typeclass + +void TypedPrintVisitor::Visit(ParametrizedTypeclass* node) { + out_ << "[ParametrizedTypeclass] ("; // print type?? + Visit(&node->typeclass); + for (auto& parameter : node->parameters) { + out_ << ' '; + Visit(parameter.get()); + } + out_ << ')'; +} + +// Typeclass & Type ----------------- + +void TypedPrintVisitor::Visit(ParametrizedType* node) { + out_ << "[ParametrizedType : "; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << "] ("; + Visit(&node->type); + for (auto& parameter : node->parameters) { + out_ << ' '; + Visit(parameter.get()); + } + out_ << ')'; +} + +// Identifiers, constants, etc. ----------------- + +void TypedPrintVisitor::Visit(std::string* node) { // std::string + out_ << "[Identifier " << *node << "] "; +} + +void TypedPrintVisitor::Visit(FloatNumberLiteral* node) { + out_ << "[FloatNumber : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") " << node->value << "] "; +} + +void TypedPrintVisitor::Visit(NumberLiteral* node) { + out_ << "[Number : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") " << node->value << "] "; +} + +void TypedPrintVisitor::Visit(StringLiteral* node) { + out_ << "[String : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") " << node->value << "] "; +} + +void TypedPrintVisitor::Visit(CharLiteral* node) { + out_ << "[Char : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") " << node->value << "] "; +} + +void TypedPrintVisitor::Visit(UnitLiteral* node) { + out_ << "[Unit : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") ()] "; +} + +void TypedPrintVisitor::Visit(BoolLiteral* node) { + out_ << "[bool : ("; + + if (node->base.type_.has_value()) { + out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); + } + + out_ << ") " << (node->value ? "true" : "false") << "] "; +} + +} // namespace interpreter diff --git a/src/types.cpp b/src/types.cpp new file mode 100644 index 0000000..9bf19af --- /dev/null +++ b/src/types.cpp @@ -0,0 +1,588 @@ +// for clangd +#include "../include/types.hpp" +#include + +namespace info::type { + +std::optional AbstractType::InContext(const std::unordered_map& context) { + auto type_iter = context.find(typeclass_graph_.GetVertex(graph_id_).name); + + if (type_iter != context.end()) { + return type_iter->second; + } + return std::nullopt; +} + +bool AbstractType::Same(const AbstractType& type) const { + return graph_id_ == type.graph_id_; +} + +bool AbstractType::operator<(const AbstractType& type) const { // TODO: cache DependenciesSet + return typeclass_graph_.GetDependenciesSet(graph_id_).count(type.graph_id_) != 0 || graph_id_ == type.graph_id_; +} + +bool AbstractType::operator>(const AbstractType& type) const { + return type < *this; +} + +std::optional AbstractType::GetFieldType(const std::string&, + const std::unordered_set&) const { + return std::nullopt; +} + +// + +std::optional DefinedType::InContext(const std::unordered_map& context) { + std::optional maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context); + + if (maybe_type_replacement.has_value()) { + type_ = maybe_type_replacement.value(); + } + + return std::nullopt; +} + +bool DefinedType::Same(const DefinedType& type) const { + return type_id_ == type.type_id_ + && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); +} + +bool DefinedType::operator<(const DefinedType& type) const { + return type_id_ == type.type_id_ + && *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_); +} + +bool DefinedType::operator>(const DefinedType& type) const { + return type < *this; +} + +std::optional DefinedType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { + if (class_modifier_ == utils::ClassModifier::Struct || type_namespaces.count(type_id_) != 0) { + return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces); + } + return std::nullopt; +} + +// + +std::optional TupleType::InContext(const std::unordered_map& context) { + for (size_t i = 0; i < fields_.size(); ++i) { + std::optional maybe_field_replacement = type_manager_->GetAnyValue(fields_[i].second)->InContext(context); + + if (maybe_field_replacement.has_value()) { + fields_[i].second = maybe_field_replacement.value(); + } + } + + return std::nullopt; +} + +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_->GetAnyValue(fields_[i].second)->Same(*type_manager_->GetAnyValue(type.fields_[i].second))) { + 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_->GetAnyValue(fields_[i].second) < *type_manager_->GetAnyValue(type.fields_[i].second))) { + return false; + } + } + + return true; +} + +bool TupleType::operator>(const TupleType& type) const { + return type < *this; +} + +std::optional TupleType::GetFieldType(const std::string& name, + const std::unordered_set&) const { + for (size_t i = 0; i < fields_.size(); ++i) { // TODO: optimize?? + if (fields_[i].first.has_value() && fields_[i].first.value() == name) { + return fields_[i].second; + } + } + return std::nullopt; +} + +std::string TupleType::ToString() { + std::string result; + + result += "("; + + for (auto& field : fields_) { + result += "& "; + result += type_manager_->GetAnyValue(field.second)->ToString(); + } + + result += ")"; + + return result; +} + +// + +std::optional VariantType::InContext(const std::unordered_map& context) { + for (size_t i = 0; i < constructors_.size(); ++i) { + constructors_[i].InContext(context); + } + + return std::nullopt; +} + +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; +} + +std::optional VariantType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { + if (current_constructor_.has_value()) { + return constructors_.at(current_constructor_.value()).GetFieldType(name, type_namespaces); + } + return std::nullopt; +} + +std::string VariantType::ToString() { + std::string result; + + result += "("; + + for (auto& constructor : constructors_) { + result += "& "; + result += constructor.ToString(); + } + + result += ")"; + + return result; +} + +// + +std::optional OptionalType::InContext(const std::unordered_map& context) { + std::optional maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context); + + if (maybe_type_replacement.has_value()) { + type_ = maybe_type_replacement.value(); + } + + return std::nullopt; +} + +bool OptionalType::Same(const OptionalType& type) const { + return type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); +} + +bool OptionalType::operator<(const OptionalType& type) const { + return *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_); +} + +bool OptionalType::operator>(const OptionalType& type) const { + return type < *this; +} + +std::optional OptionalType::GetFieldType(const std::string&, + const std::unordered_set&) const { + return std::nullopt; +} + +std::string OptionalType::ToString() { + return "Optional " + type_manager_->GetAnyValue(type_)->ToString(); +} + +// + +std::optional ReferenceToType::InContext(const std::unordered_map& context) { + std::optional maybe_type_replacement = type_manager_->GetAnyValue(type_)->InContext(context); + + if (maybe_type_replacement.has_value()) { + type_ = maybe_type_replacement.value(); + } + + return std::nullopt; +} + +bool ReferenceToType::Same(const ReferenceToType& type) const { + return references_ == type.references_ && type_manager_->GetAnyValue(type_)->Same(*type_manager_->GetAnyValue(type.type_)); +} + +bool ReferenceToType::operator<(const ReferenceToType& type) const { + return references_ == type.references_ && *type_manager_->GetAnyValue(type_) < *type_manager_->GetAnyValue(type.type_); +} + +bool ReferenceToType::operator>(const ReferenceToType& type) const { + return type < *this; +} + +std::optional ReferenceToType::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { + return type_manager_->GetAnyValue(type_)->GetFieldType(name, type_namespaces); +} + + +std::string ReferenceToType::ToString() { + std::string result; + + for (auto& reference : references_) { + switch (reference) { + case utils::ReferenceModifier::Dereference: + result += '~'; + break; + case utils::ReferenceModifier::Reference: + result += '^'; + break; + case utils::ReferenceModifier::UniqueReference: + result += '@'; + break; + } + } + + result += type_manager_->GetAnyValue(type_)->ToString(); + + return result; +} + +// + +std::optional FunctionType::InContext(const std::unordered_map& context) { + for (size_t i = 0; i < argument_types_.size(); ++i) { + std::optional maybe_argument_type_replacement = + type_manager_->GetAnyValue(argument_types_[i])->InContext(context); + + if (maybe_argument_type_replacement.has_value()) { + argument_types_[i] = maybe_argument_type_replacement.value(); + } + } + + return std::nullopt; +} + +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_->GetAnyValue(argument_types_[i])->Same(*type_manager_->GetAnyValue(type.argument_types_[i]))) { + 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_->GetAnyValue(argument_types_[i]) < *type_manager_->GetAnyValue(type.argument_types_[i]))) { + return false; + } + } + + return true; +} + +bool FunctionType::operator>(const FunctionType& type) const { + return type < *this; +} + +std::optional FunctionType::GetFieldType(const std::string&, + const std::unordered_set&) const { + return std::nullopt; +} + +std::string FunctionType::ToString() { + std::string result; + + result += "("; + + bool is_first_argument = true; + for (auto& argument_type : argument_types_) { + if (is_first_argument) { + is_first_argument = false; + } else { + result += " -> "; + } + result += type_manager_->GetAnyValue(argument_type)->ToString(); + } + + result += " -> " + type_manager_->GetAnyValue(return_type_)->ToString() + ")"; + + return result; +} + +// + +std::optional ArrayType::InContext(const std::unordered_map& context) { + std::optional maybe_elements_type_replacement = + type_manager_->GetAnyValue(elements_type_)->InContext(context); + + if (maybe_elements_type_replacement.has_value()) { + elements_type_ = maybe_elements_type_replacement.value(); + } + + return std::nullopt; +} + +bool ArrayType::Same(const ArrayType& type) const { + return size_ == type.size_ && type_manager_->GetAnyValue(elements_type_)->Same(*type_manager_->GetAnyValue(type.elements_type_)); +} + +bool ArrayType::operator<(const ArrayType& type) const { + return size_ == type.size_ && *type_manager_->GetAnyValue(elements_type_) < *type_manager_->GetAnyValue(type.elements_type_); +} + +bool ArrayType::operator>(const ArrayType& type) const { + return type < *this; +} + +std::optional ArrayType::GetFieldType(const std::string&, + const std::unordered_set&) const { + return std::nullopt; +} + +std::string ArrayType::ToString() { + return "Array (" + std::to_string(size_) + ") " + type_manager_->GetAnyValue(elements_type_)->ToString(); +} + +// + +std::optional Type::InContext(const std::unordered_map& context) { + size_t this_index = type_.index(); + + switch (this_index) { + case 0: + return std::get(type_).InContext(context); + case 1: + return std::get(type_).InContext(context); + case 2: + return std::nullopt; + case 3: + return std::get(type_).InContext(context); + case 4: + return std::get(type_).InContext(context); + case 5: + return std::get(type_).InContext(context); + case 6: + return std::get(type_).InContext(context); + case 7: + return std::get(type_).InContext(context); + case 8: + return std::get(type_).InContext(context); + default: + // error + break; + } + + return std::nullopt; +} + +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(type_).Same(std::get(type.type_)); + case 1: + return std::get(type_).Same(std::get(type.type_)); + case 2: + return std::get(type_) == std::get(type.type_); + case 3: + return std::get(type_).Same(std::get(type.type_)); + case 4: + return std::get(type_).Same(std::get(type.type_)); + case 5: + return std::get(type_).Same(std::get(type.type_)); + case 6: + return std::get(type_).Same(std::get(type.type_)); + case 7: + return std::get(type_).Same(std::get(type.type_)); + case 8: + return std::get(type_).Same(std::get(type.type_)); + default: + // error + break; + } + } + + return false; +} + +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(type_) < std::get(type.type_); + case 1: + return std::get(type_) < std::get(type.type_); + case 2: + return std::get(type_) == std::get(type.type_); + case 3: + return std::get(type_) < std::get(type.type_); + case 4: + return std::get(type_) < std::get(type.type_); + case 5: + return std::get(type_) < std::get(type.type_); + case 6: + return std::get(type_) < std::get(type.type_); + case 7: + return std::get(type_) < std::get(type.type_); + case 8: + return std::get(type_) < std::get(type.type_); + default: + // error + break; + } + } + + return false; +} + +bool Type::operator>(const Type& type) const { + return type < *this; +} + +std::optional Type::GetFieldType(const std::string& name, + const std::unordered_set& type_namespaces) const { + size_t index = type_.index(); + + switch (index) { + case 0: + return std::get(type_).GetFieldType(name, type_namespaces); + case 1: + return std::get(type_).GetFieldType(name, type_namespaces); + case 2: + return std::nullopt; + case 3: + return std::get(type_).GetFieldType(name, type_namespaces); + case 4: + return std::get(type_).GetFieldType(name, type_namespaces); + case 5: + return std::get(type_).GetFieldType(name, type_namespaces); + case 6: + return std::get(type_).GetFieldType(name, type_namespaces); + case 7: + return std::get(type_).GetFieldType(name, type_namespaces); + case 8: + return std::get(type_).GetFieldType(name, type_namespaces); + default: + // error + break; + } + + return std::nullopt; +} + +std::string Type::GetTypeName() const { + size_t index = type_.index(); + + switch (index) { + case 0: + return "AbstractType"; + case 1: + return "DefinedType"; + case 2: + return "Builtin"; + case 3: + return "TupleType"; + case 4: + return "VariantType"; + case 5: + return "ReferenceToType"; + case 6: + return "FunctionType"; + case 7: + return "ArrayType"; + case 8: + return "OptionalType"; + default: + // error + break; + } + + return ""; // ?? +} + +std::string Type::ToString() { + size_t index = type_.index(); + + switch (index) { + case 0: + return std::get(type_).ToString(); + case 1: + return std::get(type_).ToString(); + case 2: + return ::info::type::ToString(std::get(type_)); + case 3: + return std::get(type_).ToString(); + case 4: + return std::get(type_).ToString(); + case 5: + return std::get(type_).ToString(); + case 6: + return std::get(type_).ToString(); + case 7: + return std::get(type_).ToString(); + case 8: + return std::get(type_).ToString(); + default: + // error + break; + } + + return ""; +} + +} // namespace info::type + diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..1bbebd1 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,92 @@ +// for clangd +#include "../include/utils.hpp" +#include"../include/error_handling.hpp" + +namespace utils { + +using std::size_t; + +using IdType = size_t; + +ValueType IsConstModifierToValueType(IsConstModifier modifier) { + switch (modifier) { + case IsConstModifier::Const: + return ValueType::Const; + case IsConstModifier::Var: + return ValueType::Var; + } + + exit(1); // unreachable +} + +ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier) { + switch (modifier) { + case ClassInternalsModifier::Const: + return ValueType::Const; + case ClassInternalsModifier::Var: + return ValueType::Var; + case ClassInternalsModifier::Static: + throw std::bad_cast(); // ?? + } + + exit(1); // unreachable +} + +bool IsBuiltinFunction(const std::string& name) { // optimize ?? + std::unordered_set builtin_functions; + + builtin_functions.insert("="); // TODO: for all types + // builtin_functions.insert("<-"); // TODO + builtin_functions.insert("=="); + builtin_functions.insert("<"); + builtin_functions.insert("+="); + builtin_functions.insert("-="); + builtin_functions.insert("*="); + builtin_functions.insert("div"); + builtin_functions.insert("mod"); + builtin_functions.insert("/="); + builtin_functions.insert("size"); + builtin_functions.insert("random"); + builtin_functions.insert("print"); + builtin_functions.insert("scan"); + builtin_functions.insert("zero"); + builtin_functions.insert("one"); + builtin_functions.insert("show"); + builtin_functions.insert("read"); + // builtin_functions.insert("debug_show"); // TODO + + return builtin_functions.count(name) != 0; +} + +void BackVisitDfs(size_t id, + std::vector& verticles, + std::vector& marks, + const std::vector>& edges, + size_t mark) { + if (marks[id] != 0) { + return; + } + + marks[id] = mark; + + for (size_t i = 0; i < edges[id].size(); ++i) { + BackVisitDfs(edges[id][i], verticles, marks, edges, mark); + } + + verticles.push_back(id); +} + +std::vector BackTopSort(const std::vector>& edges_) { + std::vector sorted_verticles; + std::vector marks(edges_.size(), 0); + + for (size_t i = 0; i < edges_.size(); ++i) { + if (marks[i] == 0) { + BackVisitDfs(i, sorted_verticles, marks, edges_, 1); + } + } + + return sorted_verticles; +} + +} // namespace utils diff --git a/src/values.cpp b/src/values.cpp new file mode 100644 index 0000000..676d358 --- /dev/null +++ b/src/values.cpp @@ -0,0 +1,308 @@ +#include + +// for clangd +#include "../include/values.hpp" +#include "../include/error_handling.hpp" + +namespace info::value { + +bool InternalValue::Same(const InternalValue& other_value) const { + size_t this_index = value.index(); + size_t other_index = other_value.value.index(); + + if (this_index == other_index) { + switch (this_index) { + case 0: + return std::get(value) == std::get(other_value.value); + case 1: + return std::get(value) == std::get(other_value.value); + case 2: + return std::get(value) == std::get(other_value.value); + case 3: + return std::get(value) == std::get(other_value.value); + case 4: + return std::get(value) == std::get(other_value.value); + case 5: // Unit + return true; + default: + // error + break; + } + } + + return false; +} + +std::optional InternalValue::GetFieldValue(const std::string&) const { + return std::nullopt; +} + +utils::IdType InternalValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + return value_manager->ExplicitAddValue(InternalValue(value), new_value_type); +} + +// + +bool TupleValue::Same(const TupleValue& other_value) const { + // TODO: check, that type is same ?? (checked in typecheck ??) + if (fields.size() != other_value.fields.size()) { + return false; + } + for (size_t i = 0; i < fields.size(); ++i) { // compare field names ?? (checked in typecheck ??) + if (!value_manager_->GetAnyValue(fields[i].second)->Same(*value_manager_->GetAnyValue(other_value.fields[i].second))) { + return false; + } + } + return true; +} + +std::optional TupleValue::GetFieldValue(const std::string& name) const { + for (size_t i = 0; i < fields.size(); ++i) { // TODO: optimize?? + if (fields[i].first.has_value() && fields[i].first.value() == name) { + return fields[i].second; + } + } + return std::nullopt; +} + +utils::IdType TupleValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + std::vector, utils::IdType>> fields_copy(fields.size()); + + for (size_t i = 0; i < fields.size(); ++i) { + fields_copy[i] = {fields[i].first, value_manager_->GetAnyValue(fields[i].second)->DeepCopy(value_manager, new_value_type)}; + } + + return value_manager->ExplicitAddValue( + TupleValue(std::move(fields_copy), value_manager), + new_value_type); +} + +// + +bool VariantValue::Same(const VariantValue& other_value) const { + // TODO: check, that type is same ?? (checked in typecheck ??) + if (current_constructor != other_value.current_constructor) { + return false; + } + + return value.Same(other_value.value); +} + +std::optional VariantValue::GetFieldValue(const std::string& name) const { + return value.GetFieldValue(name); +} + +utils::IdType VariantValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + auto maybe_tuple_deep_copy = value_manager->GetValue(value.DeepCopy(value_manager, new_value_type)); + + if (!maybe_tuple_deep_copy) { + error_handling::HandleInternalError("Deep copied TupleType in not TupleType", + "VariantValue.DeepCopy", + std::nullopt); + } + + return value_manager->ExplicitAddValue( + VariantValue(TupleValue(*maybe_tuple_deep_copy.value()), current_constructor), + new_value_type); +} + +// + +bool ReferenceToValue::Same(const ReferenceToValue& other_value) const { + if (references.size() != other_value.references.size()) { + return false; + } + for (size_t i = 0; i < references.size(); ++i) { + if (references[i] != other_value.references[i]) { + return false; + } + } + return value_manager_->GetAnyValue(value)->Same(*value_manager_->GetAnyValue(other_value.value)); +} + +std::optional ReferenceToValue::GetFieldValue(const std::string& name) const { + return value_manager_->GetAnyValue(value)->GetFieldValue(name); +} + +utils::IdType ReferenceToValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + return value_manager->ExplicitAddValue( + ReferenceToValue(references, value_manager_->GetAnyValue(value)->DeepCopy(value_manager, new_value_type), value_manager), + new_value_type); +} + + +// + +bool FunctionValue::Same(const FunctionValue& other_value) const { + size_t this_index = function.index(); + size_t other_index = other_value.function.index(); + + if (this_index == other_index) { + switch (this_index) { + case 0: + return std::get(function) == std::get(other_value.function); + case 1: + return std::get(function) == std::get(other_value.function); + default: + // error + break; + } + } + + return false; +} + +std::optional FunctionValue::GetFieldValue(const std::string&) const { + return std::nullopt; +} + +utils::IdType FunctionValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + return value_manager->ExplicitAddValue( + FunctionValue(function, value_manager), + new_value_type); +} + +// + +bool ArrayValue::Same(const ArrayValue& other_value) const { + if (is_constant_size != other_value.is_constant_size + || elements.size() != other_value.elements.size()) { + return false; + } + for (size_t i = 0; i < elements.size(); ++i) { + if (!value_manager_->GetAnyValue(elements[i])->Same(*value_manager_->GetAnyValue(other_value.elements[i]))) { + return false; + } + } + return true; +} + +std::optional ArrayValue::GetFieldValue(const std::string&) const { + return std::nullopt; +} + +utils::IdType ArrayValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + std::vector elements_copy(elements.size()); + + for (size_t i = 0; i < elements.size(); ++i) { + elements_copy[i] = value_manager_->GetAnyValue(elements[i])->DeepCopy(value_manager, new_value_type); + } + + return value_manager->ExplicitAddValue( + ArrayValue(std::move(elements_copy), is_constant_size, value_manager), + new_value_type); +} + +// + +bool OptionalValue::Same(const OptionalValue& other_value) const { + if (value.has_value() != other_value.value.has_value()) { + return false; + } + if (value.has_value()) { // => other_value.value.has_value() + return value_manager_->GetAnyValue(value.value())->Same(*value_manager_->GetAnyValue(other_value.value.value())); + } + + return true; +} + +std::optional OptionalValue::GetFieldValue(const std::string&) const { + return std::nullopt; +} + +utils::IdType OptionalValue::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + if (!value.has_value()) { + return value_manager->ExplicitAddValue( + OptionalValue(std::nullopt, value_manager), + utils::ValueType::Tmp); + } + + return value_manager->ExplicitAddValue( + OptionalValue(value_manager_->GetAnyValue(value.value())->DeepCopy(value_manager, new_value_type), value_manager), + new_value_type); +} + +// + +bool Value::Same(const Value& other_value) const { + size_t this_index = value.index(); + size_t other_index = other_value.value.index(); + + if (this_index == other_index) { + switch (this_index) { + case 0: + return std::get(value).Same(std::get(other_value.value)); + case 1: + return std::get(value).Same(std::get(other_value.value)); + case 2: + return std::get(value).Same(std::get(other_value.value)); + case 3: + return std::get(value).Same(std::get(other_value.value)); + case 4: + return std::get(value).Same(std::get(other_value.value)); + case 5: + return std::get(value).Same(std::get(other_value.value)); + case 6: + return std::get(value).Same(std::get(other_value.value)); + default: + // error + break; + } + } + + return false; +} + +std::optional Value::GetFieldValue(const std::string& name) const { + size_t index = value.index(); + + switch (index) { + case 0: + return std::get(value).GetFieldValue(name); + case 1: + return std::get(value).GetFieldValue(name); + case 2: + return std::get(value).GetFieldValue(name); + case 3: + return std::get(value).GetFieldValue(name); + case 4: + return std::get(value).GetFieldValue(name); + case 5: + return std::get(value).GetFieldValue(name); + case 6: + return std::get(value).GetFieldValue(name); + default: + // error + break; + } + + return std::nullopt; +} + +utils::IdType Value::DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type) { + size_t index = value.index(); + + switch (index) { + case 0: + return std::get(value).DeepCopy(value_manager, new_value_type); + case 1: + return std::get(value).DeepCopy(value_manager, new_value_type); + case 2: + return std::get(value).DeepCopy(value_manager, new_value_type); + case 3: + return std::get(value).DeepCopy(value_manager, new_value_type); + case 4: + return std::get(value).DeepCopy(value_manager, new_value_type); + case 5: + return std::get(value).DeepCopy(value_manager, new_value_type); + case 6: + return std::get(value).DeepCopy(value_manager, new_value_type); + default: + // error + break; + } + + exit(1); // better error handling ?? +} + +}; // namespace info::value diff --git a/src/visitor.cpp b/src/visitor.cpp new file mode 100644 index 0000000..86450a7 --- /dev/null +++ b/src/visitor.cpp @@ -0,0 +1,663 @@ +// for clangd +#include "../include/visitor.hpp" + +namespace interpreter { + +// Definitions ----------------- + +void Visitor::Visit(NamespaceStatement& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + case 3: + Visit(std::get>(node).get()); + break; + case 4: + Visit(std::get>(node).get()); + break; + case 5: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +void Visitor::Visit(SourceStatement& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + case 3: + Visit(*std::get>(node)); + break; + default: + // error + break; + } +} + +// Flow control ----------------- + +void Visitor::Visit(Pattern& node) { // <-> ScopedPattern + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(*std::get>(node)); + break; + case 2: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +void Visitor::Visit(FlowControl& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + case 3: + Visit(std::get>(node).get()); + break; + case 4: + Visit(std::get>(node).get()); + break; + case 5: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +// Statements, expressions, blocks, etc. ----------------- + +void Visitor::Visit(BlockStatement& node) { + switch (node.index()) { + case 0: + Visit(*std::get>(node)); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(*std::get>(node)); + break; + case 3: + Visit(*std::get>(node)); + break; + default: + // error + break; + } +} + +// + +void Visitor::Visit(SubExpressionToken& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + case 3: + Visit(*std::get>(node)); + break; + case 4: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +void Visitor::Visit(SubExpression& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(*std::get>(node)); + break; + default: + // error + break; + } +} + +void Visitor::Visit(PrefixedExpression& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(*std::get>(node)); + break; + case 2: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +void Visitor::Visit(Expression& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(*std::get>(node)); + break; + case 3: + Visit(*std::get>(node)); + break; + default: + // error + break; + } +} + +void Visitor::Visit(SuperExpression& node) { + switch (node.index()) { + case 0: + Visit(*std::get>(node)); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + case 3: + Visit(std::get>(node).get()); + break; + case 4: + Visit(*std::get>(node)); + break; + default: + // error + break; + } +} + +// Name + +void Visitor::Visit(AnyName& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +// Type, typeclass, etc. ----------------- + +// Type + +void Visitor::Visit(AnyType& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + case 3: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +// Identifiers, constants, etc. ----------------- + +void Visitor::Visit(Literal& node) { + switch (node.index()) { + case 0: + Visit(std::get>(node).get()); + break; + case 1: + Visit(std::get>(node).get()); + break; + case 2: + Visit(std::get>(node).get()); + break; + case 3: + Visit(std::get>(node).get()); + break; + case 4: + Visit(std::get>(node).get()); + break; + case 5: + Visit(std::get>(node).get()); + break; + default: + // error + break; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Sources ----------------- + +void Visitor::Visit(SourceFile* node) { + for (auto& statement : node->statements) { + Visit(statement); + } +} + +// Namespaces, partitions ----------------- + +void Visitor::Visit(NamespaceSources* node) { + for (auto& statement : node->statements) { + Visit(statement); + } +} + +void Visitor::Visit(Namespace* node) { + Visit(&node->type); + Visit(&node->scope); +} + +// 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& function_requirement : node->requirements) { + Visit(function_requirement.second.get()); + } +} + +void Visitor::Visit(PartitionStatement* node) { + Visit(&node->name); + Visit(node->value); +} + +// Definition parts + +void Visitor::Visit(FunctionDefinition* node) { + Visit(&node->name); + 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.get()); + } +} + +// Flow control ----------------- + +void Visitor::Visit(TypeConstructorPatternParameter* node) { + if (node->name.has_value()) { + Visit(&node->name.value()); + } + Visit(node->value); +} + +void Visitor::Visit(TypeConstructorPattern* node) { + Visit(node->constructor.get()); + for (auto& parameter : node->parameters) { + Visit(¶meter); + } +} + +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&) {} // enum + +// Operators + +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) { + if (node->prefix.has_value()) { + if (std::holds_alternative>(node->prefix.value())) { + Visit(*std::get>(node->prefix.value())); + } else if (std::holds_alternative>(node->prefix.value())) { + Visit(std::get>(node->prefix.value()).get()); + } else { + // error + } + } + + Visit(&node->name); + + for (auto& parameter : node->parameters) { + Visit(parameter.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(TypeConstructorParameter* node) { + if (node->name.has_value()) { + Visit(&node->name.value()); + } + Visit(node->value); +} + +void Visitor::Visit(TypeConstructor* node) { + Visit(node->constructor.get()); + for (auto& parameter : node->parameters) { + Visit(¶meter); + } +} + +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(PartitionName* node) { + for (auto& path_namespace : node->path) { + Visit(&path_namespace); + } +} + +void Visitor::Visit(NameExpression* node) { + for (auto& name : node->names) { + Visit(&name); + } +} + +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()) { + Visit(node->type.value()); + } +} + +// Type, typeclass, etc. ----------------- + +// Type + +void Visitor::Visit(FunctionType* node) { + for (auto& type : node->types) { + 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(TypeExpression* node) { + for (auto& type : node->path) { + Visit(&type); + } + Visit(&node->type); +} + +void Visitor::Visit(ExtendedScopedAnyType* node) { + Visit(node->type); +} + +// Typeclass + +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. ----------------- + +void Visitor::Visit(std::string*) {} // std::string + +void Visitor::Visit(FloatNumberLiteral*) {} + +void Visitor::Visit(NumberLiteral*) {} + +void Visitor::Visit(StringLiteral*) {} + +void Visitor::Visit(CharLiteral*) {} + +void Visitor::Visit(UnitLiteral*) {} + +void Visitor::Visit(BoolLiteral*) {} + +} // namespace interpreter + diff --git a/tests/arrays.lang b/tests/arrays.lang new file mode 100644 index 0000000..734d713 --- /dev/null +++ b/tests/arrays.lang @@ -0,0 +1,21 @@ +decl test_arrays : -> Unit +def test_arrays = { + var arr1 = ,1 ,2 ,3 + const arr2 = Int._array: 32 + var arr3 = String._array: 11 + const arr4 = 'a'--'z' + const n = 100 + var arr5 <- Int._new_array: 10 + + var arr6 <- String._new_array: 10 + var arr6_reference = ^arr6 + + const elem1 = arr1`0 + var elem2 = arr1`2 + const ref1 = ^arr1`1 + var ref2 = ^arr1`3 + ; arr1`1 = 123 + + ; ~ref1 = arr1`2 // set value + ; ref1 = ref2 // set pointer / reference +} diff --git a/tests/classes.lang b/tests/classes.lang new file mode 100644 index 0000000..bb8e32c --- /dev/null +++ b/tests/classes.lang @@ -0,0 +1,59 @@ +struct Fruit = + | Apple + | Orange + | Banana + +struct Optional 'A = + | Some & 'A + | None + +struct (Result : #Move) 'A 'B = + | & 'A + | Error & 'B + +struct (Complex : #Value) = + & Float + & Float + +struct Task = + & name : String + & duration : Float + +class Employee = + & name : String + & role : + ( | Director + & importance : Float + & share : Float + | Manager + & productivity : + ( Productivity + | .Low + | .Average + | .High + & duration : Float + & sleep_on_work : + (SleepOnWork + | ..Yes + | ..No + )) + & salary : Int + | Programmer + & skills : Float + & current_task : (Optional Task) + & salary : Int) + + +class Bag = + & + ( | Apple + | Orange + | Banana) + & bag_type : + ( | Small + | Medium + & weight_kg : Int + & weight_g : Int + & weight_g : Int + | Big) + & other_things : (Array Something) diff --git a/tests/default_constructors.lang b/tests/default_constructors.lang new file mode 100644 index 0000000..bfed145 --- /dev/null +++ b/tests/default_constructors.lang @@ -0,0 +1,44 @@ +namespace Employee { + decl gen_employee : Unit -> Employee + def gen_employee = { + var x = $@Complex & 11.3 & 15.87 // construct on heap + return + $Employee // construct on stack + & name = "John" + & role = + ($Manager + & "John" + & productivity = + ($Productivity::High + & duration = 10.3 + & sleep_on_work = ($Productivity::SleepOnWork::No)) + & salary = 123) + + } +} + +/* +class Employee = + & name : String + & role : + ( | Director + & importance : Float + & share : Float + | Manager + & productivity : + ( Productivity + | .Low + | .Average + | .High + & duration : Float + & sleep_on_work : + (SleepOnWork + | ..Yes + | ..No + )) + & salary : Int + | Programmer + & skills : Float + & current_task : Optional Task + & salary : Int) +*/ diff --git a/tests/flow_control.lang b/tests/flow_control.lang new file mode 100644 index 0000000..aaea061 --- /dev/null +++ b/tests/flow_control.lang @@ -0,0 +1,33 @@ +decl flow_control_test : -> Unit +def flow_control_test = { + if (a < b ||. a == b) && (b < c) then IO.print: x + elif x < 0 then { + ; x += 1 + ; IO.print: y + } else { + return {} + } + + while (a > 0) && not: (array.is_empty:) do { + ; a -= 1 + ; array.pop: + } + + while x < 10 do x +=. x + 3 + + for i in 0--y do { + ; IO.print: i + } + + for & i & j in (& 0--y & 0--k) do { // ?? + ; IO.print: 1 + ; IO.print: 2 + ; IO.print: 128 + } + + loop { + ; y += 1 + if y > 100 then + break + } +} diff --git a/tests/functions.lang b/tests/functions.lang new file mode 100644 index 0000000..080f30e --- /dev/null +++ b/tests/functions.lang @@ -0,0 +1,62 @@ +decl sum ('A : #Add) : 'A -> 'A -> 'A +def sum : a b = a + b + +decl fib : Int -> Int +def fib : n = + match n with + | 0 | 1 -> 1 + | n ? n > 1 -> fib: (n - 1) + fib: n + | _ -> error: "n must be positive" + +decl fact : Int -> Int +def fact : n = + match n with + | 0 -> 1 + | n ? n > 0 -> n * fact: (n - 1) + | _ -> error: "n must be positive" + +decl find_prefix_hashes ('H : (#AccHash Char)) : String -> (Array 'H) +def find_prefix_hashes : str = { + var hashes = (Array 'H).new: (str.size: + 1) + + ; hashes`0 = 'H.of: str`0 + for i in 1--hashes.size: do { + ; hashes`i = hashes`(i - 1) + ; hashes`i.append: str`i + } + + return hashes +} + +alias Hash = (AccHash Char) + +decl find_substring : String -> String -> (Array Index) +def find_substring : str substr = { + var result = (Array Index).empty: + + const str_hashes = find_prefix_hashes Hash: str + const substr_hash = Hash.of: substr + + for i in 0--(str_hashes.size: - substr.size:) do { + const part_hash = Hash.diff: str_hashes`(i + substr.size:) str_hashes`i + + if part_hash == substr_hash then { + ; result.push: i + } + } + + return result +} + +decl is_empty : -> Bool +def is_empty = 0 + +decl do_something : -> Unit +def do_something = + IO.print: "Hello World!" + +decl mul : Int -> Int -> Int +def mul : x y = x * y + +decl mul_10 : Int -> Int +def mul_10 = mul: 10 diff --git a/tests/import.lang b/tests/import.lang new file mode 100644 index 0000000..d3c2533 --- /dev/null +++ b/tests/import.lang @@ -0,0 +1,16 @@ +import "module" +import "module" : func +import "module" : + Type1 + func1 + func2 + func3 + func4 + +use ModuleNamespace = import "module" + +use PartOfModuleNamespace = + import "module" : + func1 + func2 + func3 diff --git a/tests/lambdas.lang b/tests/lambdas.lang new file mode 100644 index 0000000..3a9998f --- /dev/null +++ b/tests/lambdas.lang @@ -0,0 +1,12 @@ +decl test_lambdas : -> Unit +def test_lambdas = { + const lambda1 = \x -> x * x + const lambda2 = \x -> x.hash: + const lambda3 = \x y -> x + y + + const lambda4 = \x -> { + ; IO.print: x + const y = x + x + return y + } +} diff --git a/tests/match.lang b/tests/match.lang new file mode 100644 index 0000000..0541c72 --- /dev/null +++ b/tests/match.lang @@ -0,0 +1,18 @@ +decl fruit_cost : Fruit -> Int +def fruit_cost : fruit = { + var fruit_copy = fruit + return (match <- fruit_copy with // consuming match + | $Banana -> 11 + | $Apple | $Orange -> 7) +} + +decl amount_to_string : Int -> Bool -> String +def amount_to_string : x is_zero_separated = { + const ans = match x with + | 0 ? is_zero_separated -> "Zero" + | 0 | 1 | 2 | 3 | 4 -> "Few" + | x ? (5--9).contains: x -> "Several" + | x ? (10--19).contains: x -> "Pack" + | _ -> "Lots" + return ans +} diff --git a/tests/memory.lang b/tests/memory.lang new file mode 100644 index 0000000..0092566 --- /dev/null +++ b/tests/memory.lang @@ -0,0 +1,8 @@ +struct StructWithRef = + & @Int_0 + +decl test_memory : -> Unit +def test_memory = { + const unique_ref1 <- Int._new: 5 + var unique_ref2 <- Array.of: 1 2 3 +} diff --git a/tests/namespaces.lang b/tests/namespaces.lang new file mode 100644 index 0000000..57f3580 --- /dev/null +++ b/tests/namespaces.lang @@ -0,0 +1,19 @@ +namespace Namespace { + decl something : -> Unit +} + +namespace Array { + decl something : -> Unit +} + +namespace Array { + decl something : -> Unit +} + +namespace var Array { + decl something : -> Unit +} + +namespace const Array { + decl something : -> Unit +} diff --git a/tests/partitions.lang b/tests/partitions.lang new file mode 100644 index 0000000..9ec0b99 --- /dev/null +++ b/tests/partitions.lang @@ -0,0 +1,10 @@ +test All::Dev::Syntax::testing { + const a = 31 + ; do_something: a +} + +exec App::exe { + const b = true + const c = false + ; do_something_different: b b c +} diff --git a/tests/stdlib.lang b/tests/stdlib.lang new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_code.lang b/tests/test_code.lang new file mode 100644 index 0000000..191d028 --- /dev/null +++ b/tests/test_code.lang @@ -0,0 +1,229 @@ +basic (Float : #Ord #Div #Str) +basic (Int : #Ord #IDiv #Str) +basic (String : #Ord #Str #CharContainer #Copy) +basic (Char : #Ord #Str #Copy) +basic (Bool : #Ord #Str #Copy) +basic (Unit : #Str #Copy) + +// + +decl not : Bool -> Bool +def not : x = + (match x with + | true -> false + | false -> true) + +decl ( && ) : Bool -> Bool -> Bool +def ( && ) : x y = + match x with + | true -> ( + match y with + | true -> true + | false -> false + ) + | false -> false + +decl ( || ) : Bool -> Bool -> Bool +def ( || ) : x y = + match x with + | true -> true + | false -> ( + match y with + | true -> true + | false -> false + ) + +// + +typeclass CharContainer = + & var size : -> Int + & var at : Int -> Char + +// + +typeclass Move = + & var ( <- ) : Move -> Unit // TODO + +typeclass Copy = + & var ( = ) : Copy -> Unit + +// + +typeclass (Sum : #Copy) = + & var ( += ) : Sum -> Unit + & var ( -= ) : Sum -> Unit + & var ( + ) : Sum -> Sum + & var ( - ) : Sum -> Sum + & zero : -> Sum + +namespace var Sum { + def ( + ) : x = { + var ans = self + ; ans += x + return ans + } + + def ( - ) : x = { + var ans = self + ; ans -= x + return ans + } +} + +typeclass (Mult : #Sum) = + & var ( *= ) : Mult -> Unit + & var ( * ) : Mult -> Mult + +namespace var Mult { + def ( * ) : x = { + var ans = self + ; ans *= x + return ans + } +} + +typeclass (IDiv : #Mult) = + & var div : IDiv -> IDiv + & var mod : IDiv -> IDiv + +namespace var IDiv { + def mod : x = self -. x * self.div: x +} + +typeclass (Div : #Mult) = + & var ( /= ) : Div -> Unit + & var ( / ) : Div -> Div + +namespace var Div { + def ( / ) : x = { + var ans = self + ; ans /= x + return ans + } +} + +// + +typeclass Eq = + & var ( == ) : Eq -> Bool + & var ( != ) : Eq -> Bool + +namespace var Eq { + def ( != ) : x = not: (self == x) +} + +// + +struct Order = + | EQ + | LT + | GT + +typeclass (Ord : #Eq) = + & var compare : Ord -> Order + & var ( < ) : Ord -> Bool + & var ( >= ) : Ord -> Bool + & var ( > ) : Ord -> Bool + & var ( <= ) : Ord -> Bool + +decl min ('A : #Ord) : 'A -> 'A -> 'A +def min : x y = if x < y then x else y + +decl max ('A : #Ord) : 'A -> 'A -> 'A +def max : x y = if x < y then y else x + +namespace var Ord { + def compare : x = + if self == x then $EQ + elif self < x then $LT + else $GT + + def ( >= ) : x = not: (self < x) + def ( > ) : x = x < self + def ( <= ) : x = not: (x < self) +} + +// + +typeclass Show = + & var show : -> String + +typeclass Read = + & var read : String -> Read + +typeclass (Str : #Show #Read) + +// typeclass DebugShow = // TODO +// & debug_show : -> String + +// + +typeclass Default = + & default : -> Default + +// + +typeclass Bounded = + & min_bound : -> Bounded + & max_bound : -> Bounded + & var is_max_bound : -> Bool + & var is_min_bound : -> Bool + +// + +typeclass Enum = + & var succ : -> (Optional Enum) + & var pred : -> (Optional Enum) + & to_enum : Int -> Enum + & var from_enum : -> Int + +// + +decl print : String -> Unit +decl scan : -> String +decl random : -> Int // TODO + +// + +// // bad +// typeclass Functor 'A = +// & fmap 'B ('F : (#Functor 'B)) : ('A -> 'B) -> Functor -> 'F + +// typeclass (Iterator : #Eq) = +// & next : -> Unit +// & prev : -> Unit +// +// typeclass Iterable ('Iter : #Iterable) = +// & begin : -> 'Iter +// & end : -> 'Iter + +// + +decl ret_one : -> Int +def ret_one = 1 + +decl ( -- ) : Int -> Int -> Int_0 +def ( -- ) : begin end = { + var current = begin + return (while current < end do { + ; current += 1 + bring current - 1 + }) +} + +decl func : String -> Int -> Int +def func : s i = { + ; print: s + var x = s + ; print: (i.show:) + return 5 +} + +exec main { + for i in 0--19 do func: "a" (i * 2 +. 3) + ; print: ({ + if true then bring scan: else { ; print: "aaa" } + bring "nothing" + ; print: "aaa" + }) +} diff --git a/tests/tuples.lang b/tests/tuples.lang new file mode 100644 index 0000000..73692e8 --- /dev/null +++ b/tests/tuples.lang @@ -0,0 +1,8 @@ +decl test_tuples : -> Unit +def test_tuples = { + var tuple1 = & "a" & 2 & "hello" + const & t1 & t2 & t3 = f: x + + ; tuple1`0 = "b" + +} diff --git a/tests/type_casting.lang b/tests/type_casting.lang new file mode 100644 index 0000000..9d9c255 --- /dev/null +++ b/tests/type_casting.lang @@ -0,0 +1,5 @@ +decl test_type_casting : -> Unit +def test_type_casting = { + var x = y.as Int: + var k = (f: y x).as Float: +} diff --git a/tests/typeclasses.lang b/tests/typeclasses.lang new file mode 100644 index 0000000..4b32064 --- /dev/null +++ b/tests/typeclasses.lang @@ -0,0 +1,29 @@ +typeclass Default = + & default : -> Copy + +typeclass (Ord : #Eq) = + & var is_less_then : Ord -> Bool + +typeclass (D : #A #B #C) 'A 'B = + & var do_something : -> (& 'A & 'B) + +typeclass E 'A = + & var do_something : -> 'A + +decl ( == ) ('A : #Ord) : 'A -> 'A -> Bool +def ( == ) : a b = a.is_equal_to: b + +decl ( != ) ('A : #Ord) : 'A -> 'A -> Bool +def ( != ) : a b = not: (a == b) + +decl ( < ) ('A : #Ord) : 'A -> 'A -> Bool +def ( < ) : a b = a.is_less_then: b + +decl ( > ) ('A : #Ord) : 'A -> 'A -> Bool +def ( > ) : a b = not: (a <= b) + +decl ( <= ) ('A : #Ord) : 'A -> 'A -> Bool +def ( <= ) : a b = a < b ||. a == b + +decl ( >= ) ('A : #Ord) : 'A -> 'A -> Bool +def ( >= ) : a b = not: (a < b) diff --git a/tests/types.lang b/tests/types.lang new file mode 100644 index 0000000..f6ce429 --- /dev/null +++ b/tests/types.lang @@ -0,0 +1,8 @@ +alias T1 = Int + +abstract (T2 : #A #B #C) + +// Used to pre-compile module for some types +let T2 = Int +let T2 = Float +let T2 = Complex diff --git a/tests/variants.lang b/tests/variants.lang new file mode 100644 index 0000000..9b747b7 --- /dev/null +++ b/tests/variants.lang @@ -0,0 +1,15 @@ +decl test_variants : -> Unit +def test_variants = { + var variant1 = | 'a' | 2 | "hello" + var | val | err = f: x + + ; val -?> "something" // open variant as value in expr + + ; val -!> "nothing" // open variant as None in expr + + match variant1 with + | 'a' -> "something" + | 2 -> "nothing" + | "hello" -> "nothing" + | 11 -> "nothing" +} diff --git a/tree-sitter b/tree-sitter new file mode 160000 index 0000000..1b1c397 --- /dev/null +++ b/tree-sitter @@ -0,0 +1 @@ +Subproject commit 1b1c3974f789a9bfaa31f493e6eaa212f13bdfb9