19 friend std::ostream&
operator<<(std::ostream& os,
const S& s) {
return s.node->stream(s.tab, os), os; }
26struct std::formatter<
mim::ast::S> : fe::ostream_formatter {};
42 friend std::ostream&
operator<<(std::ostream& os,
const R& r) {
43 for (std::string_view curr_sep{};
const auto& ptr : r.range) {
45 ptr->stream(r.tab, os);
56struct std::formatter<
mim::ast::R<T>> : fe::ostream_formatter {};
64 auto tab = fe::Tab::spaces();
66 std::cout << std::endl;
82void GrpPtrn::stream(fe::Tab& tab, std::ostream& os)
const { std::print(os,
"{}: {}",
dbg(),
S(tab,
id()->type())); }
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; }
90 os <<
"<invalid identifier pattern>";
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());
101 std::print(os,
"{}{}",
S(tab,
ptrn(i)), i + 1 != n ?
", " :
"");
109void Path::stream(fe::Tab&, std::ostream& os)
const { std::print(os,
"{}", fe::Join(
dbgs(),
".")); }
122 if (size == 0 || (size > 1 && std::has_single_bit(size)))
125 std::print(os,
"{}_{}", val, size);
128 case Tag::L_s: os << std::bit_cast<s64>(
tok().lit_u());
break;
129 case Tag::L_u: os <<
tok().
lit_u();
break;
131 auto str = std::format(
"{}", std::bit_cast<f64>(
tok().lit_u()));
133 if (str.find_first_of(
".ein") == std::string::npos) str +=
".0";
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;
140 case Tag::T_top: os <<
tag();
break;
141 default: std::unreachable();
143 if (
type()) std::print(os,
":{}",
S(tab,
type()));
148 std::println(os,
"{} where",
S(tab,
expr()));
152 std::print(os,
"{}end", tab);
154 for (
auto decl :
decls())
155 std::print(os,
"{}\n{}",
S(tab, decl.get()), tab);
156 std::print(os,
"{}",
S(tab,
expr()));
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()));
175 if (ctor_) std::print(os,
"{} ", ctor_);
176 if (
ptrn()) std::print(os,
"{} ",
S(tab,
ptrn()));
177 std::print(os,
"=> {}",
S(tab,
body()));
181 if (
type())
return std::print(os,
"{}: {}",
dbg(),
S(tab,
type()));
182 std::print(os,
"{}",
dbg());
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()));
194 std::print(os,
"match {} with",
S(tab,
scrutinee()));
197 std::print(os,
"\n{}| {}", tab,
S(tab,
arm.get()));
202 std::print(os,
"{}",
S(tab,
ptrn()));
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()));
217 std::println(os,
"ret {} = {} $ {};",
S(tab,
ptrn()),
S(tab,
callee()),
S(tab,
arg()));
218 std::print(os,
"{}{}", tab,
S(tab,
body()));
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() ?
"›" :
"»");
231 std::print(os,
"{}{}{}",
is_wrap() ?
"‹" :
"«",
S(tab,
body()),
is_wrap() ?
"›" :
"»");
249 if (mods.
is_extern) std::print(os,
"extern ");
250 if (mods.
is_anx) std::print(os,
"anx ");
258struct std::formatter<
mim::ast::Mods> : fe::ostream_formatter {};
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()));
280 if (mod_) std::print(os,
"{}.", mod_);
282 std::print(os,
"({})",
R(tab,
names()));
284 std::print(os,
"{}",
S(tab,
names().front().get()));
285 std::print(os,
": {}",
S(tab,
type()));
287 if (
curry()) std::print(os,
", {}",
curry().lit_u());
288 if (
trip()) std::print(os,
", {}",
trip().lit_u());
294 std::print(os,
"anx {} = {};",
dbg(),
S(tab,
path()));
298 std::println(os,
"{}mod {}",
mods(),
dbg());
302 std::print(os,
"{}end", tab);
309 std::print(os,
"{}{} {}",
mods(),
tag(),
S(tab,
path()));
310 if (
alias()) std::print(os,
" as {}",
alias());
316 std::print(os,
"{}let {} = {};",
mods(),
S(tab,
ptrn()),
S(tab,
value()));
320 std::print(os,
"{}",
mods());
331 for (std::string_view sep{};
auto decl :
decls()) {
332 std::println(os,
"{}{}{}", sep, tab,
S(tab, decl.get()));
336 std::print(os,
"{}end", tab);
340 std::print(os,
"{}",
S(tab,
ptrn()));
348 if (
auto decl = expr->isa<
DeclExpr>())
return !decl->is_where();
354 std::print(os,
"nom {}",
dbg());
356 std::print(os,
" {}",
S(tab,
dom.get()));
357 std::print(os,
" = {}",
S(tab, nom->body()));
360 std::print(os,
"{}",
tag());
361 if (
dbg()) std::print(os,
" {}",
dbg());
363 std::print(os,
" {}",
S(tab,
dom.get()));
364 if (
codom()) std::print(os,
": {}",
S(tab,
codom()));
368 std::print(os,
" =\n{}{}", tab,
S(tab,
body()));
371 std::print(os,
" = {}",
S(tab,
body()));
377 std::print(os,
"{}{} {} {}: {}",
mods(),
is_norm() ? Tag::K_norm : Tag::K_rule,
dbg(),
S(tab,
var()),
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()));
static constexpr nat_t size2bitwidth(nat_t n)
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
void stream(fe::Tab &, std::ostream &) const override
const Path * path() const
const Ptrn * ptrn() const
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
const Expr * callee() const
void stream(fe::Tab &, std::ostream &) const override
const Expr * type() const
bool is_family() const
Whether the names are spelled as a parenthesized list, even if it is just one.
void stream(fe::Tab &, std::ostream &) const override
axm is always anx, so only priv is ever printed.
decls expr or expr where decls if DeclExpr::is_where.
const Expr * expr() const
void stream(fe::Tab &, std::ostream &) const override
virtual Dbg dbg() const
The name this Decl introduces; anonymous if it has none.
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
Base class of all expressions.
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
void stream(fe::Tab &, std::ostream &) const override
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
const Expr * type() const
void stream(fe::Tab &, std::ostream &) const override
const Expr * filter() const
void stream(fe::Tab &, std::ostream &) const override
const Expr * codom() const
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,...
const Dom * dom(size_t i) const
void stream_(fe::Tab &, std::ostream &) const override
Streams this declaration without modifiers and without the trailing ;.
const LamDecl * lam() const
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
const Expr * value() const
const Ptrn * ptrn() const
static std::string escape(std::string_view str)
Inverse of Lexer::lex_char: renders str as the body of a Mim string literal.
const Expr * type() const
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
const Expr * body() const
const Ptrn * ptrn() const
std::optional< nat_t > index() const
The case this arm selects by literal index, as in 1 (h, t).
const Expr * scrutinee() const
void stream(fe::Tab &, std::ostream &) const override
const Arm * arm(size_t i) const
void stream(fe::Tab &, std::ostream &) const override
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
void stream(fe::Tab &, std::ostream &) const override
Base class of all AST nodes.
virtual void stream(fe::Tab &, std::ostream &) const =0
void stream_(fe::Tab &, std::ostream &) const override
Streams this declaration without modifiers and without the trailing ;.
const Path * path() const
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
const Expr * ret_type() const
void stream(fe::Tab &, std::ostream &) const override
const Ptrn * ptrn() const
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
virtual void stream_(fe::Tab &, std::ostream &) const
Streams this declaration without modifiers and without the trailing ;.
const Expr * body() const
ret ptrn = callee $ arg; body
const Ptrn * ptrn() const
void stream(fe::Tab &, std::ostream &) const override
const Expr * body() const
const Expr * callee() const
const Expr * guard() const
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
const Expr * body() const
const IdDecl * index() const
void stream(fe::Tab &, std::ostream &) const override
const Expr * shape() const
const TuplePtrn * ptrn() const
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
const Expr * body() const
std::pair< uint64_t, uint64_t > lit_i() const
static const char * tag2str(Tok::Tag)
void stream(fe::Tab &, std::ostream &) const override
const Ptrn * ptrn(size_t i) const
void stream(fe::Tab &, std::ostream &) const override
const Expr * level() const
void stream(fe::Tab &, std::ostream &) const override
import "file"|name [as alias|*];, plugin name [as alias|*];, or use path [as alias|*]; as * splices i...
bool is_splice() const
as *: splice the module's public members, bind no name.
Dbg alias() const
Empty, unless the source spelled as I.
void stream(fe::Tab &, std::ostream &) const override
Sym file_path() const
Spelling of an import "..."; empty otherwise.
bool is_file_path() const
Tok::Tag tag() const
import, plugin, or use.
const Path * path() const
Module path of a use; module name of an import/plugin.
Base class of all declarations that bind values.
const Mods & mods() const
Vis vis() const override
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
const Expr * type() const
nullptr if omitted.
void stream(fe::Tab &, std::ostream &) const override
void stream(fe::Tab &, std::ostream &) const override
const Ctor * ctor(size_t i) const
static void stream_decls(fe::Tab &tab, std::ostream &os, fe::View< Ptr< ValDecl > > decls)
static std::string_view vis2str(Vis vis)
Vis
Visibility tier of a ValDecl.
static bool is_block(const Expr *expr)
Does expr span several statements and hence deserve an indented block of its own?
static std::string escape_char(char8_t c)
fe::Arena::Ref< const T > Ptr
Nodes live in the AST's Arena and are never destroyed, so this merely points at one.
std::ostream & operator<<(std::ostream &os, Tok tok)
Raw, unvalidated combination of priv/pub/extern/anx modifiers written before a declaration.
Vis default_vis() const
extern/anx nudge the default visibility to Pub unless priv is given explicitly.
friend std::ostream & operator<<(std::ostream &os, const R &r)
fe::View< Ptr< T > > range
R(fe::Tab &tab, fe::View< Ptr< T > > range, std::string_view sep=", ")
friend std::ostream & operator<<(std::ostream &os, const S &s)
S(fe::Tab &tab, const Node *node)