mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-05 22:48:43 +00:00
function type
This commit is contained in:
parent
7f3dfd71a1
commit
fa01d36a84
10 changed files with 87 additions and 64 deletions
2
deps/tree-sitter-lang
vendored
2
deps/tree-sitter-lang
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6b093311dfb371cf67a218a8c97779ae5e15e234
|
Subproject commit 1357783074e77c2c5ddcec16e90cf59940dabd9d
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
<RegExpr String="\b[0-9]+[il]?\b" attribute="Decimal" context="#stay"/>
|
<RegExpr String="\b[0-9]+[il]?\b" attribute="Decimal" context="#stay"/>
|
||||||
<RegExpr String=""([^\\"]|(\\.))*"u?" attribute="String" context="#stay" />
|
<RegExpr String=""([^\\"]|(\\.))*"u?" attribute="String" context="#stay" />
|
||||||
|
|
||||||
<RegExpr String="((?<![\+\\\-\*/%\^\!\?\|&,<>=\.])((\.+)|([\+\\\-\*/%\^\!\?\|&,<>=]+\.?\.?\.?)))|(\|)" attribute="Operator" context="#stay"/>
|
<RegExpr String="((?<![\+\\\-\*/%\^\!\?\|&,<>=\.])((\.+)|([\+\\\-\*/%\^\!\?\|&,<>=]+\.?\.?\.?)))|(\|)|(\[\[)|(\]\])|(\(\()|(\)\))" attribute="Operator" context="#stay"/>
|
||||||
|
|
||||||
<RegExpr String="([a-z_][a-z0-9_]*\.)*(([a-z_][a-z0-9_]*)|_)(?![a-z0-9_])" attribute="Name" context="#stay"/>
|
<RegExpr String="([a-z_][a-z0-9_]*\.)*(([a-z_][a-z0-9_]*)|_)(?![a-z0-9_])" attribute="Name" context="#stay"/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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::TypeProxy build_tuple_type(parser::ParseTree::Node parse_node,
|
||||||
nodes::TypeStorage &type_storage);
|
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::TypeProxy build_array_type(parser::ParseTree::Node parse_node,
|
||||||
nodes::TypeStorage &type_storage);
|
nodes::TypeStorage &type_storage);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ const static std::string TUPLE_IDENTIFIER = "Tuple";
|
||||||
|
|
||||||
const static std::string VARIANT_IDENTIFIER = "Variant";
|
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 ARRAY_IDENTIFIER = "Array";
|
||||||
|
|
||||||
const static std::string OPTIONAL_IDENTIFIER = "Optional";
|
const static std::string OPTIONAL_IDENTIFIER = "Optional";
|
||||||
|
|
@ -50,6 +52,7 @@ enum class Type {
|
||||||
// -- containers
|
// -- containers
|
||||||
TUPLE,
|
TUPLE,
|
||||||
VARIANT,
|
VARIANT,
|
||||||
|
FUNCTION,
|
||||||
ARRAY,
|
ARRAY,
|
||||||
OPTIONAL,
|
OPTIONAL,
|
||||||
RESULT,
|
RESULT,
|
||||||
|
|
@ -75,6 +78,8 @@ inline std::string to_string(Type type) {
|
||||||
return TUPLE_IDENTIFIER;
|
return TUPLE_IDENTIFIER;
|
||||||
case Type::VARIANT:
|
case Type::VARIANT:
|
||||||
return VARIANT_IDENTIFIER;
|
return VARIANT_IDENTIFIER;
|
||||||
|
case Type::FUNCTION:
|
||||||
|
return FUNCTION_IDENTIFIER;
|
||||||
case Type::ARRAY:
|
case Type::ARRAY:
|
||||||
return ARRAY_IDENTIFIER;
|
return ARRAY_IDENTIFIER;
|
||||||
case Type::OPTIONAL:
|
case Type::OPTIONAL:
|
||||||
|
|
@ -118,6 +123,7 @@ inline Type to_type(const std::string &str) {
|
||||||
// -- containers
|
// -- containers
|
||||||
builtin_types[TUPLE_IDENTIFIER] = Type::TUPLE;
|
builtin_types[TUPLE_IDENTIFIER] = Type::TUPLE;
|
||||||
builtin_types[VARIANT_IDENTIFIER] = Type::VARIANT;
|
builtin_types[VARIANT_IDENTIFIER] = Type::VARIANT;
|
||||||
|
builtin_types[FUNCTION_IDENTIFIER] = Type::FUNCTION;
|
||||||
builtin_types[ARRAY_IDENTIFIER] = Type::ARRAY;
|
builtin_types[ARRAY_IDENTIFIER] = Type::ARRAY;
|
||||||
builtin_types[OPTIONAL_IDENTIFIER] = Type::OPTIONAL;
|
builtin_types[OPTIONAL_IDENTIFIER] = Type::OPTIONAL;
|
||||||
builtin_types[RESULT_IDENTIFIER] = Type::RESULT;
|
builtin_types[RESULT_IDENTIFIER] = Type::RESULT;
|
||||||
|
|
@ -161,6 +167,7 @@ inline std::optional<size_t> get_parameters_count(Type type) {
|
||||||
// -- containers
|
// -- containers
|
||||||
case Type::TUPLE:
|
case Type::TUPLE:
|
||||||
case Type::VARIANT:
|
case Type::VARIANT:
|
||||||
|
case Type::FUNCTION:
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
case Type::ARRAY:
|
case Type::ARRAY:
|
||||||
case Type::OPTIONAL:
|
case Type::OPTIONAL:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "expression_nodes.hpp"
|
#include "expression_nodes.hpp"
|
||||||
#include "sources_manager.hpp"
|
#include "sources_manager.hpp"
|
||||||
#include "type_nodes.hpp"
|
#include "type_nodes.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
|
@ -10,9 +11,46 @@
|
||||||
|
|
||||||
namespace type_check {
|
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<nodes::TypeProxy> 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<nodes::TypeProxy> brought_type;
|
std::optional<nodes::TypeProxy> brought_type;
|
||||||
std::optional<nodes::TypeProxy> returned_type;
|
std::optional<nodes::TypeProxy> returned_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unordered_map<std::string, nodes::TypeProxy>> contexts_ = {
|
||||||
|
{}};
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes::TypeCheckResult
|
nodes::TypeCheckResult
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -207,10 +208,11 @@ class TypeStorage {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TypeProxy primitive_type(builtin::types::Type type) {
|
TypeProxy primitive_type(builtin::types::Type type) {
|
||||||
if (unit_type_id.has_value()) {
|
auto iter = primitive_type_ids_.find(type);
|
||||||
return TypeProxy(*this, unit_type_id.value());
|
if (iter != primitive_type_ids_.end()) {
|
||||||
|
return TypeProxy(*this, iter->second);
|
||||||
} else {
|
} else {
|
||||||
unit_type_id = storage_.size();
|
primitive_type_ids_[type] = storage_.size();
|
||||||
return add_type(Type(Identifier(Node(), Identifier::SIMPLE_TYPE,
|
return add_type(Type(Identifier(Node(), Identifier::SIMPLE_TYPE,
|
||||||
builtin::types::to_string(type))));
|
builtin::types::to_string(type))));
|
||||||
}
|
}
|
||||||
|
|
@ -251,72 +253,27 @@ public:
|
||||||
return TypeProxy(*this, storage_.size() - 1);
|
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:
|
private:
|
||||||
Type *get_type(size_t id) { return &storage_.at(id); }
|
Type *get_type(size_t id) { return &storage_.at(id); }
|
||||||
|
|
||||||
const Type *get_type(size_t id) const { return &storage_.at(id); }
|
const Type *get_type(size_t id) const { return &storage_.at(id); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<size_t> unit_type_id;
|
// TODO
|
||||||
|
// std::unordered_map<std::string, size_t> named_local_types_;
|
||||||
|
std::unordered_map<builtin::types::Type, size_t> primitive_type_ids_;
|
||||||
std::vector<Type> storage_;
|
std::vector<Type> 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 {
|
class TypeCheckResult {
|
||||||
public:
|
public:
|
||||||
// for invalid type
|
// for invalid type
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ enum class Type {
|
||||||
|
|
||||||
VARIANT_TYPE,
|
VARIANT_TYPE,
|
||||||
TUPLE_TYPE,
|
TUPLE_TYPE,
|
||||||
|
FUNCTION_TYPE,
|
||||||
ARRAY_TYPE,
|
ARRAY_TYPE,
|
||||||
REFERENCE_TYPE,
|
REFERENCE_TYPE,
|
||||||
MODIFIED_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 VARIANT_TYPE = "variant_type";
|
||||||
const static std::string TUPLE_TYPE = "tuple_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 ARRAY_TYPE = "array_type";
|
||||||
const static std::string REFERENCE_TYPE = "reference_type";
|
const static std::string REFERENCE_TYPE = "reference_type";
|
||||||
const static std::string MODIFIED_TYPE = "modified_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;
|
return Type::VARIANT_TYPE;
|
||||||
} else if (str == TUPLE_TYPE) {
|
} else if (str == TUPLE_TYPE) {
|
||||||
return Type::TUPLE_TYPE;
|
return Type::TUPLE_TYPE;
|
||||||
|
} else if (str == FUNCTION_TYPE) {
|
||||||
|
return Type::FUNCTION_TYPE;
|
||||||
} else if (str == ARRAY_TYPE) {
|
} else if (str == ARRAY_TYPE) {
|
||||||
return Type::ARRAY_TYPE;
|
return Type::ARRAY_TYPE;
|
||||||
} else if (str == REFERENCE_TYPE) {
|
} else if (str == REFERENCE_TYPE) {
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,7 @@ nodes::FunctionDefinition build_function_definition(
|
||||||
break;
|
break;
|
||||||
case tokens::Type::VARIANT_TYPE:
|
case tokens::Type::VARIANT_TYPE:
|
||||||
case tokens::Type::TUPLE_TYPE:
|
case tokens::Type::TUPLE_TYPE:
|
||||||
|
case tokens::Type::FUNCTION_TYPE:
|
||||||
case tokens::Type::ARRAY_TYPE:
|
case tokens::Type::ARRAY_TYPE:
|
||||||
case tokens::Type::REFERENCE_TYPE:
|
case tokens::Type::REFERENCE_TYPE:
|
||||||
case tokens::Type::MODIFIED_TYPE:
|
case tokens::Type::MODIFIED_TYPE:
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ nodes::TypeProxy build_type(parser::ParseTree::Node parser_node,
|
||||||
return build_variant_type(parser_node, type_storage);
|
return build_variant_type(parser_node, type_storage);
|
||||||
case tokens::Type::TUPLE_TYPE:
|
case tokens::Type::TUPLE_TYPE:
|
||||||
return build_tuple_type(parser_node, type_storage);
|
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:
|
case tokens::Type::ARRAY_TYPE:
|
||||||
return build_array_type(parser_node, type_storage);
|
return build_array_type(parser_node, type_storage);
|
||||||
case tokens::Type::REFERENCE_TYPE:
|
case tokens::Type::REFERENCE_TYPE:
|
||||||
|
|
@ -78,6 +80,13 @@ nodes::TypeProxy build_tuple_type(parser::ParseTree::Node parser_node,
|
||||||
builtin::types::Type::TUPLE);
|
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 ']]'
|
// '[[' type ']]'
|
||||||
nodes::TypeProxy build_array_type(parser::ParseTree::Node parser_node,
|
nodes::TypeProxy build_array_type(parser::ParseTree::Node parser_node,
|
||||||
nodes::TypeStorage &type_storage) {
|
nodes::TypeStorage &type_storage) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
tuple_argument_test 'x : (A & B & C) = do_something;
|
||||||
|
|
||||||
// ((A1 & A2) | B | C) same to Variant[Tuple[A1 A2] B C]
|
// ((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 = {
|
literals_test = {
|
||||||
%float_number_literal := 1.0f;
|
%float_number_literal := 1.0f;
|
||||||
|
|
@ -242,3 +242,7 @@ literals_test = {
|
||||||
%unit_literal := ();
|
%unit_literal := ();
|
||||||
%null_literal := null;
|
%null_literal := null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array_argument_test 'x : [[ Int ]] = do_something;
|
||||||
|
|
||||||
|
functional_arguments_test 'x 'y : (( Int -> Int )) (( Float <- Float -> Float )) = do_something;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue