FE
0.15.0
A C++23 toolkit for writing compiler/interpreter frontends.
Toggle main menu visibility
Loading...
Searching...
No Matches
cast.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <cassert>
4
#include <concepts>
5
6
#include <format>
7
#include <utility>
8
9
#include <
fe/term.h
>
10
11
namespace
fe
{
12
13
template
<
class
T>
14
concept
Nodeable
=
requires
(T n) {
15
T::Node;
16
n.node();
17
};
18
19
/// Like Nodeable, but for a class that spans a *set* of node kinds instead of a single one.
20
/// Such a class declares `static constexpr bool isa_node(<node type>)` to decide membership.
21
/// This keeps RuntimeCast::isa from falling back to a `dynamic_cast` for abstract bases that merely group nodes.
22
template
<
class
T>
23
concept
NodeSetable
=
requires
(T n) {
24
{ T::isa_node(n.node()) } -> std::convertible_to<bool>;
25
};
26
27
/// Inherit from this class using [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern),
28
/// for some nice `dynamic_cast`-style wrappers.
29
template
<
class
B>
30
class
RuntimeCast
{
31
public
:
32
// clang-format off
33
/// `static_cast` with debug check.
34
template
<
class
T> T*
as
() { assert(
isa<T>
());
return
static_cast<
T*
>
(
this
); }
35
36
/// `dynamic_cast`.
37
/// If @p T isa fe::Nodeable, it will use `node()`, otherwise a `dynamic_cast`.
38
template
<
class
T>
39
T*
isa
() {
40
if
constexpr
(
Nodeable<T>
) {
41
return
static_cast<
B*
>
(
this
)->node() == T::Node ?
static_cast<
T*
>
(
this
) :
nullptr
;
42
}
else
if
constexpr
(
NodeSetable<T>
) {
43
return
T::isa_node(
static_cast<
B*
>
(
this
)->node()) ?
static_cast<
T*
>
(
this
) :
nullptr
;
44
}
else
{
45
return
dynamic_cast<
T*
>
(
static_cast<
B*
>
(
this
));
46
}
47
}
48
49
template
<
class
T>
const
T*
as
()
const
{
return
const_cast<
RuntimeCast
*
>
(
this
)->
template
as<T >
(); }
///< `const` version.
50
template
<
class
T>
const
T*
isa
()
const
{
return
const_cast<
RuntimeCast
*
>
(
this
)->
template
isa<T >
(); }
///< `const` version.
51
// clang-format on
52
53
/// Like as() but - instead of merely asserting via isa() in `Debug` builds - throws a `std::logic_error` with a
54
/// formatted message when the cast fails.
55
/// @p fmt / @p args describe what was expected: a plain string works, as does a fe::cite_string plus arguments.
56
/// If `B` is `std::formattable`, the offending object is appended to the message as a `` `citation` ``.
57
template
<
class
T,
class
... Args>
58
T*
expect
(
cite_string<Args...>
fmt, Args&&... args) {
59
if
(
auto
res =
isa<T>
())
return
res;
60
auto
what =
format_cite
(fmt, std::forward<Args>(args)...);
61
if
constexpr
(std::formattable<const B*, char>)
62
throwf
(
"expected {}, but got `{}`"
, what,
static_cast<
const
B*
>
(
this
));
63
else
64
throwf
(
"expected {}"
, what);
65
}
66
67
/// `const` version.
68
template
<
class
T,
class
... Args>
69
const
T*
expect
(
cite_string<Args...>
fmt, Args&&... args)
const
{
70
return
const_cast<
RuntimeCast
*
>
(
this
)->
template
expect<T>
(fmt, std::forward<Args>(args)...);
71
}
72
};
73
74
}
// namespace fe
fe::RuntimeCast
Inherit from this class using CRTP, for some nice dynamic_cast-style wrappers.
Definition
cast.h:30
fe::RuntimeCast::as
T * as()
static_cast with debug check.
Definition
cast.h:34
fe::RuntimeCast::isa
T * isa()
dynamic_cast.
Definition
cast.h:39
fe::RuntimeCast::expect
const T * expect(cite_string< Args... > fmt, Args &&... args) const
const version.
Definition
cast.h:69
fe::RuntimeCast::isa
const T * isa() const
const version.
Definition
cast.h:50
fe::RuntimeCast::as
const T * as() const
const version.
Definition
cast.h:49
fe::RuntimeCast::expect
T * expect(cite_string< Args... > fmt, Args &&... args)
Like as() but - instead of merely asserting via isa() in Debug builds - throws a std::logic_error wit...
Definition
cast.h:58
fe::NodeSetable
Like Nodeable, but for a class that spans a set of node kinds instead of a single one.
Definition
cast.h:23
fe::Nodeable
Definition
cast.h:14
fe::term::cite_string
std::format_string< detail::cite_arg_t< Args >... > cite_string
A std::format_string whose backticks delimit a `citation` while those of its arguments are data.
Definition
term.h:243
fe
Definition
algo.h:17
fe::throwf
void throwf(cite_string< Args... > fmt, Args &&... args)
<
Definition
term.h:280
fe::format_cite
Cited format_cite(cite_string< Args... > fmt, Args &&... args)
<
Definition
term.h:248
term.h
fe
cast.h
Generated by
1.18.0