MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
stream.cpp
Go to the documentation of this file.
1#include <ostream>
2
3#include "mim/ast/ast.h"
4#include "mim/ast/lexer.h"
5
6namespace mim::ast {
7
8using Tag = Tok::Tag;
9
10struct S {
11 S(fe::Tab& tab, const Node* node)
12 : tab(tab)
13 , node(node) {}
14
15 fe::Tab& tab;
16 const Node* node;
17
18 friend std::ostream& operator<<(std::ostream& os, const S& s) { return s.node->stream(s.tab, os), os; }
19};
20
21} // namespace mim::ast
22
23#ifndef DOXYGEN
24template<>
25struct std::formatter<mim::ast::S> : fe::ostream_formatter {};
26#endif
27
28namespace mim::ast {
29
30template<class T>
31struct R {
32 R(fe::Tab& tab, fe::View<Ptr<T>> range, std::string_view sep = ", ")
33 : tab(tab)
34 , range(range)
35 , sep(sep) {}
36
37 fe::Tab& tab;
38 fe::View<Ptr<T>> range;
39 std::string_view sep;
40
41 friend std::ostream& operator<<(std::ostream& os, const R& r) {
42 for (std::string_view curr_sep{}; const auto& ptr : r.range) {
43 os << curr_sep;
44 ptr->stream(r.tab, os);
45 curr_sep = r.sep;
46 }
47 return os;
48 }
49};
50
51} // namespace mim::ast
52
53#ifndef DOXYGEN
54template<class T>
55struct std::formatter<mim::ast::R<T>> : fe::ostream_formatter {};
56#endif
57
58namespace mim::ast {
59
60template<class T>
61static void stream_decls(fe::Tab& tab, std::ostream& os, fe::View<Ptr<T>> decls) {
62 for (auto decl : decls)
63 std::println(os, "{}{}", tab, S(tab, decl.get()));
64}
65
66void Node::dump() const {
67 auto tab = fe::Tab::spaces();
68 stream(tab, std::cout);
69 std::cout << std::endl;
70}
71
72/*
73 * File
74 */
75
76void File::stream(fe::Tab& tab, std::ostream& os) const { stream_decls(tab, os, decls()); }
77
78/*
79 * Ptrn
80 */
81
82void ErrorPtrn::stream(fe::Tab&, std::ostream& os) const { os << "<error pattern>"; }
83void AliasPtrn::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "{}: {}", S(tab, ptrn()), dbg()); }
84void GrpPtrn::stream(fe::Tab&, std::ostream& os) const { os << dbg(); }
85
86void IdPtrn::stream(fe::Tab& tab, std::ostream& os) const {
87 // clang-format off
88 if ( dbg() && type()) { std::print(os, "{}: {}", dbg(), S(tab, type())); return; }
89 if ( dbg() && !type()) { std::print(os, "{}", dbg()); return; }
90 if (!dbg() && type()) { std::print(os, "{}", S(tab, type())); return; }
91 // clang-format on
92 os << "<invalid identifier pattern>";
93}
94
95void TuplePtrn::stream(fe::Tab& tab, std::ostream& os) const {
96 std::print(os, "{}{}{}", delim_l(), R(tab, ptrns()), delim_r());
97}
98
99/*
100 * Expr
101 */
102
103void Path::stream(fe::Tab&, std::ostream& os) const { std::print(os, "{}", fe::Join(dbgs(), ".")); }
104
105void PathExpr::stream(fe::Tab& tab, std::ostream& os) const { path()->stream(tab, os); }
106void ErrorExpr::stream(fe::Tab&, std::ostream& os) const { os << "<error expression>"; }
107void HoleExpr::stream(fe::Tab&, std::ostream& os) const { os << "?"; }
108void PrimaryExpr::stream(fe::Tab&, std::ostream& os) const { std::print(os, "{}", tag()); }
109
110void LitExpr::stream(fe::Tab& tab, std::ostream& os) const {
111 switch (tag()) {
112 case Tag::L_i: {
113 auto [size, val] = tok().lit_i();
114 std::print(os, "{}_{}", val, size); // the `_` form spells out every size, 2^64 included
115 return;
116 }
117 case Tag::L_f: os << std::bit_cast<double>(tok().lit_u()); return;
118 case Tag::L_s:
119 case Tag::L_u:
120 os << tok().lit_u();
121 if (type()) std::print(os, ": {}", S(tab, type()));
122 return;
123 default: os << "TODO";
124 }
125}
126
127void DeclExpr::stream(fe::Tab& tab, std::ostream& os) const {
128 if (is_where()) {
129 std::println(os, "{}{} where", tab, S(tab, expr()));
130 ++tab;
131 stream_decls(tab, os, decls());
132 --tab;
133 } else {
134 stream_decls(tab, os, decls());
135 std::print(os, "{}", S(tab, expr()));
136 }
137}
138
139void TypeExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "(Type {})", S(tab, level())); }
140void RuleExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "(Rule {})", S(tab, dom())); }
141
142void InfixExpr::stream(fe::Tab& tab, std::ostream& os) const {
143 std::print(os, "({} {} {})", S(tab, lhs()), Tok::tag2str(op().tag()), S(tab, rhs()));
144}
145
146void MatchExpr::Arm::stream(fe::Tab& tab, std::ostream& os) const {
147 std::print(os, "{} => {}", S(tab, ptrn()), S(tab, body()));
148}
149
150void MatchExpr::stream(fe::Tab& tab, std::ostream& os) const {
151 std::println(os, "{}match {} with", tab, S(tab, scrutinee()));
152 ++tab;
153 for (auto arm : arms())
154 std::println(os, "{}| {}", tab, S(tab, arm.get()));
155 --tab;
156 std::println(os, "{}}}", tab);
157}
158
159void PiExpr::Dom::stream(fe::Tab& tab, std::ostream& os) const {
160 std::print(os, "{}{}", is_implicit() ? "." : "", S(tab, ptrn()));
161 if (ret()) std::print(os, " -> {}", S(tab, ret()->type()));
162}
163
164void PiExpr::stream(fe::Tab& tab, std::ostream& os) const {
165 if (tag() != Tag::Nil) std::print(os, "{} ", tag());
166 std::print(os, "{}", S(tab, dom()));
167 if (codom()) std::print(os, " -> {}", S(tab, codom()));
168}
169
170void LamExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "{};", S(tab, lam())); }
171
172void AppExpr::stream(fe::Tab& tab, std::ostream& os) const {
173 std::print(os, "({} {})", S(tab, callee()), S(tab, arg()));
174}
175
176void RetExpr::stream(fe::Tab& tab, std::ostream& os) const {
177 std::println(os, "ret {} = {} $ {};", S(tab, ptrn()), S(tab, callee()), S(tab, arg()));
178 std::print(os, "{}{}", tab, S(tab, body()));
179}
180
181void SigmaExpr::stream(fe::Tab& tab, std::ostream& os) const { ptrn()->stream(tab, os); }
182void TupleExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "({})", R(tab, elems())); }
183
184void SeqExpr::stream(fe::Tab& tab, std::ostream& os) const {
185 std::print(os, "{}{}; {}{}", is_pack() ? "‹" : "«", S(tab, arity()), S(tab, body()), is_pack() ? "›" : "»");
186}
187
188void UniqExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "⦃{}⦄", S(tab, inhabitant())); }
189
190/*
191 * Decl
192 */
193
194static std::string_view vis2str(Vis vis) {
195 switch (vis) {
196 case Vis::Priv: return "priv";
197 case Vis::Pub: return "pub";
198 }
199 fe::unreachable();
200}
201
202/// Prints `vis`/`extern`/`anx`, skipping `vis` if it's the modifier-nudged Mods::default_vis.
203static std::ostream& operator<<(std::ostream& os, const Mods& mods) {
204 if (auto vis = mods.resolved_vis(); vis != mods.default_vis()) std::print(os, "{} ", vis2str(vis));
205 if (mods.is_extern) std::print(os, "extern ");
206 if (mods.is_anx) std::print(os, "anx ");
207 return os;
208}
209
210} // namespace mim::ast
211
212#ifndef DOXYGEN
213template<>
214struct std::formatter<mim::ast::Mods> : fe::ostream_formatter {};
215#endif
216
217namespace mim::ast {
218
219void AxmDecl::stream(fe::Tab& tab, std::ostream& os) const {
220 if (vis() == Vis::Priv) std::print(os, "priv "); // `axm` is always anx, so it's never printed here
221 std::print(os, "axm {}: {}", dbg(), S(tab, type()));
222 if (normalizer()) std::print(os, ", {}", normalizer());
223 if (curry()) std::print(os, ", {}", curry());
224 if (trip()) std::print(os, ", {}", trip());
225 os << ";";
226}
227
228void AxmDecl::Sibling::stream(fe::Tab& tab, std::ostream& os) const {
229 if (vis() == Vis::Priv) std::print(os, "priv "); // `axm` is always anx, so it's never printed here
230 std::print(os, "axm {}: {}", dbg(), S(tab, owner()->type()));
231 if (owner()->normalizer()) std::print(os, ", {}", owner()->normalizer());
232 os << ";";
233}
234
235void AliasDecl::stream(fe::Tab& tab, std::ostream& os) const {
236 if (vis() == Vis::Priv) std::print(os, "priv ");
237 std::print(os, "anx {} = {};", dbg(), S(tab, path()));
238}
239
240void ModDecl::stream(fe::Tab& tab, std::ostream& os) const {
241 std::println(os, "{}mod {} {{", mods(), dbg());
242 ++tab;
243 stream_decls(tab, os, decls());
244 --tab;
245 std::print(os, "{}}}", tab);
246}
247
248void UseDecl::stream(fe::Tab& tab, std::ostream& os) const {
249 if (is_file_path())
250 std::print(os, "{}{} \"{}\"", mods(), tag(), Lexer::escape(file_path().view()));
251 else
252 std::print(os, "{}{} {}", mods(), tag(), S(tab, path()));
253 if (alias()) std::print(os, " as {}", alias());
254 if (is_splice() && is_import()) std::print(os, " as {}", Tag::T_star);
255 os << ';';
256}
257
258void LetDecl::stream(fe::Tab& tab, std::ostream& os) const {
259 std::print(os, "{}let {} = {};", mods(), S(tab, ptrn()), S(tab, value()));
260}
261
262void RecDecl::stream(fe::Tab& tab, std::ostream& os) const {
263 std::print(os, "{}{}", mods(), isa<LamDecl>() ? "" : "rec ");
264 stream_(tab, os);
265 for (auto curr = next(); curr; curr = curr->next()) {
266 std::println(os);
267 std::print(os, "{}and ", tab);
268 curr->stream_(tab, os);
269 }
270 os << ';';
271}
272
273void RecDecl::stream_(fe::Tab& tab, std::ostream& os) const { std::print(os, "{} = {}", dbg(), S(tab, body())); }
274
275void LamDecl::Dom::stream(fe::Tab& tab, std::ostream& os) const {
276 std::print(os, "{}{}", is_implicit() ? "." : "", S(tab, ptrn()));
277 if (filter()) std::print(os, "@({})", S(tab, filter()));
278 if (ret()) std::print(os, ": {}", S(tab, ret()->type()));
279}
280
281void LamDecl::stream_(fe::Tab& tab, std::ostream& os) const {
282 std::print(os, "{} {}", tag(), dbg());
283 if (!doms().front()->ptrn()->isa<TuplePtrn>()) os << ' ';
284 std::print(os, "{}", R(tab, doms()));
285 if (codom()) std::print(os, ": {}", S(tab, codom()));
286 if (body()) {
287 if (body()->isa<DeclExpr>()) {
288 os << " =" << std::endl;
289 ++tab;
290 std::print(os, "{}{}", tab, S(tab, body()));
291 --tab;
292 } else {
293 std::print(os, " = {}", S(tab, body()));
294 }
295 }
296}
297
298void RuleDecl::stream(fe::Tab& tab, std::ostream& os) const {
299 std::print(os, "rule {} : {} => {} when {}", S(tab, var()), S(tab, lhs()), S(tab, rhs()), S(tab, guard()));
300}
301} // namespace mim::ast
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1121
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:235
const Path * path() const
Definition ast.h:1122
const Ptrn * ptrn() const
Definition ast.h:375
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:376
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:83
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:172
const Expr * arg() const
Definition ast.h:763
const Expr * callee() const
Definition ast.h:762
const AxmDecl * owner() const
Definition ast.h:978
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:977
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:228
const Expr * type() const
Definition ast.h:1001
Tok trip() const
Definition ast.h:1004
Tok curry() const
Definition ast.h:1003
Dbg normalizer() const
Definition ast.h:1002
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:219
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1000
const Expr * expr() const
Definition ast.h:543
auto decls() const
Definition ast.h:541
bool is_where() const
Definition ast.h:542
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:127
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:106
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:82
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:76
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:84
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:354
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:107
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:86
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:318
const Expr * type() const
Definition ast.h:319
const Expr * rhs() const
Definition ast.h:606
const Expr * lhs() const
Definition ast.h:604
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:142
Tok op() const
Definition ast.h:605
const Expr * filter() const
Definition ast.h:1069
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:275
bool is_implicit() const
Definition ast.h:1068
Tok::Tag tag() const
Definition ast.h:1089
auto doms() const
Definition ast.h:1092
const Expr * codom() const
Definition ast.h:1095
void stream_(fe::Tab &, std::ostream &) const override
Streams this declaration alone - without the leading rec/and and without the trailing ;.
Definition stream.cpp:281
const LamDecl * lam() const
Definition ast.h:741
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:170
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:258
const Expr * value() const
Definition ast.h:953
const Ptrn * ptrn() const
Definition ast.h:952
static std::string escape(std::string_view str)
Inverse of Lexer::lex_char: renders str as the body of a Mim string literal.
Definition lexer.cpp:199
Tok tok() const
Definition ast.h:517
const Expr * type() const
Definition ast.h:519
Tok::Tag tag() const
Definition ast.h:518
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:110
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:146
const Expr * body() const
Definition ast.h:645
const Ptrn * ptrn() const
Definition ast.h:644
auto arms() const
Definition ast.h:663
const Expr * scrutinee() const
Definition ast.h:662
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:150
const Arm * arm(size_t i) const
Definition ast.h:664
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:240
auto decls() const
Definition ast.h:1180
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1179
Base class of all AST nodes.
Definition ast.h:186
virtual void stream(fe::Tab &, std::ostream &) const =0
void dump() const
Definition stream.cpp:66
const Path * path() const
Definition ast.h:476
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:105
auto dbgs() const
Definition ast.h:457
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:103
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:159
const IdPtrn * ret() const
Definition ast.h:690
bool is_implicit() const
Definition ast.h:688
const Ptrn * ptrn() const
Definition ast.h:689
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:164
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:108
Tok::Tag tag() const
Definition ast.h:498
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:262
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1031
virtual void stream_(fe::Tab &, std::ostream &) const
Streams this declaration alone - without the leading rec/and and without the trailing ;.
Definition stream.cpp:273
const Expr * body() const
Definition ast.h:1032
const RecDecl * next() const
Definition ast.h:1033
const Ptrn * ptrn() const
Definition ast.h:785
const Expr * arg() const
Definition ast.h:787
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:176
const Expr * body() const
Definition ast.h:788
const Expr * callee() const
Definition ast.h:786
const Ptrn * var() const
Definition ast.h:1149
const Expr * guard() const
Definition ast.h:1152
const Expr * rhs() const
Definition ast.h:1151
const Expr * lhs() const
Definition ast.h:1150
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:298
const Expr * dom() const
Definition ast.h:580
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:140
bool is_pack() const
Definition ast.h:851
const Expr * body() const
Definition ast.h:853
const IdPtrn * arity() const
Definition ast.h:852
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:184
const TuplePtrn * ptrn() const
Definition ast.h:810
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:181
std::pair< uint64_t, uint64_t > lit_i() const
Definition tok.h:317
uint64_t lit_u() const
Definition tok.h:319
static const char * tag2str(Tok::Tag)
Definition tok.cpp:10
auto elems() const
Definition ast.h:831
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:182
Tok::Tag delim_r() const
Definition ast.h:399
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:95
auto ptrns() const
Definition ast.h:404
Tok::Tag delim_l() const
Definition ast.h:398
const Expr * level() const
Definition ast.h:562
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:139
const Expr * inhabitant() const
Definition ast.h:873
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:188
bool is_splice() const
as *: splice the module's public members, bind no name.
Definition ast.h:921
Dbg alias() const
Empty, unless the source spelled as I.
Definition ast.h:917
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:248
Sym file_path() const
Spelling of an import "..."; empty otherwise.
Definition ast.h:918
bool is_file_path() const
Definition ast.h:919
bool is_import() const
Definition ast.h:915
Tok::Tag tag() const
import, plugin, or use.
Definition ast.h:914
const Path * path() const
Module path of a use; module name of an import/plugin.
Definition ast.h:916
const Mods & mods() const
Definition ast.h:266
Vis vis() const override
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
Definition ast.h:263
Definition ast.h:16
static std::string_view vis2str(Vis vis)
Definition stream.cpp:194
Vis
Visibility tier of a ValDecl.
Definition ast.h:41
fe::Arena::Ref< const T > Ptr
Nodes live in the AST's Arena and are never destroyed, so this merely points at one.
Definition ast.h:26
static void stream_decls(fe::Tab &tab, std::ostream &os, fe::View< Ptr< T > > decls)
Definition stream.cpp:61
Tok::Tag Tag
Definition bind.cpp:9
std::ostream & operator<<(std::ostream &os, Tok tok)
Definition tok.cpp:30
Definition ast.h:16
Raw, unvalidated combination of priv/pub/extern/anx modifiers written before a declaration.
Definition ast.h:55
bool is_anx
Definition ast.h:58
Vis resolved_vis() const
Definition ast.h:62
bool is_extern
Definition ast.h:57
Vis default_vis() const
extern/anx nudge the default visibility to Pub unless priv is given explicitly.
Definition ast.h:61
fe::Tab & tab
Definition stream.cpp:37
std::string_view sep
Definition stream.cpp:39
friend std::ostream & operator<<(std::ostream &os, const R &r)
Definition stream.cpp:41
fe::View< Ptr< T > > range
Definition stream.cpp:38
R(fe::Tab &tab, fe::View< Ptr< T > > range, std::string_view sep=", ")
Definition stream.cpp:32
fe::Tab & tab
Definition stream.cpp:15
friend std::ostream & operator<<(std::ostream &os, const S &s)
Definition stream.cpp:18
S(fe::Tab &tab, const Node *node)
Definition stream.cpp:11
const Node * node
Definition stream.cpp:16