MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
stream.cpp
Go to the documentation of this file.
1#include <bit>
2#include <ostream>
3
4#include "mim/ast/ast.h"
5#include "mim/ast/lexer.h"
6
7namespace mim::ast {
8
9using Tag = Tok::Tag;
10
11struct S {
12 S(fe::Tab& tab, const Node* node)
13 : tab(tab)
14 , node(node) {}
15
16 fe::Tab& tab;
17 const Node* node;
18
19 friend std::ostream& operator<<(std::ostream& os, const S& s) { return s.node->stream(s.tab, os), os; }
20};
21
22} // namespace mim::ast
23
24#ifndef DOXYGEN
25template<>
26struct std::formatter<mim::ast::S> : fe::ostream_formatter {};
27#endif
28
29namespace mim::ast {
30
31template<class T>
32struct R {
33 R(fe::Tab& tab, fe::View<Ptr<T>> range, std::string_view sep = ", ")
34 : tab(tab)
35 , range(range)
36 , sep(sep) {}
37
38 fe::Tab& tab;
39 fe::View<Ptr<T>> range;
40 std::string_view sep;
41
42 friend std::ostream& operator<<(std::ostream& os, const R& r) {
43 for (std::string_view curr_sep{}; const auto& ptr : r.range) {
44 os << curr_sep;
45 ptr->stream(r.tab, os);
46 curr_sep = r.sep;
47 }
48 return os;
49 }
50};
51
52} // namespace mim::ast
53
54#ifndef DOXYGEN
55template<class T>
56struct std::formatter<mim::ast::R<T>> : fe::ostream_formatter {};
57#endif
58
59namespace mim::ast {
60
61static void stream_decls(fe::Tab& tab, std::ostream& os, fe::View<Ptr<ValDecl>> decls);
62
63void Node::dump() const {
64 auto tab = fe::Tab::spaces();
65 stream(tab, std::cout);
66 std::cout << std::endl;
67}
68
69/*
70 * File
71 */
72
73// The output parses back into the same AST: every paren of the input is a TupleExpr, so none is added here.
74void File::stream(fe::Tab& tab, std::ostream& os) const { stream_decls(tab, os, decls()); }
75
76/*
77 * Ptrn
78 */
79
80void ErrorPtrn::stream(fe::Tab&, std::ostream& os) const { os << "<error pattern>"; }
81void AliasPtrn::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "{} as {}", S(tab, ptrn()), dbg()); }
82void GrpPtrn::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "{}: {}", dbg(), S(tab, id()->type())); }
83
84void IdPtrn::stream(fe::Tab& tab, std::ostream& os) const {
85 // clang-format off
86 if ( dbg() && type()) { std::print(os, "{}: {}", dbg(), S(tab, type())); return; }
87 if ( dbg() && !type()) { std::print(os, "{}", dbg()); return; }
88 if (!dbg() && type()) { std::print(os, "{}", S(tab, type())); return; }
89 // clang-format on
90 os << "<invalid identifier pattern>";
91}
92
93void IdDecl::stream(fe::Tab&, std::ostream& os) const { os << dbg(); }
94
95void TuplePtrn::stream(fe::Tab& tab, std::ostream& os) const {
96 os << delim_l();
97 for (size_t i = 0, n = num_ptrns(); i != n; ++i)
98 if (i + 1 != n && ptrn(i + 1)->isa<GrpPtrn>())
99 std::print(os, "{} ", ptrn(i)->dbg());
100 else
101 std::print(os, "{}{}", S(tab, ptrn(i)), i + 1 != n ? ", " : "");
102 os << delim_r();
103}
104
105/*
106 * Expr
107 */
108
109void Path::stream(fe::Tab&, std::ostream& os) const { std::print(os, "{}", fe::Join(dbgs(), ".")); }
110
111void PathExpr::stream(fe::Tab& tab, std::ostream& os) const { path()->stream(tab, os); }
112void ErrorExpr::stream(fe::Tab&, std::ostream& os) const { os << "<error expression>"; }
113void HoleExpr::stream(fe::Tab&, std::ostream& os) const { os << "?"; }
114void PrimaryExpr::stream(fe::Tab&, std::ostream& os) const { std::print(os, "{}", tag()); }
115
116static std::string escape_char(char8_t c) { return c == '\'' ? "\\'" : Lexer::escape(std::string(1, char(c))); }
117
118void LitExpr::stream(fe::Tab& tab, std::ostream& os) const {
119 switch (tag()) {
120 case Tag::L_i: {
121 auto [size, val] = tok().lit_i();
122 if (size == 0 || (size > 1 && std::has_single_bit(size)))
123 std::print(os, "{}I{}", val, Idx::size2bitwidth(size));
124 else
125 std::print(os, "{}_{}", val, size);
126 break;
127 }
128 case Tag::L_s: os << std::bit_cast<s64>(tok().lit_u()); break;
129 case Tag::L_u: os << tok().lit_u(); break;
130 case Tag::L_f: {
131 auto str = std::format("{}", std::bit_cast<f64>(tok().lit_u()));
132 // The shortest round-tripping spelling may lack both `.` and exponent, which would lex as an integer.
133 if (str.find_first_of(".ein") == std::string::npos) str += ".0";
134 os << str;
135 break;
136 }
137 case Tag::L_c: std::print(os, "'{}'", escape_char(tok().lit_c())); break;
138 case Tag::L_str: std::print(os, "\"{}\"", Lexer::escape(tok().sym().view())); break;
139 case Tag::T_bot:
140 case Tag::T_top: os << tag(); break;
141 default: std::unreachable();
142 }
143 if (type()) std::print(os, ":{}", S(tab, type()));
144}
145
146void DeclExpr::stream(fe::Tab& tab, std::ostream& os) const {
147 if (is_where()) {
148 std::println(os, "{} where", S(tab, expr()));
149 ++tab;
150 stream_decls(tab, os, decls());
151 --tab;
152 std::print(os, "{}end", tab);
153 } else {
154 for (auto decl : decls())
155 std::print(os, "{}\n{}", S(tab, decl.get()), tab);
156 std::print(os, "{}", S(tab, expr()));
157 }
158}
159
160void TypeExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "Type {}", S(tab, level())); }
161void RuleExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "Rule {}", S(tab, dom())); }
162
163void PrefixExpr::stream(fe::Tab& tab, std::ostream& os) const {
164 std::print(os, "{}{}", Tok::tag2str(op().tag()), S(tab, rhs()));
165}
166
167void InfixExpr::stream(fe::Tab& tab, std::ostream& os) const {
168 auto op = Tok::tag2str(this->op().tag());
169 if (this->op().isa(Tag::T_extract)) return std::print(os, "{}{}{}", S(tab, lhs()), op, S(tab, rhs()));
170 std::print(os, "{} {} {}", S(tab, lhs()), op, S(tab, rhs()));
171}
172
173void MatchExpr::Arm::stream(fe::Tab& tab, std::ostream& os) const {
174 if (index()) std::print(os, "{} ", *index());
175 if (ctor_) std::print(os, "{} ", ctor_);
176 if (ptrn()) std::print(os, "{} ", S(tab, ptrn()));
177 std::print(os, "=> {}", S(tab, body()));
178}
179
180void VariantExpr::Ctor::stream(fe::Tab& tab, std::ostream& os) const {
181 if (type()) return std::print(os, "{}: {}", dbg(), S(tab, type()));
182 std::print(os, "{}", dbg());
183}
184
185void VariantExpr::stream(fe::Tab& tab, std::ostream& os) const {
186 if (num_ctors() == 0) return std::print(os, "|");
187 for (auto sep = ""; auto ctor : ctors()) {
188 std::print(os, "{}| {}", sep, S(tab, ctor.get()));
189 sep = " ";
190 }
191}
192
193void MatchExpr::stream(fe::Tab& tab, std::ostream& os) const {
194 std::print(os, "match {} with", S(tab, scrutinee()));
195 ++tab;
196 for (auto arm : arms())
197 std::print(os, "\n{}| {}", tab, S(tab, arm.get()));
198 --tab;
199}
200
201void PiExpr::Dom::stream(fe::Tab& tab, std::ostream& os) const {
202 std::print(os, "{}", S(tab, ptrn()));
203 if (ret_type()) std::print(os, " {} {}", Tag::T_arrow_r, S(tab, ret_type()));
204}
205
206void PiExpr::stream(fe::Tab& tab, std::ostream& os) const {
207 if (tag() == Tag::K_Cn || tag() == Tag::K_Fn) std::print(os, "{} ", tag());
208 std::print(os, "{}", S(tab, dom()));
209 if (codom()) std::print(os, " {} {}", Tag::T_arrow_r, S(tab, codom()));
210}
211
212void LamExpr::stream(fe::Tab& tab, std::ostream& os) const { lam()->stream_(tab, os); }
213
214void AppExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "{} {}", S(tab, callee()), S(tab, arg())); }
215
216void RetExpr::stream(fe::Tab& tab, std::ostream& os) const {
217 std::println(os, "ret {} = {} $ {};", S(tab, ptrn()), S(tab, callee()), S(tab, arg()));
218 std::print(os, "{}{}", tab, S(tab, body()));
219}
220
221void SigmaExpr::stream(fe::Tab& tab, std::ostream& os) const { ptrn()->stream(tab, os); }
222void TupleExpr::stream(fe::Tab& tab, std::ostream& os) const { std::print(os, "({})", R(tab, elems())); }
223
224void SeqExpr::stream(fe::Tab& tab, std::ostream& os) const {
225 os << (is_pack() ? "‹" : "«");
226 if (index()->dbg()) std::print(os, "{}: ", S(tab, index()));
227 std::print(os, "{}; {}{}", S(tab, shape()), S(tab, body()), is_pack() ? "›" : "»");
228}
229
230void SingleExpr::stream(fe::Tab& tab, std::ostream& os) const {
231 std::print(os, "{}{}{}", is_wrap() ? "‹" : "«", S(tab, body()), is_wrap() ? "›" : "»");
232}
233
234/*
235 * Decl
236 */
237
238static std::string_view vis2str(Vis vis) {
239 switch (vis) {
240 case Vis::Priv: return "priv";
241 case Vis::Pub: return "pub";
242 }
243 std::unreachable();
244}
245
246/// Prints `vis`/`extern`/`anx`, skipping `vis` if it's the modifier-nudged Mods::default_vis.
247static std::ostream& operator<<(std::ostream& os, const Mods& mods) {
248 if (auto vis = mods.resolved_vis(); vis != mods.default_vis()) std::print(os, "{} ", vis2str(vis));
249 if (mods.is_extern) std::print(os, "extern ");
250 if (mods.is_anx) std::print(os, "anx ");
251 return os;
252}
253
254} // namespace mim::ast
255
256#ifndef DOXYGEN
257template<>
258struct std::formatter<mim::ast::Mods> : fe::ostream_formatter {};
259#endif
260
261namespace mim::ast {
262
263static void stream_decls(fe::Tab& tab, std::ostream& os, fe::View<Ptr<ValDecl>> decls) {
264 auto grouped = [](const ValDecl* prev, const ValDecl* curr) {
265 return (prev->isa<UseDecl>() && curr->isa<UseDecl>()) || (prev->isa<LetDecl>() && curr->isa<LetDecl>());
266 };
267
268 for (size_t i = 0; i != decls.size(); ++i) {
269 if (i != 0 && !grouped(decls[i - 1].get(), decls[i].get())) os << '\n';
270 std::println(os, "{}{}", tab, S(tab, decls[i].get()));
271 }
272}
273
274void AxmDecl::Name::stream(fe::Tab&, std::ostream& os) const { os << fe::Join(names(), " = "); }
275
276/// `axm` is always anx, so only `priv` is ever printed.
277void AxmDecl::stream(fe::Tab& tab, std::ostream& os) const {
278 if (vis() == Vis::Priv) os << "priv ";
279 os << "axm ";
280 if (mod_) std::print(os, "{}.", mod_);
281 if (is_family())
282 std::print(os, "({})", R(tab, names()));
283 else
284 std::print(os, "{}", S(tab, names().front().get()));
285 std::print(os, ": {}", S(tab, type()));
286 if (normalizer()) std::print(os, ", {}", normalizer());
287 if (curry()) std::print(os, ", {}", curry().lit_u());
288 if (trip()) std::print(os, ", {}", trip().lit_u());
289 os << ';';
290}
291
292void AliasDecl::stream(fe::Tab& tab, std::ostream& os) const {
293 if (vis() == Vis::Priv) std::print(os, "priv ");
294 std::print(os, "anx {} = {};", dbg(), S(tab, path()));
295}
296
297void ModDecl::stream(fe::Tab& tab, std::ostream& os) const {
298 std::println(os, "{}mod {}", mods(), dbg());
299 ++tab;
300 stream_decls(tab, os, decls());
301 --tab;
302 std::print(os, "{}end", tab);
303}
304
305void UseDecl::stream(fe::Tab& tab, std::ostream& os) const {
306 if (is_file_path())
307 std::print(os, "{}{} \"{}\"", mods(), tag(), Lexer::escape(file_path().view()));
308 else
309 std::print(os, "{}{} {}", mods(), tag(), S(tab, path()));
310 if (alias()) std::print(os, " as {}", alias());
311 if (is_splice() && is_import()) std::print(os, " as {}", Tag::T_star);
312 os << ';';
313}
314
315void LetDecl::stream(fe::Tab& tab, std::ostream& os) const {
316 std::print(os, "{}let {} = {};", mods(), S(tab, ptrn()), S(tab, value()));
317}
318
319void RecDecl::stream(fe::Tab& tab, std::ostream& os) const {
320 std::print(os, "{}", mods());
321 stream_(tab, os);
322 os << ';';
323}
324
325void RecDecl::stream_(fe::Tab& tab, std::ostream& os) const { std::print(os, "rec {} = {}", dbg(), S(tab, body())); }
326void NomDecl::stream_(fe::Tab& tab, std::ostream& os) const { std::print(os, "nom {} = {}", dbg(), S(tab, body())); }
327
328void MutualDecl::stream(fe::Tab& tab, std::ostream& os) const {
329 os << "mutual\n";
330 ++tab;
331 for (std::string_view sep{}; auto decl : decls()) {
332 std::println(os, "{}{}{}", sep, tab, S(tab, decl.get()));
333 sep = "\n";
334 }
335 --tab;
336 std::print(os, "{}end", tab);
337}
338
339void LamDecl::Dom::stream(fe::Tab& tab, std::ostream& os) const {
340 std::print(os, "{}", S(tab, ptrn()));
341 if (filter()) std::print(os, "@{}", S(tab, filter()));
342 // Parser::parse_lam_decl fills in an omitted codomain of a `fun`/`fn` as a hole.
343 if (ret_type() && !ret_type()->isa<HoleExpr>()) std::print(os, ": {}", S(tab, ret_type()));
344}
345
346/// Does @p expr span several statements and hence deserve an indented block of its own?
347static bool is_block(const Expr* expr) {
348 if (auto decl = expr->isa<DeclExpr>()) return !decl->is_where();
349 return expr->isa<RetExpr>();
350}
351
352void LamDecl::stream_(fe::Tab& tab, std::ostream& os) const {
353 if (auto nom = nom_sugar()) {
354 std::print(os, "nom {}", dbg());
355 for (auto dom : doms())
356 std::print(os, " {}", S(tab, dom.get()));
357 std::print(os, " = {}", S(tab, nom->body()));
358 return;
359 }
360 std::print(os, "{}", tag());
361 if (dbg()) std::print(os, " {}", dbg());
362 for (auto dom : doms())
363 std::print(os, " {}", S(tab, dom.get()));
364 if (codom()) std::print(os, ": {}", S(tab, codom()));
365 if (body()) {
366 if (is_block(body())) {
367 ++tab;
368 std::print(os, " =\n{}{}", tab, S(tab, body()));
369 --tab;
370 } else {
371 std::print(os, " = {}", S(tab, body()));
372 }
373 }
374}
375
376void RuleDecl::stream(fe::Tab& tab, std::ostream& os) const {
377 std::print(os, "{}{} {} {}: {}", mods(), is_norm() ? Tag::K_norm : Tag::K_rule, dbg(), S(tab, var()),
378 S(tab, lhs()));
379 if (auto tt = guard()->isa<PrimaryExpr>(); !tt || tt->tag() != Tag::K_tt)
380 std::print(os, " when {}", S(tab, guard()));
381 std::print(os, " => {};", S(tab, rhs()));
382}
383
384} // namespace mim::ast
static constexpr nat_t size2bitwidth(nat_t n)
Definition def.h:1040
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1271
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:292
const Path * path() const
Definition ast.h:1272
const Ptrn * ptrn() const
Definition ast.h:409
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:410
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:81
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:214
const Expr * arg() const
Definition ast.h:864
const Expr * callee() const
Definition ast.h:863
auto names() const
Definition ast.h:1083
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:274
auto names() const
Definition ast.h:1113
const Expr * type() const
Definition ast.h:1116
bool is_family() const
Whether the names are spelled as a parenthesized list, even if it is just one.
Definition ast.h:1115
Tok trip() const
Definition ast.h:1119
Tok curry() const
Definition ast.h:1118
Dbg normalizer() const
Definition ast.h:1117
void stream(fe::Tab &, std::ostream &) const override
axm is always anx, so only priv is ever printed.
Definition stream.cpp:277
decls expr or expr where decls if DeclExpr::is_where.
Definition ast.h:566
const Expr * expr() const
Definition ast.h:577
auto decls() const
Definition ast.h:575
bool is_where() const
Definition ast.h:576
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:146
virtual Dbg dbg() const
The name this Decl introduces; anonymous if it has none.
Definition ast.h:259
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:112
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:80
Base class of all expressions.
Definition ast.h:227
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:74
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:82
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:388
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:113
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:93
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:282
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:355
const Expr * type() const
Definition ast.h:356
const Expr * rhs() const
Definition ast.h:661
const Expr * lhs() const
Definition ast.h:659
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:167
Tok op() const
Definition ast.h:660
const Expr * filter() const
Definition ast.h:1205
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:339
Tok::Tag tag() const
Definition ast.h:1228
auto doms() const
Definition ast.h:1229
const Expr * codom() const
Definition ast.h:1232
const NomDecl * nom_sugar() const
The nom of lam I dom+ = nom I = e; I if nom I dom+ = e desugared to this; within e,...
Definition ast.h:1234
const Dom * dom(size_t i) const
Definition ast.h:1230
void stream_(fe::Tab &, std::ostream &) const override
Streams this declaration without modifiers and without the trailing ;.
Definition stream.cpp:352
const LamDecl * lam() const
Definition ast.h:842
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:212
let ptrn = value;
Definition ast.h:1052
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:315
const Expr * value() const
Definition ast.h:1060
const Ptrn * ptrn() const
Definition ast.h:1059
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:239
Tok tok() const
Definition ast.h:551
const Expr * type() const
Definition ast.h:553
Tok::Tag tag() const
Definition ast.h:552
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:118
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:173
const Expr * body() const
Definition ast.h:702
const Ptrn * ptrn() const
Definition ast.h:701
std::optional< nat_t > index() const
The case this arm selects by literal index, as in 1 (h, t).
Definition ast.h:704
auto arms() const
Definition ast.h:727
const Expr * scrutinee() const
Definition ast.h:726
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:193
const Arm * arm(size_t i) const
Definition ast.h:728
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:297
auto decls() const
Definition ast.h:1331
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1330
auto decls() const
Definition ast.h:1256
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:328
Base class of all AST nodes.
Definition ast.h:206
virtual void stream(fe::Tab &, std::ostream &) const =0
void dump() const
Definition stream.cpp:63
void stream_(fe::Tab &, std::ostream &) const override
Streams this declaration without modifiers and without the trailing ;.
Definition stream.cpp:326
const Path * path() const
Definition ast.h:510
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:111
auto dbgs() const
Definition ast.h:491
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:109
const Expr * ret_type() const
Definition ast.h:796
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:201
const Ptrn * ptrn() const
Definition ast.h:795
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:206
Tok op() const
Definition ast.h:635
const Expr * rhs() const
Definition ast.h:636
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:163
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:114
Tok::Tag tag() const
Definition ast.h:532
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:319
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1142
virtual void stream_(fe::Tab &, std::ostream &) const
Streams this declaration without modifiers and without the trailing ;.
Definition stream.cpp:325
const Expr * body() const
Definition ast.h:1143
ret ptrn = callee $ arg; body
Definition ast.h:877
const Ptrn * ptrn() const
Definition ast.h:886
const Expr * arg() const
Definition ast.h:888
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:216
const Expr * body() const
Definition ast.h:889
const Expr * callee() const
Definition ast.h:887
const Ptrn * var() const
Definition ast.h:1300
const Expr * guard() const
Definition ast.h:1303
bool is_norm() const
Definition ast.h:1304
const Expr * rhs() const
Definition ast.h:1302
const Expr * lhs() const
Definition ast.h:1301
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1299
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:376
const Expr * dom() const
Definition ast.h:614
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:161
bool is_pack() const
Definition ast.h:953
const Expr * body() const
Definition ast.h:956
const IdDecl * index() const
Definition ast.h:954
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:224
const Expr * shape() const
Definition ast.h:955
const TuplePtrn * ptrn() const
Definition ast.h:911
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:221
bool is_wrap() const
Definition ast.h:978
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:230
const Expr * body() const
Definition ast.h:979
std::pair< uint64_t, uint64_t > lit_i() const
Definition tok.h:336
uint64_t lit_u() const
Definition tok.h:338
static const char * tag2str(Tok::Tag)
Definition tok.cpp:10
auto elems() const
Definition ast.h:932
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:222
const Ptrn * ptrn(size_t i) const
Definition ast.h:438
Tok::Tag delim_r() const
Definition ast.h:433
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:95
size_t num_ptrns() const
Definition ast.h:440
Tok::Tag delim_l() const
Definition ast.h:432
const Expr * level() const
Definition ast.h:596
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:160
import "file"|name [as alias|*];, plugin name [as alias|*];, or use path [as alias|*]; as * splices i...
Definition ast.h:1000
bool is_splice() const
as *: splice the module's public members, bind no name.
Definition ast.h:1028
Dbg alias() const
Empty, unless the source spelled as I.
Definition ast.h:1024
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:305
Sym file_path() const
Spelling of an import "..."; empty otherwise.
Definition ast.h:1025
bool is_file_path() const
Definition ast.h:1026
bool is_import() const
Definition ast.h:1022
Tok::Tag tag() const
import, plugin, or use.
Definition ast.h:1021
const Path * path() const
Module path of a use; module name of an import/plugin.
Definition ast.h:1023
Base class of all declarations that bind values.
Definition ast.h:293
const Mods & mods() const
Definition ast.h:303
Vis vis() const override
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
Definition ast.h:300
const Expr * type() const
nullptr if omitted.
Definition ast.h:753
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:180
auto ctors() const
Definition ast.h:767
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:185
const Ctor * ctor(size_t i) const
Definition ast.h:768
size_t num_ctors() const
Definition ast.h:769
Definition ast.h:16
static void stream_decls(fe::Tab &tab, std::ostream &os, fe::View< Ptr< ValDecl > > decls)
Definition stream.cpp:263
static std::string_view vis2str(Vis vis)
Definition stream.cpp:238
Vis
Visibility tier of a ValDecl.
Definition ast.h:42
static bool is_block(const Expr *expr)
Does expr span several statements and hence deserve an indented block of its own?
Definition stream.cpp:347
static std::string escape_char(char8_t c)
Definition stream.cpp:116
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:27
Tok::Tag Tag
Definition bind.cpp:11
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:56
bool is_anx
Definition ast.h:59
Vis resolved_vis() const
Definition ast.h:63
bool is_extern
Definition ast.h:58
Vis default_vis() const
extern/anx nudge the default visibility to Pub unless priv is given explicitly.
Definition ast.h:62
fe::Tab & tab
Definition stream.cpp:38
std::string_view sep
Definition stream.cpp:40
friend std::ostream & operator<<(std::ostream &os, const R &r)
Definition stream.cpp:42
fe::View< Ptr< T > > range
Definition stream.cpp:39
R(fe::Tab &tab, fe::View< Ptr< T > > range, std::string_view sep=", ")
Definition stream.cpp:33
fe::Tab & tab
Definition stream.cpp:16
friend std::ostream & operator<<(std::ostream &os, const S &s)
Definition stream.cpp:19
S(fe::Tab &tab, const Node *node)
Definition stream.cpp:12
const Node * node
Definition stream.cpp:17