MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
union.h
Go to the documentation of this file.
1#pragma once
2
3#include <span>
4
5#include "mim/def.h"
6
7namespace mim {
8
9/// Common base for TExt%remum.
10class Ext : public Def {
11protected:
12 Ext(Node node, const Def* type)
13 : Def(node, type, Defs{}, 0) {}
14
15public:
16 /// Ext groups Top and Bot; see fe::NodeSetable.
17 static constexpr bool isa_node(mim::Node n) noexcept { return n == mim::Node::Top || n == mim::Node::Bot; }
18};
19
20/// Ext%remum. Either Top (@p Up) or Bot%tom.
21template<bool Up>
22class TExt : public Ext, public Setters<TExt<Up>> {
23private:
24 TExt(const Def* type)
25 : Ext(Node, type) {}
26
27public:
28 using Setters<TExt<Up>>::set;
29
30 static constexpr auto Node = Up ? mim::Node::Top : mim::Node::Bot;
31 static constexpr size_t Num_Ops = 0;
32
33private:
34 friend class World;
35};
36
37/// @name Lattice
38///@{
41/// @}
42
43/// A union type whose ops are sorted and deduplicated: `T ∪ T` is `T`.
44class Join : public Def, public Setters<Join> {
45private:
46 Join(const Def* type, Defs ops)
47 : Def(Node, type, ops, 0) {}
48
49public:
50 using Setters<Join>::set;
51
52 static constexpr auto Node = mim::Node::Join;
53 static constexpr size_t Num_Ops = std::dynamic_extent;
54
55private:
56 friend class World;
57};
58
59/// Constructs a [Join](@ref mim::Join) or Variant **value**.
60class Inj : public Def, public Setters<Inj> {
61private:
62 Inj(const Def* type, const Def* value, flags_t index)
63 : Def(Node, type, {value}, index) {}
64
65public:
66 using Setters<Inj>::set;
67
68 /// @name ops
69 ///@{
70 const Def* value() const { return op(0); }
71 ///@}
72
73 /// The case of a Variant this injects into.
74 /// A Join has no use for it: there, value()'s type determines the case.
75 size_t index() const { return flags(); }
76
77 static constexpr auto Node = mim::Node::Inj;
78 static constexpr size_t Num_Ops = 1;
79
80private:
81 friend class World;
82};
83
84/// A sum type whose cases are positional: unlike a Join, they are neither sorted nor deduplicated.
85/// It is *mutable* only if it refers to itself.
86class Variant : public Def, public Setters<Variant> {
87private:
88 Variant(const Def* type, Defs ops)
89 : Def(Node, type, ops, 0) {} ///< Constructor for an *immutable* Variant.
90 Variant(const Def* type, size_t size)
91 : Def(Node, type, size, 0) {} ///< Constructor for a *mutable* Variant.
92
93public:
94 /// @name Setters
95 /// @see @ref set_ops "Setting Ops"
96 ///@{
97 using Setters<Variant>::set;
98 Variant* set(size_t i, const Def* def) { return Def::set(i, def)->as<Variant>(); }
99 Variant* set(Defs ops) { return Def::set(ops)->as<Variant>(); }
100 Variant* unset() { return Def::unset()->as<Variant>(); }
101 ///@}
102
103 /// @name Type Checking
104 ///@{
105 static const Def* infer(World&, Defs);
106 ///@}
107
108 /// The payload `A` of a single-case Variant `| A`, which is isomorphic to `A`.
109 static const Def* isa_lone(const Def* d) {
110 auto variant = d->isa_imm<Variant>();
111 return variant && variant->num_ops() == 1 ? variant->op(0) : nullptr;
112 }
113
114 static constexpr auto Node = mim::Node::Variant;
115 static constexpr size_t Num_Ops = std::dynamic_extent;
116
117private:
118 friend class World;
119};
120
121/// Scrutinize Match::scrutinee() and dispatch to Match::arms.
122/// For a Variant, the arms are positional: `arm(i)` handles case `i`.
123class Match : public Def, public Setters<Match> {
124private:
125 Match(const Def* type, Defs ops)
126 : Def(Node, type, ops, 0) {}
127
128public:
129 using Setters<Match>::set;
130 static constexpr auto Node = mim::Node::Match;
131 static constexpr size_t Num_Ops = std::dynamic_extent;
132
133 /// @name ops
134 ///@{
135 const Def* scrutinee() const { return op(0); }
136 template<size_t N = std::dynamic_extent>
137 constexpr auto arms() const noexcept {
138 return ops().subspan<1, N>();
139 }
140 const Def* arm(size_t i) const { return arms()[i]; }
141 size_t num_arms() const { return arms().size(); } ///< @warning Can undercut Join::num_ops!
142 ///@}
143
144 /// @name Dispatch
145 ///@{
146 /// The cases @p scrutinee dispatches on: its Join's or Variant's ops, or - a one-case union - its type.
147 static DefVec cases(const Def* scrutinee);
148 /// Does @p arm handle @p c? An arm accepts the case that *is* its domain, or that its domain contains.
149 /// @p infer resolves Hole%s, so a mere search should leave it `false`.
150 static bool accepts(const Def* arm, const Def* c, bool infer = false);
151 ///@}
152
153private:
154 friend class World;
155};
156
157} // namespace mim
Base class for all Defs.
Definition def.h:289
constexpr Node node() const noexcept
Definition def.h:315
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:188
constexpr auto ops() const noexcept
Definition def.h:374
constexpr flags_t flags() const noexcept
Definition def.h:311
const Def * op(size_t i) const noexcept
Definition def.h:377
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:1119
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
Definition def.cpp:205
Ext(Node node, const Def *type)
Definition union.h:12
static constexpr bool isa_node(mim::Node n) noexcept
Ext groups Top and Bot; see fe::NodeSetable.
Definition union.h:17
static constexpr auto Node
Definition union.h:77
const Def * value() const
Definition union.h:70
size_t index() const
The case of a Variant this injects into.
Definition union.h:75
friend class World
Definition union.h:81
static constexpr size_t Num_Ops
Definition union.h:78
friend class World
Definition union.h:56
static constexpr auto Node
Definition union.h:52
static constexpr size_t Num_Ops
Definition union.h:53
static bool accepts(const Def *arm, const Def *c, bool infer=false)
Does arm handle c?
Definition union.cpp:18
static DefVec cases(const Def *scrutinee)
Definition union.cpp:10
const Def * scrutinee() const
Definition union.h:135
size_t num_arms() const
Definition union.h:141
friend class World
Definition union.h:154
static constexpr size_t Num_Ops
Definition union.h:131
static constexpr auto Node
Definition union.h:130
const Def * arm(size_t i) const
Definition union.h:140
constexpr auto arms() const noexcept
Definition union.h:137
CRTP-based mixin to declare setters for Def::loc & Def::name using a covariant return type.
Definition def.h:220
const TExt< Up > * set(Args &&... args) const
Definition def.h:232
Extremum. Either Top (Up) or Bottom.
Definition union.h:22
static constexpr auto Node
Definition union.h:30
friend class World
Definition union.h:34
static constexpr size_t Num_Ops
Definition union.h:31
Variant * set(size_t i, const Def *def)
Definition union.h:98
Variant * unset()
Definition union.h:100
static constexpr auto Node
Definition union.h:114
static const Def * infer(World &, Defs)
Definition check.cpp:494
friend class World
Definition union.h:118
Variant * set(Defs ops)
Definition union.h:99
static constexpr size_t Num_Ops
Definition union.h:115
static const Def * isa_lone(const Def *d)
The payload A of a single-case Variant | A, which is isomorphic to A.
Definition union.h:109
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:43
Definition ast.h:16
u64 flags_t
Definition types.h:39
fe::View< const Def * > Defs
Definition def.h:96
TExt< true > Top
Definition union.h:40
fe::Vector< const Def * > DefVec
Definition def.h:98
TExt< false > Bot
Definition union.h:39
Node
Definition def.h:123
@ Bot
Definition def.h:125
@ Variant
Definition def.h:125
@ Inj
Definition def.h:125
@ Match
Definition def.h:125
@ Join
Definition def.h:125
@ Top
Definition def.h:125