diff --git a/deps/tree-sitter-lang b/deps/tree-sitter-lang index 6b09331..1357783 160000 --- a/deps/tree-sitter-lang +++ b/deps/tree-sitter-lang @@ -1 +1 @@ -Subproject commit 6b093311dfb371cf67a218a8c97779ae5e15e234 +Subproject commit 1357783074e77c2c5ddcec16e90cf59940dabd9d diff --git a/etc/kate_highlighting_lang.xml b/etc/kate_highlighting_lang.xml index b076662..a93b7e4 100644 --- a/etc/kate_highlighting_lang.xml +++ b/etc/kate_highlighting_lang.xml @@ -64,7 +64,7 @@ - + diff --git a/include/builders/type_builders.hpp b/include/builders/type_builders.hpp index c39607c..1afce88 100644 --- a/include/builders/type_builders.hpp +++ b/include/builders/type_builders.hpp @@ -14,6 +14,9 @@ nodes::TypeProxy build_variant_type(parser::ParseTree::Node parse_node, nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parse_node, nodes::TypeStorage &type_storage); +nodes::TypeProxy build_function_type(parser::ParseTree::Node parse_node, + nodes::TypeStorage &type_storage); + nodes::TypeProxy build_array_type(parser::ParseTree::Node parse_node, nodes::TypeStorage &type_storage); diff --git a/include/builtin_types.hpp b/include/builtin_types.hpp index d9f0eb5..854a222 100644 --- a/include/builtin_types.hpp +++ b/include/builtin_types.hpp @@ -13,6 +13,8 @@ const static std::string TUPLE_IDENTIFIER = "Tuple"; const static std::string VARIANT_IDENTIFIER = "Variant"; +const static std::string FUNCTION_IDENTIFIER = "Function"; + const static std::string ARRAY_IDENTIFIER = "Array"; const static std::string OPTIONAL_IDENTIFIER = "Optional"; @@ -50,6 +52,7 @@ enum class Type { // -- containers TUPLE, VARIANT, + FUNCTION, ARRAY, OPTIONAL, RESULT, @@ -75,6 +78,8 @@ inline std::string to_string(Type type) { return TUPLE_IDENTIFIER; case Type::VARIANT: return VARIANT_IDENTIFIER; + case Type::FUNCTION: + return FUNCTION_IDENTIFIER; case Type::ARRAY: return ARRAY_IDENTIFIER; case Type::OPTIONAL: @@ -118,6 +123,7 @@ inline Type to_type(const std::string &str) { // -- containers builtin_types[TUPLE_IDENTIFIER] = Type::TUPLE; builtin_types[VARIANT_IDENTIFIER] = Type::VARIANT; + builtin_types[FUNCTION_IDENTIFIER] = Type::FUNCTION; builtin_types[ARRAY_IDENTIFIER] = Type::ARRAY; builtin_types[OPTIONAL_IDENTIFIER] = Type::OPTIONAL; builtin_types[RESULT_IDENTIFIER] = Type::RESULT; @@ -161,6 +167,7 @@ inline std::optional get_parameters_count(Type type) { // -- containers case Type::TUPLE: case Type::VARIANT: + case Type::FUNCTION: return std::nullopt; case Type::ARRAY: case Type::OPTIONAL: diff --git a/include/expression_type_check.hpp b/include/expression_type_check.hpp index 5c3f266..caa6ceb 100644 --- a/include/expression_type_check.hpp +++ b/include/expression_type_check.hpp @@ -3,6 +3,7 @@ #include "expression_nodes.hpp" #include "sources_manager.hpp" #include "type_nodes.hpp" +#include "utils.hpp" #include @@ -10,9 +11,46 @@ namespace type_check { -struct State { +class State { +public: + bool insert_variable(const std::string &name, nodes::TypeProxy type) { + if (contexts_.size() == 0) { + error_handling::handle_general_error( + "Insert variable into contexts_ with zero elements in State"); + } + + return contexts_.back().insert({name, type}).second; + } + + std::optional find_variable(const std::string &name) { + for (ssize_t i = contexts_.size(); i >= 0; --i) { + auto iter = contexts_[i].find(name); + if (iter != contexts_[i].end()) { + return iter->second; + } + } + + return std::nullopt; + } + + void enter_context() { contexts_.emplace_back(); } + + void exit_context() { + if (contexts_.size() == 0) { + error_handling::handle_general_error( + "Pop from contexts_ with zero elements in State"); + } + + contexts_.pop_back(); + } + +public: std::optional brought_type; std::optional returned_type; + +private: + std::vector> contexts_ = { + {}}; }; nodes::TypeCheckResult diff --git a/include/nodes/type_nodes.hpp b/include/nodes/type_nodes.hpp index 26b46fd..c661c87 100644 --- a/include/nodes/type_nodes.hpp +++ b/include/nodes/type_nodes.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -207,10 +208,11 @@ class TypeStorage { public: TypeProxy primitive_type(builtin::types::Type type) { - if (unit_type_id.has_value()) { - return TypeProxy(*this, unit_type_id.value()); + auto iter = primitive_type_ids_.find(type); + if (iter != primitive_type_ids_.end()) { + return TypeProxy(*this, iter->second); } else { - unit_type_id = storage_.size(); + primitive_type_ids_[type] = storage_.size(); return add_type(Type(Identifier(Node(), Identifier::SIMPLE_TYPE, builtin::types::to_string(type)))); } @@ -251,72 +253,27 @@ public: return TypeProxy(*this, storage_.size() - 1); } + // TODO: + // bool try_resolve_all_generic_names + // bool add_generic_type + // bool add_local_type + // // add local type requirement + // // deduce generic type + // void clear_local_types + // ... + private: Type *get_type(size_t id) { return &storage_.at(id); } const Type *get_type(size_t id) const { return &storage_.at(id); } private: - std::optional unit_type_id; - + // TODO + // std::unordered_map named_local_types_; + std::unordered_map primitive_type_ids_; std::vector storage_; }; -// class ModifiedTypeProxy { -// public: -// ModifiedTypeProxy(nodes::TypeProxy type, -// nodes::Modifier modifier = nodes::Modifier::NONE) -// : type_(type), modifier_(modifier) {} -// -// // -// -// nodes::Modifier get_modifier() const { return modifier_; } -// -// void set_modifier(nodes::Modifier modifier) { modifier_ = modifier; } -// -// // -// -// nodes::Type *get_type() { return type_.get(); } -// -// const nodes::Type *get_type() const { return type_.get(); } -// -// const nodes::TypeProxy get_type_proxy() const { return type_; } -// -// // -// -// bool operator==(const ModifiedTypeProxy &other) const { -// return *type_.get() == *other.type_.get() && modifier_ == -// other.modifier_; -// } -// -// bool operator!=(const ModifiedTypeProxy &other) const { -// return !(*this == other); -// } -// -// // -// -// bool operator<(const ModifiedTypeProxy &other) const { -// return *type_.get() < *other.type_.get() || -// (*type_.get() == *other.type_.get() && modifier_ < -// other.modifier_); -// } -// -// bool operator>(const ModifiedTypeProxy &other) const { return other < -// *this; } -// -// bool operator<=(const ModifiedTypeProxy &other) const { -// return !operator>(other); -// } -// -// bool operator>=(const ModifiedTypeProxy &other) const { -// return !operator<(other); -// } -// -// private: -// nodes::TypeProxy type_; -// nodes::Modifier modifier_; -// }; - class TypeCheckResult { public: // for invalid type diff --git a/include/tokens.hpp b/include/tokens.hpp index 52c0fce..d64480b 100644 --- a/include/tokens.hpp +++ b/include/tokens.hpp @@ -54,6 +54,7 @@ enum class Type { VARIANT_TYPE, TUPLE_TYPE, + FUNCTION_TYPE, ARRAY_TYPE, REFERENCE_TYPE, MODIFIED_TYPE, @@ -149,6 +150,7 @@ const static std::string LAMBDA = "lambda"; const static std::string VARIANT_TYPE = "variant_type"; const static std::string TUPLE_TYPE = "tuple_type"; +const static std::string FUNCTION_TYPE = "function_type"; const static std::string ARRAY_TYPE = "array_type"; const static std::string REFERENCE_TYPE = "reference_type"; const static std::string MODIFIED_TYPE = "modified_type"; @@ -242,6 +244,8 @@ inline Type string_to_type(const std::string &str) { return Type::VARIANT_TYPE; } else if (str == TUPLE_TYPE) { return Type::TUPLE_TYPE; + } else if (str == FUNCTION_TYPE) { + return Type::FUNCTION_TYPE; } else if (str == ARRAY_TYPE) { return Type::ARRAY_TYPE; } else if (str == REFERENCE_TYPE) { diff --git a/src/builders/statement_builders.cpp b/src/builders/statement_builders.cpp index e8f6e69..b6a5178 100644 --- a/src/builders/statement_builders.cpp +++ b/src/builders/statement_builders.cpp @@ -382,6 +382,7 @@ nodes::FunctionDefinition build_function_definition( break; case tokens::Type::VARIANT_TYPE: case tokens::Type::TUPLE_TYPE: + case tokens::Type::FUNCTION_TYPE: case tokens::Type::ARRAY_TYPE: case tokens::Type::REFERENCE_TYPE: case tokens::Type::MODIFIED_TYPE: diff --git a/src/builders/type_builders.cpp b/src/builders/type_builders.cpp index 64aae9a..1ac9fc7 100644 --- a/src/builders/type_builders.cpp +++ b/src/builders/type_builders.cpp @@ -23,6 +23,8 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parser_node, return build_variant_type(parser_node, type_storage); case tokens::Type::TUPLE_TYPE: return build_tuple_type(parser_node, type_storage); + case tokens::Type::FUNCTION_TYPE: + return build_function_type(parser_node, type_storage); case tokens::Type::ARRAY_TYPE: return build_array_type(parser_node, type_storage); case tokens::Type::REFERENCE_TYPE: @@ -78,6 +80,13 @@ nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parser_node, builtin::types::Type::TUPLE); } +// '((' (annotation? type)+ '))' +nodes::TypeProxy build_function_type(parser::ParseTree::Node parser_node, + nodes::TypeStorage &type_storage) { + return build_container_type(parser_node, type_storage, + builtin::types::Type::FUNCTION); +} + // '[[' type ']]' nodes::TypeProxy build_array_type(parser::ParseTree::Node parser_node, nodes::TypeStorage &type_storage) { diff --git a/tests/test.langexp b/tests/test.langexp index e5c2e39..49ba767 100644 --- a/tests/test.langexp +++ b/tests/test.langexp @@ -226,7 +226,7 @@ result_func! 'a 'b -> 'c -> 'd = ?? 'a == 0 => error "some error" !!=> ('c := 'a tuple_argument_test 'x : (A & B & C) = do_something; // ((A1 & A2) | B | C) same to Variant[Tuple[A1 A2] B C] -variant_argument_test 'x : ((A1 & A2) | B | C) = do_something; +variant_argument_test 'x : ( (A1 & A2) | B | C) = do_something; literals_test = { %float_number_literal := 1.0f; @@ -242,3 +242,7 @@ literals_test = { %unit_literal := (); %null_literal := null; } + +array_argument_test 'x : [[ Int ]] = do_something; + +functional_arguments_test 'x 'y : (( Int -> Int )) (( Float <- Float -> Float )) = do_something;