Rename libs/type -> libs/types, separate computed type tree from the AST type tree

This commit is contained in:
Nikita Lisitsa 2025-12-20 00:03:23 +03:00
parent 437123f6f4
commit 4175a86ae3
31 changed files with 335 additions and 216 deletions

View file

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.30) cmake_minimum_required(VERSION 3.30)
project(pslang CXX) project(pslang CXX)
add_subdirectory(libs/type) add_subdirectory(libs/types)
add_subdirectory(libs/ast) add_subdirectory(libs/ast)
add_subdirectory(libs/parser) add_subdirectory(libs/parser)
add_subdirectory(libs/jit) add_subdirectory(libs/jit)

View file

@ -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}) add_library(pslang-ast STATIC ${PSLANG_AST_HEADERS} ${PSLANG_AST_SOURCES})
target_include_directories(pslang-ast PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") 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)

View file

@ -2,7 +2,7 @@
#include <pslang/ast/expression_fwd.hpp> #include <pslang/ast/expression_fwd.hpp>
#include <pslang/ast/location.hpp> #include <pslang/ast/location.hpp>
#include <pslang/type/type.hpp> #include <pslang/ast/type.hpp>
namespace pslang::ast namespace pslang::ast
{ {
@ -10,7 +10,7 @@ namespace pslang::ast
struct cast_operation struct cast_operation
{ {
expression_ptr expression; expression_ptr expression;
type::type_ptr type; type_ptr type;
ast::location location; ast::location location;
}; };

View file

@ -3,7 +3,7 @@
#include <pslang/ast/statement_fwd.hpp> #include <pslang/ast/statement_fwd.hpp>
#include <pslang/ast/expression_fwd.hpp> #include <pslang/ast/expression_fwd.hpp>
#include <pslang/ast/location.hpp> #include <pslang/ast/location.hpp>
#include <pslang/type/type_fwd.hpp> #include <pslang/ast/type_fwd.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
@ -16,13 +16,13 @@ namespace pslang::ast
struct argument struct argument
{ {
std::string name; std::string name;
type::type_ptr type; type_ptr type;
ast::location location; ast::location location;
}; };
std::string name; std::string name;
std::vector<argument> arguments; std::vector<argument> arguments;
type::type_ptr return_type; type_ptr return_type;
statement_list_ptr statements; statement_list_ptr statements;
ast::location location; ast::location location;
}; };

View file

@ -7,7 +7,7 @@
#include <pslang/ast/function.hpp> #include <pslang/ast/function.hpp>
#include <pslang/ast/struct.hpp> #include <pslang/ast/struct.hpp>
#include <pslang/ast/statement_fwd.hpp> #include <pslang/ast/statement_fwd.hpp>
#include <pslang/type/type.hpp> #include <pslang/ast/type.hpp>
#include <variant> #include <variant>
@ -18,7 +18,7 @@ namespace pslang::ast
{ {
value_category category; value_category category;
std::string name; std::string name;
type::type_ptr type; type_ptr type;
expression_ptr initializer; expression_ptr initializer;
ast::location location; ast::location location;
}; };

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <pslang/type/type_fwd.hpp>
#include <pslang/ast/expression_fwd.hpp> #include <pslang/ast/expression_fwd.hpp>
#include <pslang/ast/type_fwd.hpp>
#include <pslang/ast/location.hpp> #include <pslang/ast/location.hpp>
#include <string> #include <string>
@ -13,7 +13,7 @@ namespace pslang::ast
struct field_definition struct field_definition
{ {
std::string name; std::string name;
type::type_ptr type; ast::type_ptr type;
ast::location location; ast::location location;
}; };

View file

@ -0,0 +1,49 @@
#pragma once
#include <pslang/types/unit.hpp>
#include <pslang/types/primitive.hpp>
#include <pslang/types/array.hpp>
#include <pslang/types/function.hpp>
#include <pslang/types/type_fwd.hpp>
#include <pslang/ast/location.hpp>
#include <pslang/ast/type_fwd.hpp>
#include <variant>
namespace pslang::ast
{
struct array_type
{
type_ptr element_type;
std::uint64_t size;
};
struct function_type
{
std::vector<type_ptr> 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;
};
}

View file

@ -0,0 +1,12 @@
#pragma once
#include <memory>
namespace pslang::ast
{
struct type;
using type_ptr = std::shared_ptr<type>;
}

View file

@ -1,5 +1,6 @@
#include <pslang/ast/print.hpp> #include <pslang/ast/print.hpp>
#include <pslang/type/print.hpp> #include <pslang/types/print.hpp>
#include <pslang/types/type.hpp>
#include <iomanip> #include <iomanip>
@ -21,6 +22,56 @@ namespace pslang::ast
out << options.indent_string; 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) void print_impl(std::ostream & out, bool_literal const & node, print_options const & options)
{ {
put_indent(out, options); put_indent(out, options);
@ -117,7 +168,7 @@ namespace pslang::ast
{ {
put_indent(out, options); put_indent(out, options);
out << "cast as "; out << "cast as ";
type::print(out, *node.type); print(out, *node.type, options);
out << '\n'; out << '\n';
print(out, node.expression, child(options)); print(out, node.expression, child(options));
} }
@ -174,7 +225,7 @@ namespace pslang::ast
if (node.type) if (node.type)
{ {
out << ", type = "; out << ", type = ";
type::print(out, *node.type); print(out, *node.type, options);
} }
out << " }\n"; out << " }\n";
print(out, node.initializer, child(options)); print(out, node.initializer, child(options));
@ -234,13 +285,13 @@ namespace pslang::ast
{ {
put_indent(out, options); put_indent(out, options);
out << "function { name = \"" << node.name << "\", return type = "; out << "function { name = \"" << node.name << "\", return type = ";
type::print(out, *node.return_type); print(out, *node.return_type, options);
out << " }\n"; out << " }\n";
for (auto const & arg : node.arguments) for (auto const & arg : node.arguments)
{ {
put_indent(out, child(options)); put_indent(out, child(options));
out << "argument { name = \"" << arg.name << "\", type = "; out << "argument { name = \"" << arg.name << "\", type = ";
type::print(out, *arg.type); print(out, *arg.type, options);
out << " }\n"; out << " }\n";
} }
put_indent(out, child(options)); put_indent(out, child(options));
@ -260,7 +311,7 @@ namespace pslang::ast
{ {
put_indent(out, options); put_indent(out, options);
out << "field { name = \"" << node.name << "\", type = "; out << "field { name = \"" << node.name << "\", type = ";
type::print(out, *node.type); print(out, *node.type, options);
out << " }\n"; out << " }\n";
} }

View file

@ -57,29 +57,29 @@ namespace pslang::ast
std::vector<scope> scopes; std::vector<scope> 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, expression & expression);
void resolve_identifiers(context & context, statement_list const & statements); 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); 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) for (auto const & argument : function_type.arguments)
resolve_identifiers(context, *argument); resolve_identifiers(context, *argument);
resolve_identifiers(context, *function_type.result); 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) 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", {}); 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); return std::visit([&](auto & type){ return resolve_identifiers_impl(context, type); }, type);
} }

View file

@ -21,7 +21,13 @@ namespace pslang::interpreter
struct struct_data struct struct_data
{ {
std::vector<ast::field_definition> fields; struct field
{
std::string name;
types::type_ptr type;
};
std::vector<field> fields;
}; };
struct scope struct scope

View file

@ -3,11 +3,13 @@
#include <pslang/interpreter/context.hpp> #include <pslang/interpreter/context.hpp>
#include <pslang/interpreter/value.hpp> #include <pslang/interpreter/value.hpp>
#include <pslang/ast/expression_fwd.hpp> #include <pslang/ast/expression_fwd.hpp>
#include <pslang/ast/type_fwd.hpp>
#include <pslang/types/type.hpp>
namespace pslang::interpreter 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); value eval(context & context, ast::expression_ptr const & expression);

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <pslang/type/type.hpp> #include <pslang/types/type.hpp>
#include <pslang/ast/function.hpp> #include <pslang/ast/function.hpp>
#include <pslang/interpreter/value_fwd.hpp> #include <pslang/interpreter/value_fwd.hpp>
@ -60,20 +60,26 @@ namespace pslang::interpreter
struct array_value struct array_value
{ {
// Can't infer type from elements in case of zero-sized array // Can't infer type from elements in case of zero-sized array
type::type_ptr element_type; types::type_ptr element_type;
std::vector<value_ptr> elements; std::vector<value_ptr> elements;
}; };
struct struct_value struct struct_value
{ {
type::type_ptr struct_type; types::type_ptr struct_type;
std::unordered_map<std::string, value_ptr> fields; std::unordered_map<std::string, value_ptr> fields;
}; };
struct function_value struct function_value
{ {
std::vector<ast::function_definition::argument> arguments; struct argument
type::type_ptr return_type; {
std::string name;
types::type_ptr type;
};
std::vector<argument> arguments;
types::type_ptr return_type;
ast::statement_list_ptr statements; ast::statement_list_ptr statements;
}; };
@ -91,7 +97,7 @@ namespace pslang::interpreter
using value_impl::value_impl; 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); void print(std::ostream & out, value const & value);

View file

@ -1,5 +1,5 @@
#include <pslang/interpreter/context.hpp> #include <pslang/interpreter/context.hpp>
#include <pslang/type/print.hpp> #include <pslang/types/print.hpp>
namespace pslang::interpreter namespace pslang::interpreter
{ {
@ -20,7 +20,7 @@ namespace pslang::interpreter
out << variable.first << " = "; out << variable.first << " = ";
print(out, variable.second.value); print(out, variable.second.value);
out << " ("; out << " (";
type::print(out, type_of(variable.second.value)); types::print(out, type_of(variable.second.value));
out << ")\n"; out << ")\n";
} }
} }

View file

@ -2,7 +2,7 @@
#include <pslang/interpreter/exec.hpp> #include <pslang/interpreter/exec.hpp>
#include <pslang/interpreter/value.hpp> #include <pslang/interpreter/value.hpp>
#include <pslang/ast/expression.hpp> #include <pslang/ast/expression.hpp>
#include <pslang/type/print.hpp> #include <pslang/types/print.hpp>
#include <sstream> #include <sstream>
#include <optional> #include <optional>
@ -13,44 +13,36 @@ namespace pslang::interpreter
namespace 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; 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; 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<type::type>(resolve_type(context, *type.element_type)), type.size}; return types::array_type{std::make_unique<types::type>(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) for (auto const & argument : type.arguments)
result.arguments.push_back(std::make_unique<type::type>(resolve_type(context, *argument))); result.arguments.push_back(std::make_unique<types::type>(resolve_type(context, *argument)));
result.result = std::make_unique<type::type>(resolve_type(context, *type.result)); result.result = std::make_unique<types::type>(resolve_type(context, *type.result));
return 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) return types::named_type{type.name, type.level};
{
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");
} }
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); return std::visit([&](auto const & type){ return resolve_type_impl(context, type); }, type);
} }
@ -166,7 +158,7 @@ namespace pslang::interpreter
{ {
std::ostringstream os; std::ostringstream os;
os << "Cannot index into an array with an expression of type "; 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()); throw std::runtime_error(os.str());
} }
@ -223,7 +215,7 @@ namespace pslang::interpreter
os << "Cannot apply unary operator \""; os << "Cannot apply unary operator \"";
print(os, type); print(os, type);
os << "\" to a value of 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()); throw std::runtime_error(os.str());
} }
@ -254,7 +246,7 @@ namespace pslang::interpreter
os << "Cannot apply unary operator \""; os << "Cannot apply unary operator \"";
print(os, type); print(os, type);
os << "\" to a value of 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()); throw std::runtime_error(os.str());
} }
@ -370,9 +362,9 @@ namespace pslang::interpreter
os << "Cannot apply binary operator \""; os << "Cannot apply binary operator \"";
print(os, type); print(os, type);
os << "\" to values of type "; os << "\" to values of type ";
type::print(os, type_of(primitive_value(arg1))); types::print(os, type_of(primitive_value(arg1)));
os << " and "; os << " and ";
type::print(os, type_of(primitive_value(arg2))); types::print(os, type_of(primitive_value(arg2)));
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -383,9 +375,9 @@ namespace pslang::interpreter
os << "Cannot apply binary operator \""; os << "Cannot apply binary operator \"";
print(os, type); print(os, type);
os << "\" to values of type "; os << "\" to values of type ";
type::print(os, type_of(arg1)); types::print(os, type_of(arg1));
os << " and "; os << " and ";
type::print(os, type_of(arg2)); types::print(os, type_of(arg2));
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -404,15 +396,15 @@ namespace pslang::interpreter
auto type1 = type_of(arg1); auto type1 = type_of(arg1);
auto type2 = type_of(arg2); auto type2 = type_of(arg2);
if (!type::equal(type1, type2)) if (!types::equal(type1, type2))
{ {
std::ostringstream os; std::ostringstream os;
os << "Cannot apply binary operator \""; os << "Cannot apply binary operator \"";
print(os, binary_operation.type); print(os, binary_operation.type);
os << "\" to values of type "; os << "\" to values of type ";
type::print(os, type1); types::print(os, type1);
os << " and "; os << " and ";
type::print(os, type2); types::print(os, type2);
throw std::runtime_error(os.str()); 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"); 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; return value;
throw std::runtime_error("Cannot cast unit type to anything"); 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; return value;
throw std::runtime_error("Cannot cast array type to anything"); throw std::runtime_error("Cannot cast array type to anything");
} }
template <typename T> template <typename T>
value cast_impl(primitive_value_base<T> const & value, type::unit_type const &) value cast_impl(primitive_value_base<T> const & value, types::unit_type const &)
{ {
throw std::runtime_error("Cannot cast anything to unit type"); throw std::runtime_error("Cannot cast anything to unit type");
} }
template <typename T, typename H> template <typename T, typename H>
value cast_impl(primitive_value_base<T> const & value, type::primitive_type_base<H> const & type) value cast_impl(primitive_value_base<T> const & value, types::primitive_type_base<H> const & type)
{ {
if constexpr (std::is_same_v<T, H>) if constexpr (std::is_same_v<T, H>)
{ {
@ -458,50 +450,50 @@ namespace pslang::interpreter
std::ostringstream os; std::ostringstream os;
os << "Cannot cast value of type "; 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 "; os << " to type ";
type::print(os, type::primitive_type(type)); types::print(os, types::primitive_type(type));
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
template <typename T> template <typename T>
value cast_impl(primitive_value_base<T> const & value, type::primitive_type const & type) value cast_impl(primitive_value_base<T> const & value, types::primitive_type const & type)
{ {
return std::visit([&](auto const & type){ return cast_impl(value, type); }, type); return std::visit([&](auto const & type){ return cast_impl(value, type); }, type);
} }
template <typename T> template <typename T>
value cast_impl(primitive_value_base<T> const &, type::array_type const &) value cast_impl(primitive_value_base<T> const &, types::array_type const &)
{ {
throw std::runtime_error("Cannot cast anything to array type"); throw std::runtime_error("Cannot cast anything to array type");
} }
template <typename T> template <typename T>
value cast_impl(primitive_value_base<T> const &, type::function_type const &) value cast_impl(primitive_value_base<T> const &, types::function_type const &)
{ {
throw std::runtime_error("Cannot cast anything to function type"); throw std::runtime_error("Cannot cast anything to function type");
} }
template <typename T> template <typename T>
value cast_impl(primitive_value_base<T> const & value, type::type const & type) value cast_impl(primitive_value_base<T> const & value, types::type const & type)
{ {
return std::visit([&](auto const & type){ return cast_impl(value, type); }, 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); 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; return value;
throw std::runtime_error("Cannot cast struct type to anything"); 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"); 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) value eval_impl(context & context, ast::cast_operation const & cast_operation)
{ {
auto arg = eval(context, cast_operation.expression); 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) 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) for (std::size_t i = 0; i < args.size(); ++i)
{ {
auto actual_type = type_of(args[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; std::ostringstream os;
os << "Cannot create struct \"" << identifier->name << "\": field " << jt->second.fields[i].name << " expects type "; 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 "; os << " but actual type is ";
type::print(os, actual_type); types::print(os, actual_type);
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -551,7 +544,7 @@ namespace pslang::interpreter
} }
return struct_value{ return struct_value{
.struct_type = std::make_unique<type::type>(resolve_type(context, type::identifier{identifier->name})), .struct_type = std::make_unique<types::type>(types::named_type{.name = identifier->name, .level = identifier->level}),
.fields = std::move(fields), .fields = std::move(fields),
}; };
} }
@ -576,13 +569,13 @@ namespace pslang::interpreter
for (std::size_t i = 0; i < args.size(); ++i) for (std::size_t i = 0; i < args.size(); ++i)
{ {
auto actual_type = type_of(args[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; std::ostringstream os;
os << "Cannot call function: argument #" << (i + 1) << " expects type "; 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 "; os << " but actual type is ";
type::print(os, actual_type); types::print(os, actual_type);
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
} }
@ -598,13 +591,13 @@ namespace pslang::interpreter
exec(context, fvalue->statements); exec(context, fvalue->statements);
auto actual_return_type = type_of(context.scope_stack.back().return_value); 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; std::ostringstream os;
os << "Error returning from function: expected return type is "; 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 "; os << " but actual type is ";
type::print(os, actual_return_type); types::print(os, actual_return_type);
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -625,23 +618,23 @@ namespace pslang::interpreter
if (array.elements.empty()) if (array.elements.empty())
throw std::runtime_error("Internal error: array ast node cannot have zero elements"); 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<value_ptr> elements; std::vector<value_ptr> elements;
for (std::size_t i = 0; i < array.elements.size(); ++i) for (std::size_t i = 0; i < array.elements.size(); ++i)
{ {
auto element = std::make_unique<value>(eval(context, array.elements[i])); auto element = std::make_unique<value>(eval(context, array.elements[i]));
if (i == 0) if (i == 0)
element_type = std::make_unique<type::type>(type_of(*element)); element_type = std::make_unique<types::type>(type_of(*element));
else else
{ {
auto new_type = type_of(*element); auto new_type = type_of(*element);
if (!type::equal(*element_type, new_type)) if (!types::equal(*element_type, new_type))
{ {
std::ostringstream os; std::ostringstream os;
os << "Error forming array: inferred element type is "; os << "Error forming array: inferred element type is ";
type::print(os, *element_type); types::print(os, *element_type);
os << " but element #" << i << " type is "; os << " but element #" << i << " type is ";
type::print(os, new_type); types::print(os, new_type);
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
} }
@ -664,7 +657,7 @@ namespace pslang::interpreter
std::ostringstream os; std::ostringstream os;
os << "Cannot index into a non-array of type "; 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()); throw std::runtime_error(os.str());
} }
@ -678,14 +671,14 @@ namespace pslang::interpreter
std::ostringstream os; std::ostringstream os;
os << "Struct "; os << "Struct ";
type::print(os, type_of(object)); types::print(os, type_of(object));
os << " has no field named \"" << field_access.field_name << "\""; os << " has no field named \"" << field_access.field_name << "\"";
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
std::ostringstream os; std::ostringstream os;
os << "Value of type "; os << "Value of type ";
type::print(os, type_of(object)); types::print(os, type_of(object));
os << " is not a struct"; os << " is not a struct";
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -753,7 +746,7 @@ namespace pslang::interpreter
std::ostringstream os; std::ostringstream os;
os << "Cannot index into a non-array of type "; 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()); throw std::runtime_error(os.str());
} }
@ -767,14 +760,14 @@ namespace pslang::interpreter
std::ostringstream os; std::ostringstream os;
os << "Struct "; 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 << "\""; os << " has no field named \"" << field_access.field_name << "\"";
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
std::ostringstream os; std::ostringstream os;
os << "Value of type "; os << "Value of type ";
type::print(os, type_of(*object_ref)); types::print(os, type_of(*object_ref));
os << " is not a struct"; os << " is not a struct";
throw std::runtime_error(os.str()); 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); return resolve_type_impl(context, type);
} }

View file

@ -1,7 +1,7 @@
#include <pslang/interpreter/exec.hpp> #include <pslang/interpreter/exec.hpp>
#include <pslang/interpreter/eval.hpp> #include <pslang/interpreter/eval.hpp>
#include <pslang/ast/statement.hpp> #include <pslang/ast/statement.hpp>
#include <pslang/type/print.hpp> #include <pslang/types/print.hpp>
#include <stdexcept> #include <stdexcept>
#include <sstream> #include <sstream>
@ -43,13 +43,13 @@ namespace pslang::interpreter
auto ref = eval_ref(context, assignment.lhs); auto ref = eval_ref(context, assignment.lhs);
auto existing_type = type_of(*ref); auto existing_type = type_of(*ref);
if (!type::equal(existing_type, new_type)) if (!types::equal(existing_type, new_type))
{ {
std::ostringstream os; std::ostringstream os;
os << "Cannot assign a value of type "; os << "Cannot assign a value of type ";
type::print(os, new_type); types::print(os, new_type);
os << " to a variable of type "; os << " to a variable of type ";
type::print(os, existing_type); types::print(os, existing_type);
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -67,13 +67,13 @@ namespace pslang::interpreter
{ {
auto expected_type = resolve_type(context, *variable_declaration.type); auto expected_type = resolve_type(context, *variable_declaration.type);
auto actual_type = type_of(value); auto actual_type = type_of(value);
if (!type::equal(expected_type, actual_type)) if (!types::equal(expected_type, actual_type))
{ {
std::ostringstream os; std::ostringstream os;
os << "Cannot initialize a variable of type "; os << "Cannot initialize a variable of type ";
type::print(os, expected_type); types::print(os, expected_type);
os << " with an expression of type "; os << " with an expression of type ";
type::print(os, actual_type); types::print(os, actual_type);
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
} }
@ -105,11 +105,11 @@ namespace pslang::interpreter
{ {
auto value = eval(context, block.condition); auto value = eval(context, block.condition);
auto actual_type = type_of(value); 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; std::ostringstream os;
os << "Expected type bool, got type "; os << "Expected type bool, got type ";
type::print(os, actual_type); types::print(os, actual_type);
os << " in if block condition"; os << " in if block condition";
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -133,11 +133,11 @@ namespace pslang::interpreter
{ {
auto value = eval(context, while_block.condition); auto value = eval(context, while_block.condition);
auto actual_type = type_of(value); 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; std::ostringstream os;
os << "Expected type bool, got type "; os << "Expected type bool, got type ";
type::print(os, actual_type); types::print(os, actual_type);
os << " in while block condition"; os << " in while block condition";
throw std::runtime_error(os.str()); throw std::runtime_error(os.str());
} }
@ -162,8 +162,8 @@ namespace pslang::interpreter
function_value value; function_value value;
for (auto const & argument : function_definition.arguments) for (auto const & argument : function_definition.arguments)
value.arguments.push_back({.name = argument.name, .type = std::make_unique<type::type>(resolve_type(context, *argument.type))}); value.arguments.push_back({.name = argument.name, .type = std::make_unique<types::type>(resolve_type(context, *argument.type))});
value.return_type = std::make_unique<type::type>(resolve_type(context, *function_definition.return_type)); value.return_type = std::make_unique<types::type>(resolve_type(context, *function_definition.return_type));
value.statements = function_definition.statements; value.statements = function_definition.statements;
scope.variables[function_definition.name] = {.category = ast::value_category::constant, .value = std::move(value)}; 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({ result.fields.push_back({
.name = field.name, .name = field.name,
.type = std::make_unique<type::type>(resolve_type(context, *field.type)), .type = std::make_unique<types::type>(resolve_type(context, *field.type)),
}); });
} }
scope.structs[struct_definition.name] = std::move(result); scope.structs[struct_definition.name] = std::move(result);

View file

@ -1,5 +1,5 @@
#include <pslang/interpreter/value.hpp> #include <pslang/interpreter/value.hpp>
#include <pslang/type/print.hpp> #include <pslang/types/print.hpp>
#include <iomanip> #include <iomanip>
@ -9,42 +9,42 @@ namespace pslang::interpreter
namespace 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 <typename T> template <typename T>
type::type type_of_impl(primitive_value_base<T> const &) types::type type_of_impl(primitive_value_base<T> const &)
{ {
return type::primitive_type(type::primitive_type_base<T>{}); return types::primitive_type(types::primitive_type_base<T>{});
} }
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); 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; 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) for (auto const & argument : value.arguments)
result.arguments.push_back(argument.type); result.arguments.push_back(argument.type);
result.result = value.return_type; result.result = value.return_type;
return result; 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); 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); return type_of_impl(value);
} }

View file

@ -20,9 +20,8 @@
%code requires { %code requires {
#include <pslang/ast/statement.hpp>
#include <pslang/ast/location.hpp>
#include <pslang/parser/indented_statement.hpp> #include <pslang/parser/indented_statement.hpp>
#include <pslang/ast/statement.hpp>
namespace pslang::parser { namespace pslang::parser {
@ -149,13 +148,13 @@ template <typename T>
%type <std::vector<ast::function_definition::argument>> function_definition_argument_list %type <std::vector<ast::function_definition::argument>> function_definition_argument_list
%type <std::vector<ast::function_definition::argument>> nonempty_function_definition_argument_list %type <std::vector<ast::function_definition::argument>> nonempty_function_definition_argument_list
%type <ast::function_definition::argument> function_definition_single_argument %type <ast::function_definition::argument> function_definition_single_argument
%type <type::type_ptr> function_return_type %type <ast::type_ptr> function_return_type
%type <ast::variable_declaration> variable_declaration %type <ast::variable_declaration> variable_declaration
%type <ast::value_category> variable_keyword %type <ast::value_category> variable_keyword
%type <type::type> type_expression %type <ast::type> type_expression
%type <type::primitive_type> primitive_type %type <types::primitive_type> primitive_type
%type <std::vector<type::type_ptr>> function_paren_type_list %type <std::vector<ast::type_ptr>> function_paren_type_list
%type <std::vector<type::type_ptr>> two_or_more_type_list %type <std::vector<ast::type_ptr>> two_or_more_type_list
%type <ast::expression> expression %type <ast::expression> expression
%type <ast::expression> postfix_expression %type <ast::expression> postfix_expression
%type <ast::expression> base_expression %type <ast::expression> base_expression
@ -192,7 +191,7 @@ statement
| return expression { $$ = ast::return_statement{std::make_unique<ast::expression>($2), @$}; } | return expression { $$ = ast::return_statement{std::make_unique<ast::expression>($2), @$}; }
| return { $$ = ast::return_statement{nullptr, @$}; } | return { $$ = ast::return_statement{nullptr, @$}; }
| struct name colon { $$ = ast::struct_definition{$2, {}, @$}; } | struct name colon { $$ = ast::struct_definition{$2, {}, @$}; }
| name colon type_expression { $$ = ast::field_definition{$1, std::make_unique<type::type>($3), @$}; } | name colon type_expression { $$ = ast::field_definition{$1, std::make_unique<ast::type>($3), @$}; }
; ;
function_definition_argument_list function_definition_argument_list
@ -206,17 +205,17 @@ nonempty_function_definition_argument_list
; ;
function_definition_single_argument function_definition_single_argument
: name colon type_expression { $$ = ast::function_definition::argument{$1, std::make_unique<type::type>($3), @$}; } : name colon type_expression { $$ = ast::function_definition::argument{$1, std::make_unique<ast::type>($3), @$}; }
; ;
function_return_type function_return_type
: arrow type_expression { $$ = std::make_unique<type::type>($2); } : arrow type_expression { $$ = std::make_unique<ast::type>($2); }
| %empty { $$ = std::make_unique<type::type>(type::unit_type{}); } | %empty { $$ = std::make_unique<ast::type>(types::unit_type{}); }
; ;
variable_declaration variable_declaration
: variable_keyword name assignment expression { $$ = ast::variable_declaration{$1, $2, nullptr, std::make_unique<ast::expression>($4), @$}; } : variable_keyword name assignment expression { $$ = ast::variable_declaration{$1, $2, nullptr, std::make_unique<ast::expression>($4), @$}; }
| variable_keyword name colon type_expression assignment expression { $$ = ast::variable_declaration{$1, $2, std::make_unique<type::type>($4), std::make_unique<ast::expression>($6), @$}; } | variable_keyword name colon type_expression assignment expression { $$ = ast::variable_declaration{$1, $2, std::make_unique<ast::type>($4), std::make_unique<ast::expression>($6), @$}; }
; ;
variable_keyword variable_keyword
@ -226,37 +225,37 @@ variable_keyword
; ;
type_expression type_expression
: unit { $$ = type::type(type::unit_type{}); } : unit { $$ = types::unit_type{}; }
| primitive_type { $$ = type::type($1); } | primitive_type { $$ = ast::type($1); }
| name { $$ = type::identifier{$1}; } | name { $$ = ast::type_identifier{$1}; }
| type_expression lbracket lit_i32 rbracket { $$ = type::array_type{std::make_unique<type::type>($1), std::stoull($3)}; } | type_expression lbracket lit_i32 rbracket { $$ = ast::array_type{std::make_unique<ast::type>($1), std::stoull($3)}; }
| type_expression arrow type_expression { std::vector<type::type_ptr> args; args.push_back(std::make_unique<type::type>($1)); $$ = type::function_type{std::move(args), std::make_unique<type::type>($3)}; } | type_expression arrow type_expression { std::vector<ast::type_ptr> args; args.push_back(std::make_unique<ast::type>($1)); $$ = ast::function_type{std::move(args), std::make_unique<ast::type>($3)}; }
| lparen function_paren_type_list rparen arrow type_expression { $$ = type::function_type{$2, std::make_unique<type::type>($5)}; } | lparen function_paren_type_list rparen arrow type_expression { $$ = ast::function_type{$2, std::make_unique<ast::type>($5)}; }
| lparen type_expression rparen { $$ = $2; } | lparen type_expression rparen { $$ = $2; }
; ;
primitive_type primitive_type
: bool { $$ = type::bool_type{}; } : bool { $$ = types::bool_type{}; }
| i8 { $$ = type::i8_type{}; } | i8 { $$ = types::i8_type{}; }
| u8 { $$ = type::u8_type{}; } | u8 { $$ = types::u8_type{}; }
| i16 { $$ = type::i16_type{}; } | i16 { $$ = types::i16_type{}; }
| u16 { $$ = type::u16_type{}; } | u16 { $$ = types::u16_type{}; }
| i32 { $$ = type::i32_type{}; } | i32 { $$ = types::i32_type{}; }
| u32 { $$ = type::u32_type{}; } | u32 { $$ = types::u32_type{}; }
| i64 { $$ = type::i64_type{}; } | i64 { $$ = types::i64_type{}; }
| u64 { $$ = type::u64_type{}; } | u64 { $$ = types::u64_type{}; }
| f32 { $$ = type::f32_type{}; } | f32 { $$ = types::f32_type{}; }
| f64 { $$ = type::f64_type{}; } | f64 { $$ = types::f64_type{}; }
; ;
function_paren_type_list function_paren_type_list
: %empty { std::vector<type::type_ptr> tmp; $$ = std::move(tmp); } : %empty { std::vector<ast::type_ptr> tmp; $$ = std::move(tmp); }
| two_or_more_type_list { $$ = $1; } | two_or_more_type_list { $$ = $1; }
; ;
two_or_more_type_list two_or_more_type_list
: type_expression comma type_expression { std::vector<type::type_ptr> tmp; tmp.push_back(std::make_unique<type::type>($1)); tmp.push_back(std::make_unique<type::type>($3)); $$ = std::move(tmp); } : type_expression comma type_expression { std::vector<ast::type_ptr> tmp; tmp.push_back(std::make_unique<ast::type>($1)); tmp.push_back(std::make_unique<ast::type>($3)); $$ = std::move(tmp); }
| two_or_more_type_list comma type_expression { auto tmp = $1; tmp.push_back(std::make_unique<type::type>($3)); $$ = std::move(tmp); } | two_or_more_type_list comma type_expression { auto tmp = $1; tmp.push_back(std::make_unique<ast::type>($3)); $$ = std::move(tmp); }
; ;
expression expression
@ -269,7 +268,7 @@ expression
| expression greater expression { $$ = ast::binary_operation{ast::binary_operation_type::greater, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; } | expression greater expression { $$ = ast::binary_operation{ast::binary_operation_type::greater, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
| expression less_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::less_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; } | expression less_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::less_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
| expression greater_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::greater_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; } | expression greater_equals expression { $$ = ast::binary_operation{ast::binary_operation_type::greater_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
| expression as type_expression { $$ = ast::cast_operation{ std::make_unique<ast::expression>($1), std::make_unique<type::type>($3), @$ }; } | expression as type_expression { $$ = ast::cast_operation{ std::make_unique<ast::expression>($1), std::make_unique<ast::type>($3), @$ }; }
| minus expression %prec UMINUS { $$ = ast::unary_operation{ast::unary_operation_type::negation, std::make_unique<ast::expression>($2), @$ }; } | minus expression %prec UMINUS { $$ = ast::unary_operation{ast::unary_operation_type::negation, std::make_unique<ast::expression>($2), @$ }; }
| expression plus expression { $$ = ast::binary_operation{ast::binary_operation_type::addition, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; } | expression plus expression { $$ = ast::binary_operation{ast::binary_operation_type::addition, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
| expression minus expression { $$ = ast::binary_operation{ast::binary_operation_type::subtraction, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; } | expression minus expression { $$ = ast::binary_operation{ast::binary_operation_type::subtraction, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }

View file

@ -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")

View file

@ -1,29 +0,0 @@
#pragma once
#include <pslang/type/unit.hpp>
#include <pslang/type/primitive.hpp>
#include <pslang/type/array.hpp>
#include <pslang/type/function.hpp>
#include <pslang/type/identifier.hpp>
#include <pslang/type/type_fwd.hpp>
#include <variant>
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;
};
}

View file

@ -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")

View file

@ -1,10 +1,10 @@
#pragma once #pragma once
#include <pslang/type/type_fwd.hpp> #include <pslang/types/type_fwd.hpp>
#include <cstdint> #include <cstdint>
namespace pslang::type namespace pslang::types
{ {
struct array_type struct array_type

View file

@ -1,10 +1,10 @@
#pragma once #pragma once
#include <pslang/type/type_fwd.hpp> #include <pslang/types/type_fwd.hpp>
#include <vector> #include <vector>
namespace pslang::type namespace pslang::types
{ {
struct function_type struct function_type

View file

@ -2,16 +2,16 @@
#include <string> #include <string>
namespace pslang::type namespace pslang::types
{ {
struct identifier struct named_type
{ {
std::string name; 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); return (t1.level == t2.level) && (t1.name == t2.name);
} }

View file

@ -3,7 +3,7 @@
#include <variant> #include <variant>
#include <cstdint> #include <cstdint>
namespace pslang::type namespace pslang::types
{ {
template <typename T> template <typename T>

View file

@ -1,10 +1,10 @@
#pragma once #pragma once
#include <pslang/type/type_fwd.hpp> #include <pslang/types/type_fwd.hpp>
#include <iostream> #include <iostream>
namespace pslang::type namespace pslang::types
{ {
void print(std::ostream & out, type const & type); void print(std::ostream & out, type const & type);

View file

@ -0,0 +1,29 @@
#pragma once
#include <pslang/types/unit.hpp>
#include <pslang/types/primitive.hpp>
#include <pslang/types/array.hpp>
#include <pslang/types/function.hpp>
#include <pslang/types/named.hpp>
#include <pslang/types/type_fwd.hpp>
#include <variant>
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;
};
}

View file

@ -2,7 +2,7 @@
#include <memory> #include <memory>
namespace pslang::type namespace pslang::types
{ {
struct type; struct type;
@ -10,4 +10,5 @@ namespace pslang::type
using type_ptr = std::shared_ptr<type>; using type_ptr = std::shared_ptr<type>;
bool equal(type const & t1, type const & t2); bool equal(type const & t1, type const & t2);
} }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
namespace pslang::type namespace pslang::types
{ {
struct unit_type struct unit_type

View file

@ -1,7 +1,7 @@
#include <pslang/type/print.hpp> #include <pslang/types/print.hpp>
#include <pslang/type/type.hpp> #include <pslang/types/type.hpp>
namespace pslang::type namespace pslang::types
{ {
namespace namespace
@ -100,7 +100,7 @@ namespace pslang::type
print(out, *type.result); 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; out << type.name;
} }

View file

@ -1,6 +1,6 @@
#include <pslang/type/type.hpp> #include <pslang/types/type.hpp>
namespace pslang::type namespace pslang::types
{ {
bool equal(type const & t1, type const & t2) bool equal(type const & t1, type const & t2)