15 #ifndef GTIRB_SYMBOL_H
16 #define GTIRB_SYMBOL_H
25 #include <type_traits>
36 template <
class T>
class ErrorOr;
44 template <
typename... Ts>
struct TypeList {};
47 template <
typename Callable,
typename Ty,
typename CommonRetTy>
48 auto visit_impl_help(Callable&& Visitor)
const
49 -> std::enable_if_t<std::is_void_v<CommonRetTy>,
bool> {
50 static_assert(std::is_invocable_v<Callable, Ty*>,
51 "Visitor must contain an overloaded function call operator "
52 "for each of the types in supported_types");
53 if (
Node*
const* Ptr = std::get_if<Node*>(&Payload)) {
54 if (Ty* Obj = dyn_cast_or_null<Ty>(*Ptr)) {
55 std::invoke(Visitor, Obj);
63 template <
typename Callable,
typename Ty,
typename CommonRetTy>
65 visit_impl_help(Callable&& Visitor,
66 std::enable_if_t<!std::is_void_v<CommonRetTy>,
67 std::optional<CommonRetTy>>& Ret)
const {
68 static_assert(std::is_invocable_v<Callable, Ty*>,
69 "Visitor must contain an overloaded function call operator "
70 "for each of the types in supported_types");
71 if (
Node*
const* Ptr = std::get_if<Node*>(&Payload)) {
72 if (Ty* Obj = dyn_cast_or_null<Ty>(*Ptr)) {
73 Ret = std::invoke(Visitor, Obj);
88 template <
typename AlwaysVoid,
typename Callable,
89 template <
typename...>
typename TypeList,
typename... Types>
90 struct common_return_type_impl : std::false_type {};
92 template <
typename Callable,
template <
typename...>
typename TypeList,
94 struct common_return_type_impl<
96 std::common_type_t<std::invoke_result_t<Callable, Types*>...>>,
97 Callable, TypeList, Types...> : std::true_type {
98 using type = std::common_type_t<std::invoke_result_t<Callable, Types*>...>;
101 template <
typename Callable,
template <
typename...>
typename TypeList,
103 using common_return_type_t =
104 typename common_return_type_impl<void, Callable, TypeList,
107 template <
typename Callable,
template <
typename...>
typename TypeList,
109 static constexpr
bool common_return_type_v =
110 common_return_type_impl<void, Callable, TypeList, Types...>::value;
118 template <
typename Callable,
template <
typename...>
typename TypeList,
120 auto visit_impl(Callable&& Visitor, TypeList<Types...>)
const
122 !std::is_void_v<common_return_type_t<Callable, TypeList, Types...>>,
123 std::optional<common_return_type_t<Callable, TypeList, Types...>>> {
127 static_assert(common_return_type_v<Callable, TypeList, Types...>,
128 "incompatible return types for the Callable object");
138 std::optional<common_return_type_t<Callable, TypeList, Types...>> Res;
140 visit_impl_help<Callable, Types, typename decltype(Res)::value_type>(
141 std::forward<Callable>(Visitor), Res));
147 template <
typename Callable,
template <
typename...>
typename TypeList,
149 auto visit_impl(Callable&& Visitor, TypeList<Types...>)
const
151 std::is_void_v<common_return_type_t<Callable, TypeList, Types...>>,
156 visit_impl_help<Callable, Types, void>(std::forward<Callable>(Visitor)));
161 template <
typename NodeTy,
template <
typename...>
typename TypeList,
163 static constexpr
bool is_supported_type_impl(TypeList<Types...>) {
164 return (... || std::is_same_v<NodeTy, Types>);
171 return is_supported_type_impl<NodeTy>(
172 std::decay_t<supported_referent_types>{});
213 template <
typename Callable>
auto visit(Callable&& Visitor)
const {
214 return visit_impl(std::forward<Callable>(Visitor),
215 std::decay_t<supported_referent_types>{});
232 bool AtEnd =
false) {
246 bool AtEnd =
false) {
259 template <
typename NodeTy>
261 bool AtEnd =
false) {
262 static_assert(is_supported_type<NodeTy>(),
"unsupported referent type");
274 std::optional<Addr> getAddress()
const;
279 const std::string&
getName()
const {
return Name; }
288 if (
Node*
const* Ptr = std::get_if<Node*>(&Payload))
289 return dyn_cast_or_null<NodeTy>(*Ptr);
300 if (
Node*
const* Ptr = std::get_if<Node*>(&Payload))
301 return dyn_cast_or_null<NodeTy>(*Ptr);
308 bool hasReferent()
const {
return std::holds_alternative<Node*>(Payload); }
311 void setName(
const std::string& N);
318 template <
typename NodeTy>
319 std::enable_if_t<is_supported_type<NodeTy>()>
setReferent(NodeTy* N) {
320 setReferentFromNode(N);
324 void setAddress(
Addr A);
339 static bool classof(
const Node* N) {
return N->getKind() == Kind::Symbol; }
343 Symbol(Context& C) : Node(C, Kind::Symbol) {}
344 Symbol(Context& C,
const std::string& N,
bool AE)
345 : Node(C, Kind::Symbol), Name(N), AtEnd(AE) {}
346 Symbol(Context& C,
const std::string& N,
bool AE,
const UUID& U)
347 : Node(C, Kind::Symbol, U), Name(N), AtEnd(AE) {}
348 Symbol(Context& C, Addr X,
const std::string& N,
bool AE)
349 : Node(C, Kind::Symbol), Payload(X), Name(N), AtEnd(AE) {}
350 template <
typename NodeTy>
351 Symbol(Context& C, NodeTy* R,
const std::string& N,
bool AE)
352 : Node(C, Kind::Symbol), Payload(R), Name(N), AtEnd(AE) {
354 Payload = std::monostate{};
358 static Symbol* Create(Context& C,
const std::string& Name,
bool AtEnd,
360 return C.Create<Symbol>(C, Name, AtEnd, U);
363 void setParent(Module* M, SymbolObserver* O) {
368 void setReferentFromNode(Node* N);
371 using MessageType = proto::Symbol;
378 void toProtobuf(MessageType* Message)
const;
386 static ErrorOr<Symbol*> fromProtobuf(Context& C,
const MessageType& Message);
389 void save(std::ostream& Out)
const;
392 static Symbol* load(Context& C, std::istream& In);
394 Module* Parent{
nullptr};
395 SymbolObserver* Observer{
nullptr};
396 std::variant<std::monostate, Addr, Node*> Payload;
403 template <
typename T>
friend typename T::MessageType toProtobuf(
const T&);
404 friend class SerializationTestHarness;
426 const std::string& NewName) = 0;
439 std::variant<std::monostate, Addr, Node*> OldReferent,
440 std::variant<std::monostate, Addr, Node*> NewReferent) = 0;
445 std::string OldName(N);
446 std::swap(Name, OldName);
450 "recovering from rejected name change is unsupported");
458 std::variant<std::monostate, Addr, Node*> OldValue = Payload;
463 "recovering from rejected address change is unsupported");
469 inline void Symbol::setReferentFromNode(
Node* N) {
470 std::variant<std::monostate, Addr, Node*> OldValue = Payload;
474 Payload = std::monostate{};
480 "recovering from rejected referent change is unsupported");
486 #endif // GTIRB_SYMBOL_H