Introduce dedicated type tree & AST tree visitors and use them in pretty-printing
This commit is contained in:
parent
4175a86ae3
commit
709c7a7a0a
9 changed files with 790 additions and 398 deletions
|
|
@ -109,7 +109,7 @@ int main(int argc, char ** argv)
|
||||||
for (std::size_t i = 0; i < filenames.size(); ++i)
|
for (std::size_t i = 0; i < filenames.size(); ++i)
|
||||||
{
|
{
|
||||||
std::cout << "Input file " << filenames[i] << " AST dump:\n\n";
|
std::cout << "Input file " << filenames[i] << " AST dump:\n\n";
|
||||||
ast::print(std::cout, parsed[i]);
|
ast::print(std::cout, *parsed[i]);
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
std::cout << std::flush;
|
std::cout << std::flush;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,2 @@
|
||||||
* Mutually recursive functions
|
* Mutually recursive functions
|
||||||
* Refactor all tree visitors to prevent infinite recursion (maybe add decicated tree traversal functions & visitors?)
|
* Type identifier location
|
||||||
* Type identifier location + move types to ast library / split type values and type ast nodes
|
|
||||||
|
|
|
||||||
85
libs/ast/include/pslang/ast/expression_visitor.hpp
Normal file
85
libs/ast/include/pslang/ast/expression_visitor.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pslang/ast/expression.hpp>
|
||||||
|
|
||||||
|
namespace pslang::ast
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct const_expression_visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Expression>
|
||||||
|
void operator()(Expression const & expression)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, const_expression_visitor_helper &, Expression const &>)
|
||||||
|
{
|
||||||
|
visitor(*this, expression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(literal const & expression)
|
||||||
|
{
|
||||||
|
std::visit(*this, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(expression const & expression)
|
||||||
|
{
|
||||||
|
std::visit(*this, expression);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct expression_visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Expression>
|
||||||
|
void operator()(Expression & expression)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, expression_visitor_helper &, Expression &>)
|
||||||
|
{
|
||||||
|
visitor(*this, expression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(literal & expression)
|
||||||
|
{
|
||||||
|
std::visit(*this, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(expression & expression)
|
||||||
|
{
|
||||||
|
std::visit(*this, expression);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, expression const & expression)
|
||||||
|
{
|
||||||
|
detail::const_expression_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, expression & expression)
|
||||||
|
{
|
||||||
|
detail::expression_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <pslang/ast/statement.hpp>
|
#include <pslang/ast/type_fwd.hpp>
|
||||||
|
#include <pslang/ast/expression_fwd.hpp>
|
||||||
|
#include <pslang/ast/statement_fwd.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
@ -13,8 +15,9 @@ namespace pslang::ast
|
||||||
std::size_t indent_level = 0;
|
std::size_t indent_level = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void print(std::ostream & out, expression_ptr const & node, print_options const & options = {});
|
void print(std::ostream & out, type const & node);
|
||||||
void print(std::ostream & out, statement_ptr const & node, print_options const & options = {});
|
void print(std::ostream & out, expression const & node, print_options const & options = {});
|
||||||
void print(std::ostream & out, statement_list_ptr const & node, print_options const & options = {});
|
void print(std::ostream & out, statement const & node, print_options const & options = {});
|
||||||
|
void print(std::ostream & out, statement_list const & node, print_options const & options = {});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
89
libs/ast/include/pslang/ast/statement_visitor.hpp
Normal file
89
libs/ast/include/pslang/ast/statement_visitor.hpp
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pslang/ast/statement.hpp>
|
||||||
|
|
||||||
|
namespace pslang::ast
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct const_statement_visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Statement>
|
||||||
|
void operator()(Statement const & statement)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, const_statement_visitor_helper &, Statement const &>)
|
||||||
|
{
|
||||||
|
visitor(*this, statement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(statement const & statement)
|
||||||
|
{
|
||||||
|
std::visit(*this, statement);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct statement_visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Statement>
|
||||||
|
void operator()(Statement & statement)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, statement_visitor_helper &, Statement &>)
|
||||||
|
{
|
||||||
|
visitor(*this, statement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(statement & statement)
|
||||||
|
{
|
||||||
|
std::visit(*this, statement);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, statement const & statement)
|
||||||
|
{
|
||||||
|
detail::const_statement_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, statement & statement)
|
||||||
|
{
|
||||||
|
detail::statement_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, statement_list const & statement_list)
|
||||||
|
{
|
||||||
|
detail::const_statement_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(statement_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, statement_list & statement_list)
|
||||||
|
{
|
||||||
|
detail::statement_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(statement_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
85
libs/ast/include/pslang/ast/type_visitor.hpp
Normal file
85
libs/ast/include/pslang/ast/type_visitor.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pslang/ast/type.hpp>
|
||||||
|
|
||||||
|
namespace pslang::ast
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct const_type_visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
void operator()(Type const & type)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, const_type_visitor_helper &, Type const &>)
|
||||||
|
{
|
||||||
|
visitor(*this, type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(types::primitive_type const & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(ast::type const & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct type_visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
void operator()(Type & type)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, type_visitor_helper &, Type &>)
|
||||||
|
{
|
||||||
|
visitor(*this, type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(types::primitive_type & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(ast::type & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, type const & type)
|
||||||
|
{
|
||||||
|
detail::const_type_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, type & type)
|
||||||
|
{
|
||||||
|
detail::type_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
#include <pslang/ast/print.hpp>
|
#include <pslang/ast/print.hpp>
|
||||||
|
#include <pslang/ast/statement.hpp>
|
||||||
|
#include <pslang/ast/type_visitor.hpp>
|
||||||
|
#include <pslang/ast/expression_visitor.hpp>
|
||||||
|
#include <pslang/ast/statement_visitor.hpp>
|
||||||
#include <pslang/types/print.hpp>
|
#include <pslang/types/print.hpp>
|
||||||
#include <pslang/types/type.hpp>
|
#include <pslang/types/type.hpp>
|
||||||
|
|
||||||
|
|
@ -10,7 +14,7 @@ namespace pslang::ast
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
print_options child(print_options options)
|
print_options as_child(print_options options)
|
||||||
{
|
{
|
||||||
options.indent_level += 1;
|
options.indent_level += 1;
|
||||||
return options;
|
return options;
|
||||||
|
|
@ -22,332 +26,377 @@ namespace pslang::ast
|
||||||
out << options.indent_string;
|
out << options.indent_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(std::ostream & out, type const & type, print_options const & options);
|
struct type_print_visitor
|
||||||
|
|
||||||
void print_impl(std::ostream & out, types::unit_type const &, print_options const &)
|
|
||||||
{
|
{
|
||||||
out << "unit";
|
std::ostream & out;
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, types::primitive_type const & type, print_options const &)
|
void operator()(types::unit_type 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 << "unit";
|
||||||
out << " -> ";
|
|
||||||
print(out, *type.result, options);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out << '(';
|
template <typename T>
|
||||||
bool first = true;
|
void operator()(types::primitive_type_base<T> const & type)
|
||||||
for (auto const & argument : type.arguments)
|
|
||||||
{
|
{
|
||||||
if (!first) out << ", ";
|
types::print(out, types::primitive_type{type});
|
||||||
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)
|
template <typename Self>
|
||||||
{
|
void operator()(Self & self, array_type const & type)
|
||||||
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);
|
|
||||||
out << "bool literal { value = " << (node.value ? "true" : "false") << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i8_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "i8 literal { value = " << (std::int32_t)node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u8_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "u8 literal { value = " << (std::uint32_t)node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i16_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "i16 literal { value = " << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u16_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "u16 literal { value = " << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i32_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "i32 literal { value = " << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u32_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "u32 literal { value = " << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i64_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "i64 literal { value = " << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u64_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "u64 literal { value = " << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, f32_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "f32 literal { value = " << std::setprecision(7) << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, f64_literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "f64 literal { value = " << std::setprecision(15) << node.value << " }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, literal const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
std::visit([&](auto const & value){ print_impl(out, value, options); }, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, identifier const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "identifier { name = \"" << node.name << "\" }\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, unary_operation const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << node.type << '\n';
|
|
||||||
print(out, node.arg1, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, binary_operation const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << node.type << '\n';
|
|
||||||
print(out, node.arg1, child(options));
|
|
||||||
print(out, node.arg2, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, cast_operation const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "cast as ";
|
|
||||||
print(out, *node.type, options);
|
|
||||||
out << '\n';
|
|
||||||
print(out, node.expression, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, function_call const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "call\n";
|
|
||||||
print(out, node.function, child(options));
|
|
||||||
for (auto const & argument : node.arguments)
|
|
||||||
print(out, argument, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, array const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "array\n";
|
|
||||||
for (auto const & element : node.elements)
|
|
||||||
print(out, element, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, array_access const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "array access\n";
|
|
||||||
print(out, node.array, child(options));
|
|
||||||
print(out, node.index, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, field_access const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "field access { name = \"" << node.field_name << "\" }\n";
|
|
||||||
print(out, node.object, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, expression_ptr const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
std::visit([&](auto const & value){ print_impl(out, value, options); }, *node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, assignment const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "assignment\n";
|
|
||||||
print(out, node.lhs, child(options));
|
|
||||||
print(out, node.rhs, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, variable_declaration const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "variable declaration { category = " << node.category << ", name = \"" << node.name << "\"";
|
|
||||||
if (node.type)
|
|
||||||
{
|
{
|
||||||
out << ", type = ";
|
self(*type.element_type);
|
||||||
print(out, *node.type, options);
|
out << "[" << type.size << "]";
|
||||||
}
|
}
|
||||||
out << " }\n";
|
|
||||||
print(out, node.initializer, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, if_block const & node, print_options const & options)
|
template <typename Self>
|
||||||
{
|
void operator()(Self & self, function_type const & type)
|
||||||
put_indent(out, options);
|
|
||||||
out << "if\n";
|
|
||||||
print(out, node.condition, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, else_block const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "else\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, else_if_block const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "else if\n";
|
|
||||||
print(out, node.condition, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, if_chain const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "if chain\n";
|
|
||||||
for (auto const & block : node.blocks)
|
|
||||||
{
|
{
|
||||||
put_indent(out, child(options));
|
if (type.arguments.size() == 1)
|
||||||
out << "condition\n";
|
|
||||||
if (block.condition)
|
|
||||||
print(out, block.condition, child(child(options)));
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
put_indent(out, child(child(options)));
|
self(*type.arguments.front());
|
||||||
out << "(none)\n";
|
out << " -> ";
|
||||||
|
self(*type.result);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
put_indent(out, child(options));
|
out << '(';
|
||||||
out << "body\n";
|
bool first = true;
|
||||||
print(out, block.statements, child(child(options)));
|
for (auto const & argument : type.arguments)
|
||||||
|
{
|
||||||
|
if (!first) out << ", ";
|
||||||
|
first = false;
|
||||||
|
self(*argument);
|
||||||
|
}
|
||||||
|
out << ") -> ";
|
||||||
|
self(*type.result);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, while_block const & node, print_options const & options)
|
void operator()(type_identifier const & type)
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "while\n";
|
|
||||||
print(out, node.condition, child(options));
|
|
||||||
print(out, node.statements, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, function_definition const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "function { name = \"" << node.name << "\", return type = ";
|
|
||||||
print(out, *node.return_type, options);
|
|
||||||
out << " }\n";
|
|
||||||
for (auto const & arg : node.arguments)
|
|
||||||
{
|
{
|
||||||
put_indent(out, child(options));
|
out << type.name;
|
||||||
out << "argument { name = \"" << arg.name << "\", type = ";
|
}
|
||||||
print(out, *arg.type, options);
|
};
|
||||||
|
|
||||||
|
struct expression_print_visitor
|
||||||
|
{
|
||||||
|
std::ostream & out;
|
||||||
|
print_options options;
|
||||||
|
|
||||||
|
template <typename Self, typename Node>
|
||||||
|
void child(Self & self, Node const & node)
|
||||||
|
{
|
||||||
|
++options.indent_level;
|
||||||
|
self(node);
|
||||||
|
--options.indent_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(bool_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "bool literal { value = " << (node.value ? "true" : "false") << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(i8_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "i8 literal { value = " << (std::int32_t)node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(u8_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "u8 literal { value = " << (std::uint32_t)node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(i16_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "i16 literal { value = " << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(u16_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "u16 literal { value = " << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(i32_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "i32 literal { value = " << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(u32_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "u32 literal { value = " << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(i64_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "i64 literal { value = " << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(u64_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "u64 literal { value = " << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(f32_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "f32 literal { value = " << std::setprecision(7) << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(f64_literal const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "f64 literal { value = " << std::setprecision(15) << node.value << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(identifier const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "identifier { name = \"" << node.name << "\" }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, unary_operation const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << node.type << '\n';
|
||||||
|
child(self, *node.arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, binary_operation const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << node.type << '\n';
|
||||||
|
child(self, *node.arg1);
|
||||||
|
child(self, *node.arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, cast_operation const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "cast as ";
|
||||||
|
print(out, *node.type);
|
||||||
|
out << '\n';
|
||||||
|
child(self, *node.expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, function_call const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "call\n";
|
||||||
|
child(self, *node.function);
|
||||||
|
for (auto const & argument : node.arguments)
|
||||||
|
child(self, *argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, array const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "array\n";
|
||||||
|
for (auto const & element : node.elements)
|
||||||
|
child(self, *element);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, array_access const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "array access\n";
|
||||||
|
child(self, *node.array);
|
||||||
|
child(self, *node.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, field_access const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "field access { name = \"" << node.field_name << "\" }\n";
|
||||||
|
child(self, *node.object);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct statement_print_visitor
|
||||||
|
{
|
||||||
|
std::ostream & out;
|
||||||
|
print_options options;
|
||||||
|
|
||||||
|
template <typename Self, typename Node>
|
||||||
|
void child(Self & self, Node const & node)
|
||||||
|
{
|
||||||
|
++options.indent_level;
|
||||||
|
self(node);
|
||||||
|
--options.indent_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(expression_ptr const & node)
|
||||||
|
{
|
||||||
|
print(out, *node, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, assignment const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "assignment\n";
|
||||||
|
child(self, node.lhs);
|
||||||
|
child(self, node.rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, variable_declaration const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "variable declaration { category = " << node.category << ", name = \"" << node.name << "\"";
|
||||||
|
if (node.type)
|
||||||
|
{
|
||||||
|
out << ", type = ";
|
||||||
|
print(out, *node.type);
|
||||||
|
}
|
||||||
|
out << " }\n";
|
||||||
|
child(self, node.initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, if_block const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "if\n";
|
||||||
|
child(self, node.condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(else_block const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "else\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, else_if_block const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "else if\n";
|
||||||
|
child(self, node.condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, if_chain const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "if chain\n";
|
||||||
|
++options.indent_level;
|
||||||
|
for (auto const & block : node.blocks)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "condition\n";
|
||||||
|
if (block.condition)
|
||||||
|
child(self, block.condition);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
put_indent(out, as_child(options));
|
||||||
|
out << "(none)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "body\n";
|
||||||
|
child(self, *block.statements);
|
||||||
|
}
|
||||||
|
--options.indent_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, while_block const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "while\n";
|
||||||
|
child(self, node.condition);
|
||||||
|
child(self, *node.statements);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, function_definition const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "function { name = \"" << node.name << "\", return type = ";
|
||||||
|
print(out, *node.return_type);
|
||||||
|
out << " }\n";
|
||||||
|
++options.indent_level;
|
||||||
|
for (auto const & arg : node.arguments)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "argument { name = \"" << arg.name << "\", type = ";
|
||||||
|
print(out, *arg.type);
|
||||||
|
out << " }\n";
|
||||||
|
}
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "body\n";
|
||||||
|
child(self, *node.statements);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, return_statement const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "return\n";
|
||||||
|
if (node.value)
|
||||||
|
child(self, node.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(field_definition const & node)
|
||||||
|
{
|
||||||
|
put_indent(out, options);
|
||||||
|
out << "field { name = \"" << node.name << "\", type = ";
|
||||||
|
print(out, *node.type);
|
||||||
out << " }\n";
|
out << " }\n";
|
||||||
}
|
}
|
||||||
put_indent(out, child(options));
|
|
||||||
out << "body\n";
|
|
||||||
print(out, node.statements, child(child(options)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, return_statement const & node, print_options const & options)
|
template <typename Self>
|
||||||
{
|
void operator()(Self & self, struct_definition const & node)
|
||||||
put_indent(out, options);
|
{
|
||||||
out << "return\n";
|
put_indent(out, options);
|
||||||
if (node.value)
|
out << "struct { name = \"" << node.name << "\" }\n";
|
||||||
print(out, node.value, child(options));
|
for (auto const & field : node.fields)
|
||||||
}
|
child(self, field);
|
||||||
|
}
|
||||||
|
|
||||||
void print_impl(std::ostream & out, field_definition const & node, print_options const & options)
|
template <typename Self>
|
||||||
{
|
void operator()(Self & self, statement_list const & node)
|
||||||
put_indent(out, options);
|
{
|
||||||
out << "field { name = \"" << node.name << "\", type = ";
|
for (auto const & statement : node.statements)
|
||||||
print(out, *node.type, options);
|
self(*statement);
|
||||||
out << " }\n";
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
void print_impl(std::ostream & out, struct_definition const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
put_indent(out, options);
|
|
||||||
out << "struct { name = \"" << node.name << "\" }\n";
|
|
||||||
for (auto const & field : node.fields)
|
|
||||||
print_impl(out, field, child(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, statement_ptr const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
std::visit([&](auto const & value){ print_impl(out, value, options); }, *node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, statement_list_ptr const & node, print_options const & options)
|
|
||||||
{
|
|
||||||
for (auto const & statement : node->statements)
|
|
||||||
print(out, statement, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(std::ostream & out, expression_ptr const & node, print_options const & options)
|
void print(std::ostream & out, type const & node)
|
||||||
{
|
{
|
||||||
print_impl(out, node, options);
|
apply(type_print_visitor{out}, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(std::ostream & out, statement_ptr const & node, print_options const & options)
|
void print(std::ostream & out, expression const & node, print_options const & options)
|
||||||
{
|
{
|
||||||
print_impl(out, node, options);
|
apply(expression_print_visitor{out, options}, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(std::ostream & out, statement_list_ptr const & node, print_options const & options)
|
void print(std::ostream & out, statement const & node, print_options const & options)
|
||||||
{
|
{
|
||||||
print_impl(out, node, options);
|
apply(statement_print_visitor{out, options}, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print(std::ostream & out, statement_list const & node, print_options const & options)
|
||||||
|
{
|
||||||
|
apply(statement_print_visitor{out, options}, node);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
85
libs/types/include/pslang/types/type_visitor.hpp
Normal file
85
libs/types/include/pslang/types/type_visitor.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pslang/types/type.hpp>
|
||||||
|
|
||||||
|
namespace pslang::types
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct const_visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
void operator()(Type const & type)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, const_visitor_helper &, Type const &>)
|
||||||
|
{
|
||||||
|
visitor(*this, type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(types::primitive_type const & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(types::type const & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct visitor_helper
|
||||||
|
{
|
||||||
|
Visitor & visitor;
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
void operator()(Type & type)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_invocable_v<Visitor, visitor_helper &, Type &>)
|
||||||
|
{
|
||||||
|
visitor(*this, type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visitor(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(types::primitive_type & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(types::type & type)
|
||||||
|
{
|
||||||
|
std::visit(*this, type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, type const & type)
|
||||||
|
{
|
||||||
|
detail::const_visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
void apply(Visitor && visitor, type & type)
|
||||||
|
{
|
||||||
|
detail::visitor_helper<Visitor> helper{visitor};
|
||||||
|
helper(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include <pslang/types/print.hpp>
|
#include <pslang/types/print.hpp>
|
||||||
#include <pslang/types/type.hpp>
|
#include <pslang/types/type_visitor.hpp>
|
||||||
|
|
||||||
namespace pslang::types
|
namespace pslang::types
|
||||||
{
|
{
|
||||||
|
|
@ -7,114 +7,111 @@ namespace pslang::types
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
void print_impl(std::ostream & out, unit_type const & type)
|
struct print_visitor
|
||||||
{
|
{
|
||||||
out << "unit";
|
std::ostream & out;
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, bool_type const &)
|
void operator()(unit_type const & type)
|
||||||
{
|
|
||||||
out << "bool";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i8_type const &)
|
|
||||||
{
|
|
||||||
out << "i8";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u8_type const &)
|
|
||||||
{
|
|
||||||
out << "u8";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i16_type const &)
|
|
||||||
{
|
|
||||||
out << "i16";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u16_type const &)
|
|
||||||
{
|
|
||||||
out << "u16";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i32_type const &)
|
|
||||||
{
|
|
||||||
out << "i32";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u32_type const &)
|
|
||||||
{
|
|
||||||
out << "u32";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, i64_type const &)
|
|
||||||
{
|
|
||||||
out << "i64";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, u64_type const &)
|
|
||||||
{
|
|
||||||
out << "u64";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, f32_type const &)
|
|
||||||
{
|
|
||||||
out << "f32";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, f64_type const &)
|
|
||||||
{
|
|
||||||
out << "f64";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, primitive_type const & type)
|
|
||||||
{
|
|
||||||
std::visit([&](auto const & value){ print_impl(out, value); }, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, array_type const & type)
|
|
||||||
{
|
|
||||||
print(out, *type.element_type);
|
|
||||||
out << "[" << type.size << "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, function_type const & type)
|
|
||||||
{
|
|
||||||
if (type.arguments.size() == 1)
|
|
||||||
{
|
{
|
||||||
print(out, *type.arguments.front());
|
out << "unit";
|
||||||
out << " -> ";
|
|
||||||
print(out, *type.result);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out << '(';
|
void operator()(bool_type const &)
|
||||||
bool first = true;
|
|
||||||
for (auto const & argument : type.arguments)
|
|
||||||
{
|
{
|
||||||
if (!first) out << ", ";
|
out << "bool";
|
||||||
first = false;
|
|
||||||
print(out, *argument);
|
|
||||||
}
|
}
|
||||||
out << ") -> ";
|
|
||||||
print(out, *type.result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_impl(std::ostream & out, named_type const & type)
|
void operator()(i8_type const &)
|
||||||
{
|
{
|
||||||
out << type.name;
|
out << "i8";
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_impl(std::ostream & out, type const & type)
|
void operator()(u8_type const &)
|
||||||
{
|
{
|
||||||
std::visit([&](auto const & value){ print_impl(out, value); }, type);
|
out << "u8";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()(i16_type const &)
|
||||||
|
{
|
||||||
|
out << "i16";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(u16_type const &)
|
||||||
|
{
|
||||||
|
out << "u16";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(i32_type const &)
|
||||||
|
{
|
||||||
|
out << "i32";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(u32_type const &)
|
||||||
|
{
|
||||||
|
out << "u32";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(i64_type const &)
|
||||||
|
{
|
||||||
|
out << "i64";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(u64_type const &)
|
||||||
|
{
|
||||||
|
out << "u64";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(f32_type const &)
|
||||||
|
{
|
||||||
|
out << "f32";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(f64_type const &)
|
||||||
|
{
|
||||||
|
out << "f64";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, array_type const & type)
|
||||||
|
{
|
||||||
|
self(*type.element_type);
|
||||||
|
out << "[" << type.size << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
void operator()(Self & self, function_type const & type)
|
||||||
|
{
|
||||||
|
if (type.arguments.size() == 1)
|
||||||
|
{
|
||||||
|
self(*type.arguments.front());
|
||||||
|
out << " -> ";
|
||||||
|
self(*type.result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << '(';
|
||||||
|
bool first = true;
|
||||||
|
for (auto const & argument : type.arguments)
|
||||||
|
{
|
||||||
|
if (!first) out << ", ";
|
||||||
|
first = false;
|
||||||
|
self(*argument);
|
||||||
|
}
|
||||||
|
out << ") -> ";
|
||||||
|
self(*type.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(named_type const & type)
|
||||||
|
{
|
||||||
|
out << type.name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(std::ostream & out, type const & type)
|
void print(std::ostream & out, type const & type)
|
||||||
{
|
{
|
||||||
print_impl(out, type);
|
apply(print_visitor{out}, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue