From 4175a86ae32a508825cb4b5d814fb159baf8160c Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 20 Dec 2025 00:03:23 +0300 Subject: [PATCH] Rename libs/type -> libs/types, separate computed type tree from the AST type tree --- CMakeLists.txt | 2 +- libs/ast/CMakeLists.txt | 2 +- libs/ast/include/pslang/ast/cast.hpp | 4 +- libs/ast/include/pslang/ast/function.hpp | 6 +- libs/ast/include/pslang/ast/statement.hpp | 4 +- libs/ast/include/pslang/ast/struct.hpp | 4 +- libs/ast/include/pslang/ast/type.hpp | 49 +++++++ libs/ast/include/pslang/ast/type_fwd.hpp | 12 ++ libs/ast/source/print.cpp | 63 ++++++++- libs/ast/source/resolve_identifiers.cpp | 14 +- .../include/pslang/interpreter/context.hpp | 8 +- .../include/pslang/interpreter/eval.hpp | 4 +- .../include/pslang/interpreter/value.hpp | 18 ++- libs/interpreter/source/context.cpp | 4 +- libs/interpreter/source/eval.cpp | 131 +++++++++--------- libs/interpreter/source/exec.cpp | 28 ++-- libs/interpreter/source/value.cpp | 26 ++-- libs/parser/rules/pslang.y | 65 +++++---- libs/type/CMakeLists.txt | 5 - libs/type/include/pslang/type/type.hpp | 29 ---- libs/types/CMakeLists.txt | 5 + .../include/pslang/types}/array.hpp | 4 +- .../include/pslang/types}/function.hpp | 4 +- .../include/pslang/types/named.hpp} | 8 +- .../include/pslang/types}/primitive.hpp | 2 +- .../include/pslang/types}/print.hpp | 4 +- libs/types/include/pslang/types/type.hpp | 29 ++++ .../include/pslang/types}/type_fwd.hpp | 3 +- .../include/pslang/types}/unit.hpp | 2 +- libs/{type => types}/source/print.cpp | 8 +- libs/{type => types}/source/type.cpp | 4 +- 31 files changed, 335 insertions(+), 216 deletions(-) create mode 100644 libs/ast/include/pslang/ast/type.hpp create mode 100644 libs/ast/include/pslang/ast/type_fwd.hpp delete mode 100644 libs/type/CMakeLists.txt delete mode 100644 libs/type/include/pslang/type/type.hpp create mode 100644 libs/types/CMakeLists.txt rename libs/{type/include/pslang/type => types/include/pslang/types}/array.hpp (81%) rename libs/{type/include/pslang/type => types/include/pslang/types}/function.hpp (88%) rename libs/{type/include/pslang/type/identifier.hpp => types/include/pslang/types/named.hpp} (51%) rename libs/{type/include/pslang/type => types/include/pslang/types}/primitive.hpp (97%) rename libs/{type/include/pslang/type => types/include/pslang/types}/print.hpp (60%) create mode 100644 libs/types/include/pslang/types/type.hpp rename libs/{type/include/pslang/type => types/include/pslang/types}/type_fwd.hpp (85%) rename libs/{type/include/pslang/type => types/include/pslang/types}/unit.hpp (84%) rename libs/{type => types}/source/print.cpp (92%) rename libs/{type => types}/source/type.cpp (71%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03e4645..89e1146 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.30) project(pslang CXX) -add_subdirectory(libs/type) +add_subdirectory(libs/types) add_subdirectory(libs/ast) add_subdirectory(libs/parser) add_subdirectory(libs/jit) diff --git a/libs/ast/CMakeLists.txt b/libs/ast/CMakeLists.txt index 065af0b..03e6ceb 100644 --- a/libs/ast/CMakeLists.txt +++ b/libs/ast/CMakeLists.txt @@ -3,4 +3,4 @@ file(GLOB_RECURSE PSLANG_AST_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp") add_library(pslang-ast STATIC ${PSLANG_AST_HEADERS} ${PSLANG_AST_SOURCES}) target_include_directories(pslang-ast PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(pslang-ast PUBLIC pslang-type) +target_link_libraries(pslang-ast PUBLIC pslang-types) diff --git a/libs/ast/include/pslang/ast/cast.hpp b/libs/ast/include/pslang/ast/cast.hpp index 31c50df..14823cd 100644 --- a/libs/ast/include/pslang/ast/cast.hpp +++ b/libs/ast/include/pslang/ast/cast.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include namespace pslang::ast { @@ -10,7 +10,7 @@ namespace pslang::ast struct cast_operation { expression_ptr expression; - type::type_ptr type; + type_ptr type; ast::location location; }; diff --git a/libs/ast/include/pslang/ast/function.hpp b/libs/ast/include/pslang/ast/function.hpp index c832577..592ffd1 100644 --- a/libs/ast/include/pslang/ast/function.hpp +++ b/libs/ast/include/pslang/ast/function.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -16,13 +16,13 @@ namespace pslang::ast struct argument { std::string name; - type::type_ptr type; + type_ptr type; ast::location location; }; std::string name; std::vector arguments; - type::type_ptr return_type; + type_ptr return_type; statement_list_ptr statements; ast::location location; }; diff --git a/libs/ast/include/pslang/ast/statement.hpp b/libs/ast/include/pslang/ast/statement.hpp index 9b1d1c8..9fa184a 100644 --- a/libs/ast/include/pslang/ast/statement.hpp +++ b/libs/ast/include/pslang/ast/statement.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include @@ -18,7 +18,7 @@ namespace pslang::ast { value_category category; std::string name; - type::type_ptr type; + type_ptr type; expression_ptr initializer; ast::location location; }; diff --git a/libs/ast/include/pslang/ast/struct.hpp b/libs/ast/include/pslang/ast/struct.hpp index bc582f2..40bfd89 100644 --- a/libs/ast/include/pslang/ast/struct.hpp +++ b/libs/ast/include/pslang/ast/struct.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include @@ -13,7 +13,7 @@ namespace pslang::ast struct field_definition { std::string name; - type::type_ptr type; + ast::type_ptr type; ast::location location; }; diff --git a/libs/ast/include/pslang/ast/type.hpp b/libs/ast/include/pslang/ast/type.hpp new file mode 100644 index 0000000..0eee52d --- /dev/null +++ b/libs/ast/include/pslang/ast/type.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace pslang::ast +{ + + struct array_type + { + type_ptr element_type; + std::uint64_t size; + }; + + struct function_type + { + std::vector arguments; + type_ptr result; + }; + + struct type_identifier + { + std::string name; + ast::location location; + std::size_t level = 0; + }; + + using type_impl = std::variant< + types::unit_type, + types::primitive_type, + array_type, + function_type, + type_identifier + >; + + struct type + : type_impl + { + using type_impl::type_impl; + }; + +} diff --git a/libs/ast/include/pslang/ast/type_fwd.hpp b/libs/ast/include/pslang/ast/type_fwd.hpp new file mode 100644 index 0000000..7dfebe5 --- /dev/null +++ b/libs/ast/include/pslang/ast/type_fwd.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace pslang::ast +{ + + struct type; + + using type_ptr = std::shared_ptr; + +} diff --git a/libs/ast/source/print.cpp b/libs/ast/source/print.cpp index b3a9b66..7d2939a 100644 --- a/libs/ast/source/print.cpp +++ b/libs/ast/source/print.cpp @@ -1,5 +1,6 @@ #include -#include +#include +#include #include @@ -21,6 +22,56 @@ namespace pslang::ast out << options.indent_string; } + void print(std::ostream & out, type const & type, print_options const & options); + + void print_impl(std::ostream & out, types::unit_type const &, print_options const &) + { + out << "unit"; + } + + void print_impl(std::ostream & out, types::primitive_type const & type, print_options const &) + { + types::print(out, type); + } + + void print_impl(std::ostream & out, array_type const & type, print_options const & options) + { + print(out, *type.element_type, options); + out << "[" << type.size << "]"; + } + + void print_impl(std::ostream & out, function_type const & type, print_options const & options) + { + if (type.arguments.size() == 1) + { + print(out, *type.arguments.front(), options); + out << " -> "; + print(out, *type.result, options); + return; + } + + out << '('; + bool first = true; + for (auto const & argument : type.arguments) + { + if (!first) out << ", "; + first = false; + print(out, *argument, options); + } + out << ") -> "; + print(out, *type.result, options); + } + + void print_impl(std::ostream & out, type_identifier const & type, print_options const & options) + { + out << type.name; + } + + void print(std::ostream & out, type const & type, print_options const & options) + { + std::visit([&](auto const & type){ print_impl(out, type, options); }, type); + } + void print_impl(std::ostream & out, bool_literal const & node, print_options const & options) { put_indent(out, options); @@ -117,7 +168,7 @@ namespace pslang::ast { put_indent(out, options); out << "cast as "; - type::print(out, *node.type); + print(out, *node.type, options); out << '\n'; print(out, node.expression, child(options)); } @@ -174,7 +225,7 @@ namespace pslang::ast if (node.type) { out << ", type = "; - type::print(out, *node.type); + print(out, *node.type, options); } out << " }\n"; print(out, node.initializer, child(options)); @@ -234,13 +285,13 @@ namespace pslang::ast { put_indent(out, options); out << "function { name = \"" << node.name << "\", return type = "; - type::print(out, *node.return_type); + print(out, *node.return_type, options); out << " }\n"; for (auto const & arg : node.arguments) { put_indent(out, child(options)); out << "argument { name = \"" << arg.name << "\", type = "; - type::print(out, *arg.type); + print(out, *arg.type, options); out << " }\n"; } put_indent(out, child(options)); @@ -260,7 +311,7 @@ namespace pslang::ast { put_indent(out, options); out << "field { name = \"" << node.name << "\", type = "; - type::print(out, *node.type); + print(out, *node.type, options); out << " }\n"; } diff --git a/libs/ast/source/resolve_identifiers.cpp b/libs/ast/source/resolve_identifiers.cpp index 48226c1..9dd3c9d 100644 --- a/libs/ast/source/resolve_identifiers.cpp +++ b/libs/ast/source/resolve_identifiers.cpp @@ -57,29 +57,29 @@ namespace pslang::ast std::vector scopes; }; - void resolve_identifiers(context & context, type::type & type); + void resolve_identifiers(context & context, type & type); void resolve_identifiers(context & context, expression & expression); void resolve_identifiers(context & context, statement_list const & statements); - void resolve_identifiers_impl(context &, type::unit_type const &) + void resolve_identifiers_impl(context &, types::unit_type const &) {} - void resolve_identifiers_impl(context &, type::primitive_type const &) + void resolve_identifiers_impl(context &, types::primitive_type const &) {} - void resolve_identifiers_impl(context & context, type::array_type const & array_type) + void resolve_identifiers_impl(context & context, array_type const & array_type) { resolve_identifiers(context, *array_type.element_type); } - void resolve_identifiers_impl(context & context, type::function_type const & function_type) + void resolve_identifiers_impl(context & context, function_type const & function_type) { for (auto const & argument : function_type.arguments) resolve_identifiers(context, *argument); resolve_identifiers(context, *function_type.result); } - void resolve_identifiers_impl(context & context, type::identifier & identifier) + void resolve_identifiers_impl(context & context, type_identifier & identifier) { for (auto it = context.scopes.rbegin(); it != context.scopes.rend(); ++it) { @@ -94,7 +94,7 @@ namespace pslang::ast throw parse_error("Identifier \"" + identifier.name + "\" not found", {}); } - void resolve_identifiers(context & context, type::type & type) + void resolve_identifiers(context & context, type & type) { return std::visit([&](auto & type){ return resolve_identifiers_impl(context, type); }, type); } diff --git a/libs/interpreter/include/pslang/interpreter/context.hpp b/libs/interpreter/include/pslang/interpreter/context.hpp index ed82313..3405129 100644 --- a/libs/interpreter/include/pslang/interpreter/context.hpp +++ b/libs/interpreter/include/pslang/interpreter/context.hpp @@ -21,7 +21,13 @@ namespace pslang::interpreter struct struct_data { - std::vector fields; + struct field + { + std::string name; + types::type_ptr type; + }; + + std::vector fields; }; struct scope diff --git a/libs/interpreter/include/pslang/interpreter/eval.hpp b/libs/interpreter/include/pslang/interpreter/eval.hpp index 30165c9..0142fd6 100644 --- a/libs/interpreter/include/pslang/interpreter/eval.hpp +++ b/libs/interpreter/include/pslang/interpreter/eval.hpp @@ -3,11 +3,13 @@ #include #include #include +#include +#include namespace pslang::interpreter { - type::type resolve_type(context & context, type::type const & type); + types::type resolve_type(context & context, ast::type const & type); value eval(context & context, ast::expression_ptr const & expression); diff --git a/libs/interpreter/include/pslang/interpreter/value.hpp b/libs/interpreter/include/pslang/interpreter/value.hpp index 2de216c..2360b5d 100644 --- a/libs/interpreter/include/pslang/interpreter/value.hpp +++ b/libs/interpreter/include/pslang/interpreter/value.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -60,20 +60,26 @@ namespace pslang::interpreter struct array_value { // Can't infer type from elements in case of zero-sized array - type::type_ptr element_type; + types::type_ptr element_type; std::vector elements; }; struct struct_value { - type::type_ptr struct_type; + types::type_ptr struct_type; std::unordered_map fields; }; struct function_value { - std::vector arguments; - type::type_ptr return_type; + struct argument + { + std::string name; + types::type_ptr type; + }; + + std::vector arguments; + types::type_ptr return_type; ast::statement_list_ptr statements; }; @@ -91,7 +97,7 @@ namespace pslang::interpreter using value_impl::value_impl; }; - type::type type_of(value const & value); + types::type type_of(value const & value); void print(std::ostream & out, value const & value); diff --git a/libs/interpreter/source/context.cpp b/libs/interpreter/source/context.cpp index 30af7cc..0a94b76 100644 --- a/libs/interpreter/source/context.cpp +++ b/libs/interpreter/source/context.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace pslang::interpreter { @@ -20,7 +20,7 @@ namespace pslang::interpreter out << variable.first << " = "; print(out, variable.second.value); out << " ("; - type::print(out, type_of(variable.second.value)); + types::print(out, type_of(variable.second.value)); out << ")\n"; } } diff --git a/libs/interpreter/source/eval.cpp b/libs/interpreter/source/eval.cpp index 74577f4..39a52a8 100644 --- a/libs/interpreter/source/eval.cpp +++ b/libs/interpreter/source/eval.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include @@ -13,44 +13,36 @@ namespace pslang::interpreter namespace { - type::type resolve_type_impl(context &, type::unit_type const & type) + types::type resolve_type_impl(context &, types::unit_type const & type) { return type; } - type::type resolve_type_impl(context &, type::primitive_type const & type) + types::type resolve_type_impl(context &, types::primitive_type const & type) { return type; } - type::type resolve_type_impl(context & context, type::array_type const & type) + types::type resolve_type_impl(context & context, ast::array_type const & type) { - return type::array_type{std::make_unique(resolve_type(context, *type.element_type)), type.size}; + return types::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) + types::type resolve_type_impl(context & context, ast::function_type const & type) { - type::function_type result; + types::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)); + 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) + types::type resolve_type_impl(context & context, ast::type_identifier const & type) { - for (auto it = context.scope_stack.rbegin(); it != context.scope_stack.rend(); ++it) - { - if (it->structs.count(type.name)) - { - return type::identifier{std::string(it.base() - context.scope_stack.begin() - 1, '/') + type.name}; - } - } - - throw std::runtime_error("Type \"" + type.name + "\" is not defined"); + return types::named_type{type.name, type.level}; } - type::type resolve_type_impl(context & context, type::type const & type) + types::type resolve_type_impl(context & context, ast::type const & type) { return std::visit([&](auto const & type){ return resolve_type_impl(context, type); }, type); } @@ -166,7 +158,7 @@ namespace pslang::interpreter { std::ostringstream os; os << "Cannot index into an array with an expression of type "; - type::print(os, type_of(index)); + types::print(os, type_of(index)); throw std::runtime_error(os.str()); } @@ -223,7 +215,7 @@ namespace pslang::interpreter os << "Cannot apply unary operator \""; print(os, type); os << "\" to a value of type "; - type::print(os, type_of(value)); + types::print(os, type_of(value)); throw std::runtime_error(os.str()); } @@ -254,7 +246,7 @@ namespace pslang::interpreter os << "Cannot apply unary operator \""; print(os, type); os << "\" to a value of type "; - type::print(os, type_of(primitive_value(arg1))); + types::print(os, type_of(primitive_value(arg1))); throw std::runtime_error(os.str()); } @@ -370,9 +362,9 @@ namespace pslang::interpreter os << "Cannot apply binary operator \""; print(os, type); os << "\" to values of type "; - type::print(os, type_of(primitive_value(arg1))); + types::print(os, type_of(primitive_value(arg1))); os << " and "; - type::print(os, type_of(primitive_value(arg2))); + types::print(os, type_of(primitive_value(arg2))); throw std::runtime_error(os.str()); } @@ -383,9 +375,9 @@ namespace pslang::interpreter os << "Cannot apply binary operator \""; print(os, type); os << "\" to values of type "; - type::print(os, type_of(arg1)); + types::print(os, type_of(arg1)); os << " and "; - type::print(os, type_of(arg2)); + types::print(os, type_of(arg2)); throw std::runtime_error(os.str()); } @@ -404,15 +396,15 @@ namespace pslang::interpreter auto type1 = type_of(arg1); auto type2 = type_of(arg2); - if (!type::equal(type1, type2)) + if (!types::equal(type1, type2)) { std::ostringstream os; os << "Cannot apply binary operator \""; print(os, binary_operation.type); os << "\" to values of type "; - type::print(os, type1); + types::print(os, type1); os << " and "; - type::print(os, type2); + types::print(os, type2); throw std::runtime_error(os.str()); } @@ -422,30 +414,30 @@ namespace pslang::interpreter throw std::runtime_error("eval(binary_operation) for different argument types not implemented"); } - value cast_impl(unit_value const & value, type::type const & type) + value cast_impl(unit_value const & value, types::type const & type) { - if (type::equal(type, type::unit_type{})) + if (types::equal(type, types::unit_type{})) return value; throw std::runtime_error("Cannot cast unit type to anything"); } - value cast_impl(array_value const & value, type::type const & type) + value cast_impl(array_value const & value, types::type const & type) { - if (type::equal(type, type_of(value))) + if (types::equal(type, type_of(value))) return value; throw std::runtime_error("Cannot cast array type to anything"); } template - value cast_impl(primitive_value_base const & value, type::unit_type const &) + value cast_impl(primitive_value_base const & value, types::unit_type const &) { throw std::runtime_error("Cannot cast anything to unit type"); } template - value cast_impl(primitive_value_base const & value, type::primitive_type_base const & type) + value cast_impl(primitive_value_base const & value, types::primitive_type_base const & type) { if constexpr (std::is_same_v) { @@ -458,50 +450,50 @@ namespace pslang::interpreter std::ostringstream os; os << "Cannot cast value of type "; - type::print(os, type_of(primitive_value(value))); + types::print(os, type_of(primitive_value(value))); os << " to type "; - type::print(os, type::primitive_type(type)); + types::print(os, types::primitive_type(type)); throw std::runtime_error(os.str()); } template - value cast_impl(primitive_value_base const & value, type::primitive_type const & type) + value cast_impl(primitive_value_base const & value, types::primitive_type const & type) { return std::visit([&](auto const & type){ return cast_impl(value, type); }, type); } template - value cast_impl(primitive_value_base const &, type::array_type const &) + value cast_impl(primitive_value_base const &, types::array_type const &) { throw std::runtime_error("Cannot cast anything to array type"); } template - value cast_impl(primitive_value_base const &, type::function_type const &) + value cast_impl(primitive_value_base const &, types::function_type const &) { throw std::runtime_error("Cannot cast anything to function type"); } template - value cast_impl(primitive_value_base const & value, type::type const & type) + value cast_impl(primitive_value_base const & value, types::type const & type) { return std::visit([&](auto const & type){ return cast_impl(value, type); }, type); } - value cast_impl(primitive_value const & value, type::type const & type) + value cast_impl(primitive_value const & value, types::type const & type) { return std::visit([&](auto const & value){ return cast_impl(value, type); }, value); } - value cast_impl(struct_value const & value, type::type const & type) + value cast_impl(struct_value const & value, types::type const & type) { - if (type::equal(type, type::unit_type{})) + if (types::equal(type, types::unit_type{})) return value; throw std::runtime_error("Cannot cast struct type to anything"); } - value cast_impl(function_value const &, type::type const &) + value cast_impl(function_value const &, types::type const &) { throw std::runtime_error("Cannot cast function type to anything"); } @@ -509,7 +501,8 @@ namespace pslang::interpreter value eval_impl(context & context, ast::cast_operation const & cast_operation) { auto arg = eval(context, cast_operation.expression); - return std::visit([&](auto const & value){ return cast_impl(value, *cast_operation.type); }, arg); + auto type = resolve_type(context, *cast_operation.type); + return std::visit([&](auto const & value){ return cast_impl(value, type); }, arg); } value eval_impl(context & context, ast::function_call const & function_call) @@ -537,13 +530,13 @@ namespace pslang::interpreter for (std::size_t i = 0; i < args.size(); ++i) { auto actual_type = type_of(args[i]); - if (!type::equal(actual_type, *jt->second.fields[i].type)) + if (!types::equal(actual_type, *jt->second.fields[i].type)) { std::ostringstream os; os << "Cannot create struct \"" << identifier->name << "\": field " << jt->second.fields[i].name << " expects type "; - type::print(os, *jt->second.fields[i].type); + types::print(os, *jt->second.fields[i].type); os << " but actual type is "; - type::print(os, actual_type); + types::print(os, actual_type); throw std::runtime_error(os.str()); } @@ -551,7 +544,7 @@ namespace pslang::interpreter } return struct_value{ - .struct_type = std::make_unique(resolve_type(context, type::identifier{identifier->name})), + .struct_type = std::make_unique(types::named_type{.name = identifier->name, .level = identifier->level}), .fields = std::move(fields), }; } @@ -576,13 +569,13 @@ namespace pslang::interpreter for (std::size_t i = 0; i < args.size(); ++i) { auto actual_type = type_of(args[i]); - if (!type::equal(actual_type, *fvalue->arguments[i].type)) + if (!types::equal(actual_type, *fvalue->arguments[i].type)) { std::ostringstream os; os << "Cannot call function: argument #" << (i + 1) << " expects type "; - type::print(os, *fvalue->arguments[i].type); + types::print(os, *fvalue->arguments[i].type); os << " but actual type is "; - type::print(os, actual_type); + types::print(os, actual_type); throw std::runtime_error(os.str()); } } @@ -598,13 +591,13 @@ namespace pslang::interpreter exec(context, fvalue->statements); auto actual_return_type = type_of(context.scope_stack.back().return_value); - if (!type::equal(actual_return_type, *expected_return_type)) + if (!types::equal(actual_return_type, *expected_return_type)) { std::ostringstream os; os << "Error returning from function: expected return type is "; - type::print(os, *expected_return_type); + types::print(os, *expected_return_type); os << " but actual type is "; - type::print(os, actual_return_type); + types::print(os, actual_return_type); throw std::runtime_error(os.str()); } @@ -625,23 +618,23 @@ namespace pslang::interpreter if (array.elements.empty()) throw std::runtime_error("Internal error: array ast node cannot have zero elements"); - type::type_ptr element_type; + types::type_ptr element_type; std::vector elements; for (std::size_t i = 0; i < array.elements.size(); ++i) { auto element = std::make_unique(eval(context, array.elements[i])); if (i == 0) - element_type = std::make_unique(type_of(*element)); + element_type = std::make_unique(type_of(*element)); else { auto new_type = type_of(*element); - if (!type::equal(*element_type, new_type)) + if (!types::equal(*element_type, new_type)) { std::ostringstream os; os << "Error forming array: inferred element type is "; - type::print(os, *element_type); + types::print(os, *element_type); os << " but element #" << i << " type is "; - type::print(os, new_type); + types::print(os, new_type); throw std::runtime_error(os.str()); } } @@ -664,7 +657,7 @@ namespace pslang::interpreter std::ostringstream os; os << "Cannot index into a non-array of type "; - type::print(os, type_of(array)); + types::print(os, type_of(array)); throw std::runtime_error(os.str()); } @@ -678,14 +671,14 @@ namespace pslang::interpreter std::ostringstream os; os << "Struct "; - type::print(os, type_of(object)); + types::print(os, type_of(object)); os << " has no field named \"" << field_access.field_name << "\""; throw std::runtime_error(os.str()); } std::ostringstream os; os << "Value of type "; - type::print(os, type_of(object)); + types::print(os, type_of(object)); os << " is not a struct"; throw std::runtime_error(os.str()); } @@ -753,7 +746,7 @@ namespace pslang::interpreter std::ostringstream os; os << "Cannot index into a non-array of type "; - type::print(os, type_of(*array_ref)); + types::print(os, type_of(*array_ref)); throw std::runtime_error(os.str()); } @@ -767,14 +760,14 @@ namespace pslang::interpreter std::ostringstream os; os << "Struct "; - type::print(os, type_of(*object_ref)); + types::print(os, type_of(*object_ref)); os << " has no field named \"" << field_access.field_name << "\""; throw std::runtime_error(os.str()); } std::ostringstream os; os << "Value of type "; - type::print(os, type_of(*object_ref)); + types::print(os, type_of(*object_ref)); os << " is not a struct"; throw std::runtime_error(os.str()); } @@ -786,7 +779,7 @@ namespace pslang::interpreter } - type::type resolve_type(context & context, type::type const & type) + types::type resolve_type(context & context, ast::type const & type) { return resolve_type_impl(context, type); } diff --git a/libs/interpreter/source/exec.cpp b/libs/interpreter/source/exec.cpp index b82ce8a..d7e9572 100644 --- a/libs/interpreter/source/exec.cpp +++ b/libs/interpreter/source/exec.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include @@ -43,13 +43,13 @@ namespace pslang::interpreter auto ref = eval_ref(context, assignment.lhs); auto existing_type = type_of(*ref); - if (!type::equal(existing_type, new_type)) + if (!types::equal(existing_type, new_type)) { std::ostringstream os; os << "Cannot assign a value of type "; - type::print(os, new_type); + types::print(os, new_type); os << " to a variable of type "; - type::print(os, existing_type); + types::print(os, existing_type); throw std::runtime_error(os.str()); } @@ -67,13 +67,13 @@ namespace pslang::interpreter { auto expected_type = resolve_type(context, *variable_declaration.type); auto actual_type = type_of(value); - if (!type::equal(expected_type, actual_type)) + if (!types::equal(expected_type, actual_type)) { std::ostringstream os; os << "Cannot initialize a variable of type "; - type::print(os, expected_type); + types::print(os, expected_type); os << " with an expression of type "; - type::print(os, actual_type); + types::print(os, actual_type); throw std::runtime_error(os.str()); } } @@ -105,11 +105,11 @@ namespace pslang::interpreter { auto value = eval(context, block.condition); auto actual_type = type_of(value); - if (!type::equal(actual_type, type::primitive_type{type::bool_type{}})) + if (!types::equal(actual_type, types::primitive_type{types::bool_type{}})) { std::ostringstream os; os << "Expected type bool, got type "; - type::print(os, actual_type); + types::print(os, actual_type); os << " in if block condition"; throw std::runtime_error(os.str()); } @@ -133,11 +133,11 @@ namespace pslang::interpreter { auto value = eval(context, while_block.condition); auto actual_type = type_of(value); - if (!type::equal(actual_type, type::primitive_type{type::bool_type{}})) + if (!types::equal(actual_type, types::primitive_type{types::bool_type{}})) { std::ostringstream os; os << "Expected type bool, got type "; - type::print(os, actual_type); + types::print(os, actual_type); os << " in while block condition"; throw std::runtime_error(os.str()); } @@ -162,8 +162,8 @@ namespace pslang::interpreter function_value value; for (auto const & argument : function_definition.arguments) - value.arguments.push_back({.name = argument.name, .type = std::make_unique(resolve_type(context, *argument.type))}); - value.return_type = std::make_unique(resolve_type(context, *function_definition.return_type)); + value.arguments.push_back({.name = argument.name, .type = std::make_unique(resolve_type(context, *argument.type))}); + value.return_type = std::make_unique(resolve_type(context, *function_definition.return_type)); value.statements = function_definition.statements; scope.variables[function_definition.name] = {.category = ast::value_category::constant, .value = std::move(value)}; @@ -200,7 +200,7 @@ namespace pslang::interpreter { result.fields.push_back({ .name = field.name, - .type = std::make_unique(resolve_type(context, *field.type)), + .type = std::make_unique(resolve_type(context, *field.type)), }); } scope.structs[struct_definition.name] = std::move(result); diff --git a/libs/interpreter/source/value.cpp b/libs/interpreter/source/value.cpp index fcae499..621ade1 100644 --- a/libs/interpreter/source/value.cpp +++ b/libs/interpreter/source/value.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include @@ -9,42 +9,42 @@ namespace pslang::interpreter namespace { - type::type type_of_impl(unit_value const &) + types::type type_of_impl(unit_value const &) { - return type::unit_type{}; + return types::unit_type{}; } template - type::type type_of_impl(primitive_value_base const &) + types::type type_of_impl(primitive_value_base const &) { - return type::primitive_type(type::primitive_type_base{}); + return types::primitive_type(types::primitive_type_base{}); } - type::type type_of_impl(primitive_value const & value) + types::type type_of_impl(primitive_value const & value) { return std::visit([](auto const & value){ return type_of_impl(value); }, value); } - type::type type_of_impl(array_value const & value) + types::type type_of_impl(array_value const & value) { - return type::array_type{.element_type = value.element_type, .size = value.elements.size()}; + return types::array_type{.element_type = value.element_type, .size = value.elements.size()}; } - type::type type_of_impl(struct_value const & value) + types::type type_of_impl(struct_value const & value) { return *value.struct_type; } - type::type type_of_impl(function_value const & value) + types::type type_of_impl(function_value const & value) { - type::function_type result; + types::function_type result; for (auto const & argument : value.arguments) result.arguments.push_back(argument.type); result.result = value.return_type; return result; } - type::type type_of_impl(value const & value) + types::type type_of_impl(value const & value) { return std::visit([](auto const & value){ return type_of_impl(value); }, value); } @@ -127,7 +127,7 @@ namespace pslang::interpreter } - type::type type_of(value const & value) + types::type type_of(value const & value) { return type_of_impl(value); } diff --git a/libs/parser/rules/pslang.y b/libs/parser/rules/pslang.y index 5203c80..e8f9ea3 100644 --- a/libs/parser/rules/pslang.y +++ b/libs/parser/rules/pslang.y @@ -20,9 +20,8 @@ %code requires { -#include -#include #include +#include namespace pslang::parser { @@ -149,13 +148,13 @@ template %type > function_definition_argument_list %type > nonempty_function_definition_argument_list %type function_definition_single_argument -%type function_return_type +%type function_return_type %type variable_declaration %type variable_keyword -%type type_expression -%type primitive_type -%type > function_paren_type_list -%type > two_or_more_type_list +%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 @@ -192,7 +191,7 @@ statement | return expression { $$ = ast::return_statement{std::make_unique($2), @$}; } | return { $$ = ast::return_statement{nullptr, @$}; } | struct name colon { $$ = ast::struct_definition{$2, {}, @$}; } -| name colon type_expression { $$ = ast::field_definition{$1, std::make_unique($3), @$}; } +| name colon type_expression { $$ = ast::field_definition{$1, std::make_unique($3), @$}; } ; function_definition_argument_list @@ -206,17 +205,17 @@ nonempty_function_definition_argument_list ; function_definition_single_argument -: name colon type_expression { $$ = ast::function_definition::argument{$1, std::make_unique($3), @$}; } +: name colon type_expression { $$ = ast::function_definition::argument{$1, std::make_unique($3), @$}; } ; function_return_type -: arrow type_expression { $$ = std::make_unique($2); } -| %empty { $$ = std::make_unique(type::unit_type{}); } +: arrow type_expression { $$ = std::make_unique($2); } +| %empty { $$ = std::make_unique(types::unit_type{}); } ; variable_declaration : variable_keyword name assignment expression { $$ = ast::variable_declaration{$1, $2, nullptr, std::make_unique($4), @$}; } -| variable_keyword name colon type_expression assignment expression { $$ = ast::variable_declaration{$1, $2, std::make_unique($4), std::make_unique($6), @$}; } +| variable_keyword name colon type_expression assignment expression { $$ = ast::variable_declaration{$1, $2, std::make_unique($4), std::make_unique($6), @$}; } ; variable_keyword @@ -226,37 +225,37 @@ variable_keyword ; type_expression -: unit { $$ = type::type(type::unit_type{}); } -| 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)}; } +: unit { $$ = types::unit_type{}; } +| primitive_type { $$ = ast::type($1); } +| name { $$ = ast::type_identifier{$1}; } +| type_expression lbracket lit_i32 rbracket { $$ = ast::array_type{std::make_unique($1), std::stoull($3)}; } +| type_expression arrow type_expression { std::vector args; args.push_back(std::make_unique($1)); $$ = ast::function_type{std::move(args), std::make_unique($3)}; } +| lparen function_paren_type_list rparen arrow type_expression { $$ = ast::function_type{$2, std::make_unique($5)}; } | lparen type_expression rparen { $$ = $2; } ; primitive_type -: bool { $$ = type::bool_type{}; } -| i8 { $$ = type::i8_type{}; } -| u8 { $$ = type::u8_type{}; } -| i16 { $$ = type::i16_type{}; } -| u16 { $$ = type::u16_type{}; } -| i32 { $$ = type::i32_type{}; } -| u32 { $$ = type::u32_type{}; } -| i64 { $$ = type::i64_type{}; } -| u64 { $$ = type::u64_type{}; } -| f32 { $$ = type::f32_type{}; } -| f64 { $$ = type::f64_type{}; } +: bool { $$ = types::bool_type{}; } +| i8 { $$ = types::i8_type{}; } +| u8 { $$ = types::u8_type{}; } +| i16 { $$ = types::i16_type{}; } +| u16 { $$ = types::u16_type{}; } +| i32 { $$ = types::i32_type{}; } +| u32 { $$ = types::u32_type{}; } +| i64 { $$ = types::i64_type{}; } +| u64 { $$ = types::u64_type{}; } +| f32 { $$ = types::f32_type{}; } +| f64 { $$ = types::f64_type{}; } ; function_paren_type_list -: %empty { std::vector tmp; $$ = std::move(tmp); } +: %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); } +: 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 @@ -269,7 +268,7 @@ expression | expression greater expression { $$ = ast::binary_operation{ast::binary_operation_type::greater, std::make_unique($1), std::make_unique($3), @$ }; } | expression less_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::less_equals, std::make_unique($1), std::make_unique($3), @$ }; } | expression greater_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::greater_equals, std::make_unique($1), std::make_unique($3), @$ }; } -| expression as type_expression { $$ = ast::cast_operation{ std::make_unique($1), std::make_unique($3), @$ }; } +| expression as type_expression { $$ = ast::cast_operation{ std::make_unique($1), std::make_unique($3), @$ }; } | minus expression %prec UMINUS { $$ = ast::unary_operation{ast::unary_operation_type::negation, std::make_unique($2), @$ }; } | expression plus expression { $$ = ast::binary_operation{ast::binary_operation_type::addition, std::make_unique($1), std::make_unique($3), @$ }; } | expression minus expression { $$ = ast::binary_operation{ast::binary_operation_type::subtraction, std::make_unique($1), std::make_unique($3), @$ }; } diff --git a/libs/type/CMakeLists.txt b/libs/type/CMakeLists.txt deleted file mode 100644 index 894b612..0000000 --- a/libs/type/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -file(GLOB_RECURSE PSLANG_TYPE_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp") -file(GLOB_RECURSE PSLANG_TYPE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp") - -add_library(pslang-type STATIC ${PSLANG_TYPE_HEADERS} ${PSLANG_TYPE_SOURCES}) -target_include_directories(pslang-type PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/libs/type/include/pslang/type/type.hpp b/libs/type/include/pslang/type/type.hpp deleted file mode 100644 index 8c49b2c..0000000 --- a/libs/type/include/pslang/type/type.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -namespace pslang::type -{ - - using type_impl = std::variant< - unit_type, - primitive_type, - array_type, - function_type, - identifier - >; - - struct type - : type_impl - { - using type_impl::type_impl; - }; - -} diff --git a/libs/types/CMakeLists.txt b/libs/types/CMakeLists.txt new file mode 100644 index 0000000..e5f3a1d --- /dev/null +++ b/libs/types/CMakeLists.txt @@ -0,0 +1,5 @@ +file(GLOB_RECURSE PSLANG_TYPES_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp") +file(GLOB_RECURSE PSLANG_TYPES_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp") + +add_library(pslang-types STATIC ${PSLANG_TYPES_HEADERS} ${PSLANG_TYPES_SOURCES}) +target_include_directories(pslang-types PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/libs/type/include/pslang/type/array.hpp b/libs/types/include/pslang/types/array.hpp similarity index 81% rename from libs/type/include/pslang/type/array.hpp rename to libs/types/include/pslang/types/array.hpp index b51c695..300b965 100644 --- a/libs/type/include/pslang/type/array.hpp +++ b/libs/types/include/pslang/types/array.hpp @@ -1,10 +1,10 @@ #pragma once -#include +#include #include -namespace pslang::type +namespace pslang::types { struct array_type diff --git a/libs/type/include/pslang/type/function.hpp b/libs/types/include/pslang/types/function.hpp similarity index 88% rename from libs/type/include/pslang/type/function.hpp rename to libs/types/include/pslang/types/function.hpp index c5dae6e..331f63c 100644 --- a/libs/type/include/pslang/type/function.hpp +++ b/libs/types/include/pslang/types/function.hpp @@ -1,10 +1,10 @@ #pragma once -#include +#include #include -namespace pslang::type +namespace pslang::types { struct function_type diff --git a/libs/type/include/pslang/type/identifier.hpp b/libs/types/include/pslang/types/named.hpp similarity index 51% rename from libs/type/include/pslang/type/identifier.hpp rename to libs/types/include/pslang/types/named.hpp index 74ec88d..1e825f3 100644 --- a/libs/type/include/pslang/type/identifier.hpp +++ b/libs/types/include/pslang/types/named.hpp @@ -2,16 +2,16 @@ #include -namespace pslang::type +namespace pslang::types { - struct identifier + struct named_type { std::string name; - std::size_t level = 0; + std::size_t level; }; - inline bool operator == (identifier const & t1, identifier const & t2) + inline bool operator == (named_type const & t1, named_type const & t2) { return (t1.level == t2.level) && (t1.name == t2.name); } diff --git a/libs/type/include/pslang/type/primitive.hpp b/libs/types/include/pslang/types/primitive.hpp similarity index 97% rename from libs/type/include/pslang/type/primitive.hpp rename to libs/types/include/pslang/types/primitive.hpp index 6d51c09..3ea7fde 100644 --- a/libs/type/include/pslang/type/primitive.hpp +++ b/libs/types/include/pslang/types/primitive.hpp @@ -3,7 +3,7 @@ #include #include -namespace pslang::type +namespace pslang::types { template diff --git a/libs/type/include/pslang/type/print.hpp b/libs/types/include/pslang/types/print.hpp similarity index 60% rename from libs/type/include/pslang/type/print.hpp rename to libs/types/include/pslang/types/print.hpp index 3900956..7e3c3f1 100644 --- a/libs/type/include/pslang/type/print.hpp +++ b/libs/types/include/pslang/types/print.hpp @@ -1,10 +1,10 @@ #pragma once -#include +#include #include -namespace pslang::type +namespace pslang::types { void print(std::ostream & out, type const & type); diff --git a/libs/types/include/pslang/types/type.hpp b/libs/types/include/pslang/types/type.hpp new file mode 100644 index 0000000..767a477 --- /dev/null +++ b/libs/types/include/pslang/types/type.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +namespace pslang::types +{ + + using type_impl = std::variant< + unit_type, + primitive_type, + array_type, + function_type, + named_type + >; + + struct type + : type_impl + { + using type_impl::type_impl; + }; + +} diff --git a/libs/type/include/pslang/type/type_fwd.hpp b/libs/types/include/pslang/types/type_fwd.hpp similarity index 85% rename from libs/type/include/pslang/type/type_fwd.hpp rename to libs/types/include/pslang/types/type_fwd.hpp index e844f2d..577febb 100644 --- a/libs/type/include/pslang/type/type_fwd.hpp +++ b/libs/types/include/pslang/types/type_fwd.hpp @@ -2,7 +2,7 @@ #include -namespace pslang::type +namespace pslang::types { struct type; @@ -10,4 +10,5 @@ namespace pslang::type using type_ptr = std::shared_ptr; bool equal(type const & t1, type const & t2); + } diff --git a/libs/type/include/pslang/type/unit.hpp b/libs/types/include/pslang/types/unit.hpp similarity index 84% rename from libs/type/include/pslang/type/unit.hpp rename to libs/types/include/pslang/types/unit.hpp index 1b9928b..50a3056 100644 --- a/libs/type/include/pslang/type/unit.hpp +++ b/libs/types/include/pslang/types/unit.hpp @@ -1,6 +1,6 @@ #pragma once -namespace pslang::type +namespace pslang::types { struct unit_type diff --git a/libs/type/source/print.cpp b/libs/types/source/print.cpp similarity index 92% rename from libs/type/source/print.cpp rename to libs/types/source/print.cpp index 635b326..b8621a6 100644 --- a/libs/type/source/print.cpp +++ b/libs/types/source/print.cpp @@ -1,7 +1,7 @@ -#include -#include +#include +#include -namespace pslang::type +namespace pslang::types { namespace @@ -100,7 +100,7 @@ namespace pslang::type print(out, *type.result); } - void print_impl(std::ostream & out, identifier const & type) + void print_impl(std::ostream & out, named_type const & type) { out << type.name; } diff --git a/libs/type/source/type.cpp b/libs/types/source/type.cpp similarity index 71% rename from libs/type/source/type.cpp rename to libs/types/source/type.cpp index b216bd1..5921287 100644 --- a/libs/type/source/type.cpp +++ b/libs/types/source/type.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace pslang::type +namespace pslang::types { bool equal(type const & t1, type const & t2)