From 61f1a9c079602e6b09355461cd18783f4d99a559 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 18 Dec 2025 15:37:38 +0300 Subject: [PATCH] Add support for function types --- libs/interpreter/source/eval.cpp | 9 +++++++ libs/parser/rules/pslang.y | 18 ++++++++++++- libs/type/include/pslang/type/function.hpp | 31 ++++++++++++++++++++++ libs/type/include/pslang/type/type.hpp | 2 ++ libs/type/source/print.cpp | 14 ++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 libs/type/include/pslang/type/function.hpp diff --git a/libs/interpreter/source/eval.cpp b/libs/interpreter/source/eval.cpp index 8e895ba..3a7224b 100644 --- a/libs/interpreter/source/eval.cpp +++ b/libs/interpreter/source/eval.cpp @@ -30,6 +30,15 @@ namespace pslang::interpreter return type::array_type{std::make_unique(resolve_type(context, *type.element_type)), type.size}; } + type::type resolve_type_impl(context & context, type::function_type const & type) + { + type::function_type result; + for (auto const & argument : type.arguments) + result.arguments.push_back(std::make_unique(resolve_type(context, *argument))); + result.result = std::make_unique(resolve_type(context, *type.result)); + return result; + } + type::type resolve_type_impl(context & context, type::identifier const & type) { for (auto it = context.scope_stack.rbegin(); it != context.scope_stack.rend(); ++it) diff --git a/libs/parser/rules/pslang.y b/libs/parser/rules/pslang.y index 1e9deb4..67231dd 100644 --- a/libs/parser/rules/pslang.y +++ b/libs/parser/rules/pslang.y @@ -131,6 +131,7 @@ template %token end 0 +%right arrow %left ampersand vertical_bar circumflex %left equals not_equals less greater less_equals greater_equals %nonassoc as @@ -138,6 +139,7 @@ template %left plus minus %left asterisk slash percent %precedence NOT +%precedence lbracket %type indented_statement_list %type indentation @@ -149,6 +151,8 @@ template %type variable_keyword %type type_expression %type primitive_type +%type > function_paren_type_list +%type > two_or_more_type_list %type expression %type postfix_expression %type base_expression @@ -219,6 +223,9 @@ type_expression | primitive_type { $$ = type::type($1); } | name { $$ = type::identifier{$1}; } | type_expression lbracket lit_i32 rbracket { $$ = type::array_type{std::make_unique($1), std::stoull($3)}; } +| type_expression arrow type_expression { std::vector args; args.push_back(std::make_unique($1)); $$ = type::function_type{std::move(args), std::make_unique($3)}; } +| lparen function_paren_type_list rparen arrow type_expression { $$ = type::function_type{$2, std::make_unique($5)}; } +| lparen type_expression rparen { $$ = $2; } ; primitive_type @@ -235,6 +242,16 @@ primitive_type | f64 { $$ = type::f64_type{}; } ; +function_paren_type_list +: %empty { std::vector tmp; $$ = std::move(tmp); } +| two_or_more_type_list { $$ = $1; } +; + +two_or_more_type_list +: type_expression comma type_expression { std::vector tmp; tmp.push_back(std::make_unique($1)); tmp.push_back(std::make_unique($3)); $$ = std::move(tmp); } +| two_or_more_type_list comma type_expression { auto tmp = $1; tmp.push_back(std::make_unique($3)); $$ = std::move(tmp); } +; + expression : expression ampersand expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_and, std::make_unique($1), std::make_unique($3), @$ }; } | expression vertical_bar expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_or, std::make_unique($1), std::make_unique($3), @$ }; } @@ -260,7 +277,6 @@ postfix_expression : base_expression | postfix_expression lbracket expression rbracket { $$ = ast::array_access{std::make_unique($1), std::make_unique($3), @$}; } | postfix_expression dot name { $$ = ast::field_access{std::make_unique($1), $3, @$}; } -//| postfix_expression dot name lparen comma_separated_expression_list rparen { auto args = $5; args.insert(args.begin(), std::make_unique($1)); $$ = ast::function_call{$3, std::move(args), @$}; } | postfix_expression lparen comma_separated_expression_list rparen { $$ = ast::function_call{std::make_unique($1), $3, @$}; } ; diff --git a/libs/type/include/pslang/type/function.hpp b/libs/type/include/pslang/type/function.hpp new file mode 100644 index 0000000..c5dae6e --- /dev/null +++ b/libs/type/include/pslang/type/function.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include + +namespace pslang::type +{ + + struct function_type + { + std::vector arguments; + type_ptr result; + }; + + inline bool operator == (function_type const & f1, function_type const & f2) + { + if (f1.arguments.size() != f2.arguments.size()) + return false; + + for (std::size_t i = 0; i < f1.arguments.size(); ++i) + if (!equal(*f1.arguments[i], *f2.arguments[i])) + return false; + + if (!equal(*f1.result, *f2.result)) + return false; + + return true; + } + +} diff --git a/libs/type/include/pslang/type/type.hpp b/libs/type/include/pslang/type/type.hpp index c605e80..8c49b2c 100644 --- a/libs/type/include/pslang/type/type.hpp +++ b/libs/type/include/pslang/type/type.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ namespace pslang::type unit_type, primitive_type, array_type, + function_type, identifier >; diff --git a/libs/type/source/print.cpp b/libs/type/source/print.cpp index 6ec2aae..28eb321 100644 --- a/libs/type/source/print.cpp +++ b/libs/type/source/print.cpp @@ -78,6 +78,20 @@ namespace pslang::type out << "[" << type.size << "]"; } + void print_impl(std::ostream & out, function_type const & type) + { + out << '('; + bool first = true; + for (auto const & argument : type.arguments) + { + if (!first) out << ", "; + first = false; + print(out, *argument); + } + out << ") -> "; + print(out, *type.result); + } + void print_impl(std::ostream & out, identifier const & type) { out << type.name;