MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
ast.h
Go to the documentation of this file.
1#pragma once
2
3#include <deque>
4#include <memory>
5#include <tuple>
6
7#include <fe/arena.h>
8#include <fe/assert.h>
9#include <fe/cast.h>
10#include <fe/vla.h>
11
12#include "mim/driver.h"
13
14#include "mim/ast/tok.h"
15
16namespace mim::ast {
17
18class Decl;
19class Expr;
20class LamDecl;
21class File;
22class Scopes;
23class Emitter;
24
25/// Nodes live in the AST's Arena and are never destroyed, so this merely points at one.
26template<class T>
27using Ptr = fe::Arena::Ref<const T>;
28
29/// @name Ptrs/Dbgs
30/// Scratch buffers the Parser fills before it creates a node; a node keeps its own lists right
31/// behind itself - see fe::VLA - and hands them out as a fe::View.
32///@{
33template<class T>
34using Ptrs = fe::Vector<Ptr<T>>;
35using Dbgs = fe::Vector<Dbg>;
36///@}
37
38/// Visibility tier of a ValDecl.
39/// `Priv` is only visible inside its enclosing `mod`; `Pub` is visible via a path/`use` from outside.
40/// Orthogonal to this, a ValDecl may independently be `extern` (Decl::is_extern) and/or `anx` (Decl::is_anx);
41/// either one nudges the default visibility to `Pub` unless `priv` is given explicitly.
42enum class Vis { Priv, Pub };
43
44/// One name in a Scope: the Decl it introduces and the Vis of *this* binding.
45/// A splicing UseDecl re-binds someone else's Decl under its own Vis, so Vis belongs here and not to the Decl.
46struct Bind {
47 const Decl* decl;
49};
50
51using Scope = fe::SymMap<Bind>; ///< Maps a name to the Binding introducing it.
52
53/// Raw, unvalidated combination of `priv`/`pub`/`extern`/`anx` modifiers written before a declaration.
54/// Parser::parse_modifiers only rejects a modifier being repeated (`priv priv`, `extern extern`, ...);
55/// whether a given combination makes sense for the decl that follows is up to that decl's own parser.
56struct Mods {
57 std::optional<Vis> vis = {};
58 bool is_extern = false;
59 bool is_anx = false;
60
61 /// `extern`/`anx` nudge the default visibility to `Pub` unless `priv` is given explicitly.
62 Vis default_vis() const { return (is_extern || is_anx) ? Vis::Pub : Vis::Priv; }
63 Vis resolved_vis() const { return vis.value_or(default_vis()); }
64 bool any() const { return vis || is_extern || is_anx; }
65 /// @p group's modifiers as defaults, so an explicit `priv`/`pub` here overrides the group's.
66 Mods inherit(const Mods& group) const {
67 return {vis ? vis : group.vis, is_extern || group.is_extern, is_anx || group.is_anx};
68 }
69};
70
71/// Bookkeeping of an annex introduced by an AxmDecl.
72struct AnnexInfo {
73 AnnexInfo(Sym sym_plugin, Sym sym_tag, tag_t id_tag)
74 : sym{sym_plugin, sym_tag}
75 , id{id_tag} {}
76
77 /// The mangled `plugin` part of the flags.
78 /// Derived from sym.plugin which is guaranteed mangleable by the time an AnnexInfo exists.
79 plugin_t plugin_id() const { return *Annex::mangle(sym.plugin); }
80 /// The base flags (`plugin` + `tag`, no `sub`).
81 flags_t base() const { return Annex::flags(plugin_id(), id.tag); }
82 /// Fully-qualified `plugin.tag[.sub]` name for @p own (this decl's own Dbg::sym), registered for
83 /// by-name lookups (e.g. `compile.named`); @p own == sym.tag (no enclosing `mod`) omits the `.sub` part.
84 Sym qualified(Driver& driver, Sym own) const {
85 auto base = sym.plugin.str() + "." + sym.tag.str();
86 return driver.sym(own == sym.tag ? base : base + "." + own.str());
87 }
88
89 struct {
90 Sym plugin, tag;
91 } sym;
92
93 struct {
94 tag_t tag;
95 } id;
96
97 fe::Vector<fe::Vector<Sym>> subs; ///< List of subs which is a list of aliases.
98 /// The constructor or field names its variant or sigma declares, by index; an unnamed field is the empty Sym.
99 fe::Vector<Sym> names;
100 bool fields = false; ///< Are AnnexInfo::names the fields of a sigma rather than the constructors of a variant?
102 std::optional<bool> pi;
103 bool fresh = true;
104};
105
106/// Owns the arena all AST nodes live in as well as the AnnexInfo%s of all plugins.
107class AST {
108public:
109 AST(const AST&) = delete;
110 AST(World&);
111 AST(AST&&);
113
114 /// @name Getters
115 ///@{
116 World& world() const { return *world_; }
117 Driver& driver() const { return world().driver(); }
118 Error& error() const { return driver().error(); }
119 ///@}
120
121 /// @name Sym
122 ///@{
123 Sym sym(const char* s) { return driver().sym(s); }
124 Sym sym(std::string_view s) { return driver().sym(s); }
125 Sym sym(const std::string& s) { return driver().sym(s); }
126 Sym sym_return() { return sym("return"); } ///< `"return"`.
127 Sym sym_error() { return sym("_error_"); } ///< `"_error_"`.
128 ///@}
129
130 /// The VLA ranges of a fe::VLA node come **last**, in the order its `VLA_Types` declares them.
131 template<class T, class... Args>
132 auto ptr(Args&&... args) {
133 return arena_.ref<const T>(std::forward<Args>(args)...);
134 }
135
136 /// An Arena-allocated copy of @p range - for the few lists that do not sit behind a node.
137 template<class R, class T = std::ranges::range_value_t<R>>
138 fe::View<T> copy(const R& range) {
139 auto span = arena_.copy(range);
140 return fe::View<T>(span.data(), span.size());
141 }
142
143 /// A fresh Scope for a ModDecl; owned here, as an AST node never runs a destructor.
144 Scope& scope() { return scopes_.emplace_back(); }
145
146 /// @name Manage Files
147 /// A file is parsed exactly once; AST::file hands out the File every Import of that file shares.
148 ///@{
149 /// The slot of @p src and whether it is fresh; a fresh slot is `nullptr` until the caller fills it in.
150 /// A `nullptr` slot that is *not* fresh is a file still being parsed further up the stack.
151 std::pair<Ptr<File>&, bool> file(const fe::Src* src);
152 ///@}
153
154 /// @name Manage Annex
155 ///@{
156 /// Registers @p dbg as an annex, deriving `plugin`/`tag`/`sub` from @p dbg's source file and @p s's current
157 /// `mod`-nesting (Scopes::mod_depth/Scopes::enclosing_mod); @p sub_id receives @p dbg's `sub` index within its
158 /// tag. `nullptr` if @p dbg is anonymous or nests more than one `mod` deep.
159 /// @p type, if given, is the declared body whose constructor or field names become AnnexInfo::names.
160 AnnexInfo* name2annex(Scopes& s, Dbg dbg, sub_t* sub_id, const Expr* type = nullptr);
161 const auto& plugin2annexes(Sym plugin) { return plugin2sym2annex_[plugin]; }
162
163 /// An `anx` alias in one plugin for an annex of another, e.g. `anx M = core.M;` in `mem`.
165 Sym alias;
168 };
169 void add_foreign_alias(Sym plugin, ForeignAlias alias) { plugin2foreign_aliases_[plugin].emplace_back(alias); }
170 const auto& plugin2foreign_aliases(Sym plugin) { return plugin2foreign_aliases_[plugin]; }
171 ///@}
172
173 /// @name bootstrap
174 ///@{
175 void bootstrap(Sym plugin, std::ostream& h);
176 void bootstrap_py(Sym plugin, std::ostream& h);
177 ///@}
178
179 friend void swap(AST& a1, AST& a2) noexcept {
180 using std::swap;
181 // clang-format off
182 swap(a1.world_, a2.world_ );
183 swap(a1.arena_, a2.arena_ );
184 swap(a1.files_, a2.files_ );
185 swap(a1.scopes_, a2.scopes_);
186 swap(a1.plugin2sym2annex_, a2.plugin2sym2annex_);
187 swap(a1.plugin2foreign_aliases_, a2.plugin2foreign_aliases_);
188 // clang-format on
189 }
190
191private:
192 // Out of line: a container of Ptr<File> would instantiate Arena::Deleter for the still incomplete File.
193 struct Files;
194
195 World* world_ = nullptr;
196 fe::Arena arena_;
197 std::unique_ptr<Files> files_;
198 std::deque<Scope> scopes_;
199 // Inner map must be pointer-stable: name2annex() hands out `AnnexInfo*`s that are cached in AST nodes,
200 // so the elements must not be relocated when further annexes are inserted into the same plugin.
201 std::unordered_map<fe::Sym, std::unordered_map<fe::Sym, AnnexInfo>> plugin2sym2annex_;
202 std::unordered_map<fe::Sym, std::vector<ForeignAlias>> plugin2foreign_aliases_;
203};
204
205/// Base class of all AST nodes.
206class Node : public fe::RuntimeCast<Node> {
207protected:
209 : loc_(loc) {
210 // Loc::operator+ takes src from its left operand, so a hull across two files points outside its own Src.
211 assert((!loc.begin == !loc.end && loc.begin <= loc.end) && "malformed Loc");
212 assert((!loc || !loc.src || (loc.src->contains(loc.begin) && loc.src->contains(loc.end)))
213 && "Loc outside its Src");
214 }
215
216public:
217 Loc loc() const { return loc_; }
218
219 virtual void stream(fe::Tab&, std::ostream&) const = 0;
220 void dump() const;
221
222private:
223 Loc loc_;
224};
225
226/// Base class of all expressions.
227class Expr : public Node {
228protected:
230 : Node(loc) {}
231
232public:
233 /// @name emit
234 /// Each installs this Expr's Loc as World::get_loc, so every Def emitted underneath is blamed on it.
235 ///@{
236 const Def* emit(Emitter&) const;
237 const Def* emit_decl(Emitter&, const Def* type) const;
238 void emit_body(Emitter&, const Def* decl) const;
239 ///@}
240
241 virtual void bind(Scopes&) const = 0;
242
243private:
244 virtual const Def* emit_(Emitter&) const = 0;
245 virtual const Def* emit_decl_(Emitter&, const Def* /*type*/) const { std::unreachable(); }
246 virtual void emit_body_(Emitter&, const Def* /*decl*/) const { std::unreachable(); }
247};
248
249/// Base class of all declarations; caches the emitted Decl::def.
250class Decl : public Node {
251protected:
253 : Node(loc) {}
254
255public:
256 const Def* def() const { return def_; }
257
258 /// The name this Decl introduces; anonymous if it has none.
259 virtual Dbg dbg() const { return Dbg(loc(), Sym()); }
260 /// Non-`nullptr` if this Decl is a module whose members a Path may walk into.
261 virtual const Scope* scope() const { return nullptr; }
262 /// The `(AnnexInfo, sub)` slot this decl registered itself under as an annex; `{nullptr, 0}` if it isn't one.
263 virtual std::pair<AnnexInfo*, sub_t> annex_sub() const { return {nullptr, 0}; }
264 /// A ValDecl's own Vis; `Pub` for anything else (Ptrn, Import, ...), which the `priv`/`pub` system ignores.
265 virtual Vis vis() const { return Vis::Pub; }
266 /// Whether this decl crosses the Mim/native boundary (`extern`); body presence picks which side supplies it.
267 virtual bool is_extern() const { return false; }
268 /// Whether this decl is registered as a compiler-exposed annex (`anx`).
269 virtual bool is_anx() const { return false; }
270
271protected:
272 mutable const Def* def_ = nullptr;
273};
274
275/// `dbg` bound to a Def whose type the binding construct dictates; hence, it carries no annotation.
276class IdDecl : public Decl {
277public:
279 : Decl(dbg.loc())
280 , dbg_(dbg) {}
281
282 Dbg dbg() const override { return dbg_; }
283
284 void bind(Scopes&, bool quiet = false) const;
285 const Def* emit(const Def*) const;
286 void stream(fe::Tab&, std::ostream&) const override;
287
288private:
289 Dbg dbg_;
290};
291
292/// Base class of all declarations that bind values.
293class ValDecl : public Decl {
294protected:
295 ValDecl(Loc loc, Mods mods = {})
296 : Decl(loc)
297 , mods_(mods) {}
298
299public:
300 Vis vis() const override { return mods_.resolved_vis(); }
301 bool is_extern() const override { return mods_.is_extern; }
302 bool is_anx() const override { return mods_.is_anx; }
303 const Mods& mods() const { return mods_; }
304
305 virtual void bind(Scopes&) const = 0;
306 virtual void emit(Emitter&) const = 0;
307
308private:
309 Mods mods_;
310};
311
312/*
313 * Ptrn
314 */
315
316/// Base class of all patterns.
317class Ptrn : public Decl {
318public:
320 : Decl(loc) {}
321
322 virtual bool is_implicit() const { return false; }
323
324 virtual void bind(Scopes&, bool rebind, bool quiet) const = 0;
325 virtual const Def* emit_value(Emitter&, const Def*) const = 0;
326 virtual const Def* emit_type(Emitter&) const = 0;
327
328 /// Ptrn::emit_value on @p def's @p i-th of @p n projections - with this Ptrn's Loc, so the
329 /// projection is blamed on the binder it introduces instead of on the enclosing pattern.
330 const Def* emit_proj(Emitter&, const Def* def, size_t n, size_t i) const;
331
332 [[nodiscard]] static Ptr<Expr> to_expr(AST&, Ptr<Ptrn>);
333};
334
335/// Erroneous pattern.
336class ErrorPtrn : public Ptrn {
337public:
339 : Ptrn(loc) {}
340
341 void bind(Scopes&, bool rebind, bool quiet) const override;
342 const Def* emit_value(Emitter&, const Def*) const override;
343 const Def* emit_type(Emitter&) const override;
344 void stream(fe::Tab&, std::ostream&) const override;
345};
346
347/// `dbg: type`
348class IdPtrn : public Ptrn {
349public:
351 : Ptrn(loc)
352 , dbg_(dbg)
353 , type_(type) {}
354
355 Dbg dbg() const override { return dbg_; }
356 const Expr* type() const { return type_.get(); }
357 std::pair<AnnexInfo*, sub_t> annex_sub() const override { return {annex_, sub_}; }
358 /// Mirrors the enclosing LetDecl::vis/is_anx, since a `let`'s Ptrn - not the LetDecl - is what a Path resolves to.
359 Vis vis() const override { return vis_; }
360 bool is_anx() const override { return anx_; }
361
362 void bind(Scopes&, bool rebind, bool quiet) const override;
363 const Def* emit_value(Emitter&, const Def*) const override;
364 const Def* emit_type(Emitter&) const override;
365 void stream(fe::Tab&, std::ostream&) const override;
366
367private:
368 Dbg dbg_;
369 Ptr<Expr> type_;
370 mutable const Def* emitted_type_ = nullptr;
371 mutable AnnexInfo* annex_ = nullptr;
372 mutable sub_t sub_ = 0;
373 mutable Vis vis_ = Vis::Priv;
374 mutable bool anx_ = false;
375
376 friend class LetDecl;
377 friend class GrpPtrn;
378};
379
380/// `dbg_i` of a group `dbg_0 ... dbg_n-1: type` for `i > 0`; the leading IdPtrn::id owns `type`.
381class GrpPtrn : public Ptrn {
382public:
383 GrpPtrn(Dbg dbg, const IdPtrn* id)
384 : Ptrn(dbg.loc())
385 , dbg_(dbg)
386 , id_(id) {}
387
388 Dbg dbg() const override { return dbg_; }
389 const IdPtrn* id() const { return id_; }
390
391 void bind(Scopes&, bool rebind, bool quiet) const override;
392 const Def* emit_value(Emitter&, const Def*) const override;
393 const Def* emit_type(Emitter&) const override;
394 void stream(fe::Tab&, std::ostream&) const override;
395
396private:
397 Dbg dbg_;
398 const IdPtrn* id_;
399};
400
401/// `ptrn as dbg`
402class AliasPtrn : public Ptrn {
403public:
405 : Ptrn(loc)
406 , ptrn_(ptrn)
407 , dbg_(dbg) {}
408
409 const Ptrn* ptrn() const { return ptrn_.get(); }
410 Dbg dbg() const override { return dbg_; }
411 bool is_implicit() const override { return ptrn()->is_implicit(); }
412
413 void bind(Scopes&, bool rebind, bool quiet) const override;
414 const Def* emit_value(Emitter&, const Def*) const override;
415 const Def* emit_type(Emitter&) const override;
416 void stream(fe::Tab&, std::ostream&) const override;
417
418private:
419 Ptr<Ptrn> ptrn_;
420 Dbg dbg_;
421};
422
423/// `(ptrn_0, ..., ptrn_n-1)`, `[ptrn_0, ..., ptrn_n-1]`, or `{ptrn_0, ..., ptrn_n-1}`
424class TuplePtrn : public Ptrn, public fe::VLA<TuplePtrn> {
425public:
426 using VLA_Types = std::tuple<Ptr<Ptrn>>;
427
429 : Ptrn(loc)
430 , delim_l_(delim_l) {}
431
432 Tok::Tag delim_l() const { return delim_l_; }
433 Tok::Tag delim_r() const { return Tok::delim_l2r(delim_l()); }
434 bool is_brckt() const { return delim_l() == Tok::Tag::D_brckt_l; }
435 bool is_implicit() const override { return delim_l_ == Tok::Tag::D_brace_l; }
436
437 auto ptrns() const { return vla<0>(); }
438 const Ptrn* ptrn(size_t i) const { return ptrns()[i].get(); }
439 Sym field(size_t i) const; ///< The field name of ptrn(@p i), or the empty Sym if it binds none.
440 size_t num_ptrns() const { return ptrns().size(); }
441
442 void bind(Scopes&, bool rebind, bool quiet) const override;
443 const Def* emit_value(Emitter&, const Def*) const override;
444 const Def* emit_type(Emitter&) const override;
445 const Def* emit_decl(Emitter&, const Def* type) const;
446 const Def* emit_body(Emitter&, const Def* decl) const;
447 void stream(fe::Tab&, std::ostream&) const override;
448
449private:
450 Tok::Tag delim_l_;
451};
452
453/*
454 * Expr
455 */
456
457/// Erroneous expression.
458class ErrorExpr : public Expr {
459public:
461 : Expr(loc) {}
462
463 void bind(Scopes&) const override;
464 void stream(fe::Tab&, std::ostream&) const override;
465
466private:
467 const Def* emit_(Emitter&) const override;
468};
469
470/// `?`
471class HoleExpr : public Expr {
472public:
474 : Expr(loc) {}
475
476 void bind(Scopes&) const override;
477 void stream(fe::Tab&, std::ostream&) const override;
478
479private:
480 const Def* emit_(Emitter&) const override;
481};
482
483/// `dbg_0.....dbg_n-1`.
484class Path : public Node, public fe::VLA<Path> {
485public:
486 using VLA_Types = std::tuple<Dbg>;
487
489 : Node(loc) {}
490
491 auto dbgs() const { return vla<0>(); }
492 Dbg front() const { return dbgs().front(); }
493 Dbg back() const { return dbgs().back(); }
494 const Decl* decl() const { return decl_; }
495
496 void bind(Scopes&, bool quiet = false) const;
497 void stream(fe::Tab&, std::ostream&) const override;
498
499private:
500 mutable const Decl* decl_ = nullptr;
501};
502
503/// `path`
504class PathExpr : public Expr {
505public:
507 : Expr(path->loc())
508 , path_(path) {}
509
510 const Path* path() const { return path_.get(); }
511 Dbg dbg() const { return path_->back(); }
512 const Decl* decl() const { return path_->decl(); }
513
514 void bind(Scopes&) const override;
515 void stream(fe::Tab&, std::ostream&) const override;
516
517private:
518 const Def* emit_(Emitter&) const override;
519
520 Ptr<Path> path_;
521};
522
523/// `tag`
524class PrimaryExpr : public Expr {
525public:
527 : Expr(loc)
528 , tag_(tag) {}
530 : PrimaryExpr(tok.loc(), tok.tag()) {}
531
532 Tok::Tag tag() const { return tag_; }
533
534 void bind(Scopes&) const override;
535 void stream(fe::Tab&, std::ostream&) const override;
536
537private:
538 const Def* emit_(Emitter&) const override;
539
540 Tok::Tag tag_;
541};
542
543/// `tok:type`
544class LitExpr : public Expr {
545public:
547 : Expr(loc)
548 , tok_(tok)
549 , type_(type) {}
550
551 Tok tok() const { return tok_; }
552 Tok::Tag tag() const { return tok_.tag(); }
553 const Expr* type() const { return type_.get(); }
554
555 void bind(Scopes&) const override;
556 void stream(fe::Tab&, std::ostream&) const override;
557
558private:
559 const Def* emit_(Emitter&) const override;
560
561 Tok tok_;
562 Ptr<Expr> type_;
563};
564
565/// `decls expr` or `expr where decls` if DeclExpr::is_where.
566class DeclExpr : public Expr, public fe::VLA<DeclExpr> {
567public:
568 using VLA_Types = std::tuple<Ptr<ValDecl>>;
569
571 : Expr(loc)
572 , expr_(expr)
573 , is_where_(is_where) {}
574
575 auto decls() const { return vla<0>(); }
576 bool is_where() const { return is_where_; }
577 const Expr* expr() const { return expr_.get(); }
578
579 void bind(Scopes&) const override;
580 void stream(fe::Tab&, std::ostream&) const override;
581
582private:
583 const Def* emit_(Emitter&) const override;
584
585 Ptr<Expr> expr_;
586 bool is_where_;
587};
588
589/// `Type level`
590class TypeExpr : public Expr {
591public:
593 : Expr(loc)
594 , level_(level) {}
595
596 const Expr* level() const { return level_.get(); }
597
598 void bind(Scopes&) const override;
599 void stream(fe::Tab&, std::ostream&) const override;
600
601private:
602 const Def* emit_(Emitter&) const override;
603
604 Ptr<Expr> level_;
605};
606
607/// `Rule dom`
608class RuleExpr : public Expr {
609public:
611 : Expr(loc)
612 , dom_(dom) {}
613
614 const Expr* dom() const { return dom_.get(); }
615
616 void bind(Scopes&) const override;
617 void stream(fe::Tab&, std::ostream&) const override;
618
619private:
620 const Def* emit_(Emitter&) const override;
621
622 Ptr<Expr> dom_;
623};
624
625// prefix/infix
626
627/// `op rhs`; PrefixExpr::op picks the meaning - see MIM_PREFIX.
628class PrefixExpr : public Expr {
629public:
631 : Expr(loc)
632 , op_(op)
633 , rhs_(rhs) {}
634
635 Tok op() const { return op_; }
636 const Expr* rhs() const { return rhs_.get(); }
637
638 void bind(Scopes&) const override;
639 void stream(fe::Tab&, std::ostream&) const override;
640
641private:
642 const Def* emit_(Emitter&) const override;
643
644 Tok op_;
645 Ptr<Expr> rhs_;
646};
647
648/// `lhs op rhs`; InfixExpr::op picks the meaning - see MIM_INFIX.
649class InfixExpr : public Expr {
650public:
651 /// @p callee is the `` `op `` a MIM_INFIX_SUGAR operator desugars to and `nullptr` for MIM_INFIX_CORE.
653 : Expr(loc)
654 , lhs_(lhs)
655 , op_(op)
656 , rhs_(rhs)
657 , callee_(callee) {}
658
659 const Expr* lhs() const { return lhs_.get(); }
660 Tok op() const { return op_; }
661 const Expr* rhs() const { return rhs_.get(); }
662 const Expr* callee() const { return callee_.get(); }
663
664 /// @returns @p expr if it is an InfixExpr whose operator is @p tag.
665 static const InfixExpr* isa_op(Tok::Tag tag, const Expr* expr) {
666 auto infix = expr->isa<InfixExpr>();
667 return infix && infix->op().isa(tag) ? infix : nullptr;
668 }
669
670 void bind(Scopes&) const override;
671 void stream(fe::Tab&, std::ostream&) const override;
672
673private:
674 /// Resolves this `#`'s index against @p tup - a simple path may name a field of tup's Sigma.
675 const Def* emit_index(Emitter&, const Def* tup) const;
676
677 const Def* emit_(Emitter&) const override;
678 const Def* emit_decl_(Emitter&, const Def* type) const override;
679 void emit_body_(Emitter&, const Def* decl) const override;
680
681 Ptr<Expr> lhs_;
682 Tok op_;
683 Ptr<Expr> rhs_;
684 Ptr<Expr> callee_;
685 mutable Pi* pi_ = nullptr;
686};
687
688/// `match scrutinee with | arm_0 | ... | arm_n-1`
689class MatchExpr : public Expr, public fe::VLA<MatchExpr> {
690public:
691 /// `ptrn => body`, `ctor ptrn => body`, or `index [ptrn] => body` of a MatchExpr.
692 class Arm : public Node {
693 public:
694 Arm(Loc loc, std::optional<nat_t> index, Dbg ctor, Ptr<Ptrn> ptrn, Ptr<Expr> body)
695 : Node(loc)
696 , index_(index)
697 , ctor_(ctor)
698 , ptrn_(ptrn)
699 , body_(body) {}
700
701 const Ptrn* ptrn() const { return ptrn_.get(); }
702 const Expr* body() const { return body_.get(); }
703 /// The case this arm selects by literal index, as in `1 (h, t)`.
704 std::optional<nat_t> index() const { return index_; }
705 /// The constructor in `Cons (h, t)`; a bare `Nil` is an unannotated IdPtrn instead.
706 Dbg ctor() const { return ctor_; }
707
708 virtual void bind(Scopes&) const;
709 /// @p dom is the case's payload type if the scrutinee is a Variant; otherwise ptrn() determines the domain.
710 Lam* emit(Emitter&, const Def* dom = nullptr) const;
711 void stream(fe::Tab&, std::ostream&) const override;
712
713 private:
714 std::optional<nat_t> index_;
715 Dbg ctor_;
716 Ptr<Ptrn> ptrn_;
717 Ptr<Expr> body_;
718 };
719
720 using VLA_Types = std::tuple<Ptr<Arm>>;
721
723 : Expr(loc)
724 , scrutinee_(scrutinee) {}
725
726 const Expr* scrutinee() const { return scrutinee_.get(); }
727 auto arms() const { return vla<0>(); }
728 const Arm* arm(size_t i) const { return arms()[i].get(); }
729 size_t num_arms() const { return arms().size(); }
730
731 void bind(Scopes&) const override;
732 void stream(fe::Tab&, std::ostream&) const override;
733
734private:
735 const Def* emit_(Emitter&) const override;
736 const Def* emit_variant(Emitter&, const Def* scrutinee, const Variant*) const;
737
738 Ptr<Expr> scrutinee_;
739};
740
741/// `| ctor_0: type_0 | ... | ctor_n-1: type_n-1`; a constructor without a type carries `[]`.
742class VariantExpr : public Expr, public fe::VLA<VariantExpr> {
743public:
744 /// `dbg: type` of a VariantExpr.
745 class Ctor : public Node {
746 public:
748 : Node(loc)
749 , dbg_(dbg)
750 , type_(type) {}
751
752 Dbg dbg() const { return dbg_; }
753 const Expr* type() const { return type_.get(); } ///< `nullptr` if omitted.
754
755 void stream(fe::Tab&, std::ostream&) const override;
756
757 private:
758 Dbg dbg_;
759 Ptr<Expr> type_;
760 };
761
762 using VLA_Types = std::tuple<Ptr<Ctor>>;
763
765 : Expr(loc) {}
766
767 auto ctors() const { return vla<0>(); }
768 const Ctor* ctor(size_t i) const { return ctors()[i].get(); }
769 size_t num_ctors() const { return ctors().size(); }
770
771 void bind(Scopes&) const override;
772 void stream(fe::Tab&, std::ostream&) const override;
773
774private:
775 const Def* emit_(Emitter&) const override;
776 const Def* emit_decl_(Emitter&, const Def* type) const override;
777 void emit_body_(Emitter&, const Def* decl) const override;
778 DefVec emit_payloads(Emitter&) const;
779};
780
781// lam
782
783/// `dom → codom`, `Cn dom`, or `Fn dom → codom` depending on PiExpr::tag.
784class PiExpr : public Expr {
785public:
786 /// One `dom` of a PiExpr: `ptrn` with an optional `-> ret` type.
787 class Dom : public Node {
788 public:
790 : Node(loc)
791 , ptrn_(ptrn)
792 , ret_type_(ret_type) {}
793
794 bool is_implicit() const { return ptrn_->is_implicit(); }
795 const Ptrn* ptrn() const { return ptrn_.get(); }
796 const Expr* ret_type() const { return ret_type_.get(); }
797
798 virtual void bind(Scopes&, bool quiet = false) const;
799 virtual void emit_type(Emitter&) const;
800 void stream(fe::Tab&, std::ostream&) const override;
801
802 protected:
803 mutable Pi* decl_ = nullptr;
804 mutable Pi* pi_ = nullptr;
805
806 private:
807 Ptr<Ptrn> ptrn_;
808 Ptr<Expr> ret_type_;
809
810 friend class PiExpr;
811 };
812
813 PiExpr(Loc loc, Tok::Tag tag, Ptr<Dom> dom, Ptr<Expr> codom)
814 : Expr(loc)
815 , tag_(tag)
816 , dom_(dom)
817 , codom_(codom) {}
818
819private:
820 Tok::Tag tag() const { return tag_; }
821 const Dom* dom() const { return dom_.get(); }
822 const Expr* codom() const { return codom_.get(); }
823
824 void bind(Scopes&) const override;
825 void stream(fe::Tab&, std::ostream&) const override;
826
827private:
828 const Def* emit_(Emitter&) const override;
829 const Def* emit_decl_(Emitter&, const Def* type) const override;
830 void emit_body_(Emitter&, const Def* decl) const override;
831
832 Tok::Tag tag_;
833 Ptr<Dom> dom_;
834 Ptr<Expr> codom_;
835};
836
837/// Wraps a LamDecl as Expr.
838class LamExpr : public Expr {
839public:
841
842 const LamDecl* lam() const { return lam_.get(); }
843
844 void bind(Scopes&) const override;
845 void stream(fe::Tab&, std::ostream&) const override;
846
847private:
848 const Def* emit_(Emitter&) const override;
849 const Def* emit_decl_(Emitter&, const Def* type) const override;
850 void emit_body_(Emitter&, const Def* decl) const override;
851
852 Ptr<LamDecl> lam_;
853};
854
855/// `callee arg`
856class AppExpr : public Expr {
857public:
859 : Expr(loc)
860 , callee_(callee)
861 , arg_(arg) {}
862
863 const Expr* callee() const { return callee_.get(); }
864 const Expr* arg() const { return arg_.get(); }
865
866 void bind(Scopes&) const override;
867 void stream(fe::Tab&, std::ostream&) const override;
868
869private:
870 const Def* emit_(Emitter&) const override;
871
872 Ptr<Expr> callee_;
873 Ptr<Expr> arg_;
874};
875
876/// `ret ptrn = callee $ arg; body`
877class RetExpr : public Expr {
878public:
880 : Expr(loc)
881 , ptrn_(ptrn)
882 , callee_(callee)
883 , arg_(arg)
884 , body_(body) {}
885
886 const Ptrn* ptrn() const { return ptrn_.get(); }
887 const Expr* callee() const { return callee_.get(); }
888 const Expr* arg() const { return arg_.get(); }
889 const Expr* body() const { return body_.get(); }
890
891 void bind(Scopes&) const override;
892 void stream(fe::Tab&, std::ostream&) const override;
893
894private:
895 const Def* emit_(Emitter&) const override;
896
897 Ptr<Ptrn> ptrn_;
898 Ptr<Expr> callee_;
899 Ptr<Expr> arg_;
900 Ptr<Expr> body_;
901};
902// tuple
903
904/// Wraps a TuplePtrn as Expr.
905class SigmaExpr : public Expr {
906public:
908 : Expr(ptrn->loc())
909 , ptrn_(ptrn) {}
910
911 const TuplePtrn* ptrn() const { return ptrn_.get(); }
912
913 void bind(Scopes&) const override;
914 void stream(fe::Tab&, std::ostream&) const override;
915
916private:
917 const Def* emit_(Emitter&) const override;
918 const Def* emit_decl_(Emitter&, const Def* type) const override;
919 void emit_body_(Emitter&, const Def* decl) const override;
920
921 Ptr<TuplePtrn> ptrn_;
922};
923
924/// `(elem_0, ..., elem_n-1)`
925class TupleExpr : public Expr, public fe::VLA<TupleExpr> {
926public:
927 using VLA_Types = std::tuple<Ptr<Expr>>;
928
930 : Expr(loc) {}
931
932 auto elems() const { return vla<0>(); }
933 const Expr* elem(size_t i) const { return elems()[i].get(); }
934 size_t num_elems() const { return elems().size(); }
935
936 void bind(Scopes&) const override;
937 void stream(fe::Tab&, std::ostream&) const override;
938
939private:
940 const Def* emit_(Emitter&) const override;
941};
942
943/// `«index: shape; body»` or `‹index: shape; body›` if SeqExpr::is_pack; `index: ` is optional.
944class SeqExpr : public Expr {
945public:
947 : Expr(loc)
948 , is_pack_(is_pack)
949 , index_(index)
950 , shape_(shape)
951 , body_(body) {}
952
953 bool is_pack() const { return is_pack_; }
954 const IdDecl* index() const { return index_.get(); }
955 const Expr* shape() const { return shape_.get(); }
956 const Expr* body() const { return body_.get(); }
957
958 void bind(Scopes&) const override;
959 void stream(fe::Tab&, std::ostream&) const override;
960
961private:
962 const Def* emit_(Emitter&) const override;
963
964 bool is_pack_;
965 Ptr<IdDecl> index_;
966 Ptr<Expr> shape_;
967 Ptr<Expr> body_;
968};
969
970/// `«body»` or `‹body›` if SingleExpr::is_wrap.
971class SingleExpr : public Expr {
972public:
974 : Expr(loc)
975 , is_wrap_(is_wrap)
976 , body_(body) {}
977
978 bool is_wrap() const { return is_wrap_; }
979 const Expr* body() const { return body_.get(); }
980
981 void bind(Scopes&) const override;
982 void stream(fe::Tab&, std::ostream&) const override;
983
984private:
985 const Def* emit_(Emitter&) const override;
986
987 bool is_wrap_;
988 Ptr<Expr> body_;
989};
990
991/*
992 * Decls
993 */
994
995/// `import "file"|name [as alias|*];`, `plugin name [as alias|*];`, or `use path [as alias|*];`
996/// `as *` splices instead of naming; a `use` without an `as` is sugar for `as *`.
997/// Makes another module available here: `import`/`plugin` pull in a File, `use` walks a Path.
998/// Either that module is bound under UseDecl::dbg, or its public members are spliced into the current scope.
999/// Defaults to `priv`; whatever it binds or splices carries this decl's own Vis, so only `pub` re-exports.
1000class UseDecl : public ValDecl {
1001public:
1002 /// `use path [as alias|*];`; no @p alias means `as *`.
1004 : ValDecl(loc, mods)
1005 , tag_(Tok::Tag::K_use)
1006 , path_(path)
1007 , alias_(alias)
1008 , splice_(!alias) {}
1009
1010 /// `import`/`plugin`; @p name is the module name, derived from @p file_path if there is one.
1011 /// The File itself is owned by the AST and shared by all its importers.
1012 UseDecl(Loc loc, Mods mods, Tok::Tag tag, Ptr<Path> path, Sym file_path, Dbg alias, bool splice, const File* file)
1013 : ValDecl(loc, mods)
1014 , tag_(tag)
1015 , path_(path)
1016 , alias_(alias)
1017 , file_path_(file_path)
1018 , file_(file)
1019 , splice_(splice) {}
1020
1021 Tok::Tag tag() const { return tag_; } ///< `import`, `plugin`, or `use`.
1022 bool is_import() const { return tag_ != Tok::Tag::K_use; }
1023 const Path* path() const { return path_.get(); } ///< Module path of a `use`; module name of an `import`/`plugin`.
1024 Dbg alias() const { return alias_; } ///< Empty, unless the source spelled `as I`.
1025 Sym file_path() const { return file_path_; } ///< Spelling of an `import "..."`; empty otherwise.
1026 bool is_file_path() const { return (bool)file_path_; }
1027 const File* file() const { return file_; }
1028 bool is_splice() const { return splice_; } ///< `as *`: splice the module's public members, bind no name.
1029
1030 /// The name this decl introduces; anonymous if it splices instead.
1031 Dbg dbg() const override { return is_splice() ? Dbg() : alias_ ? alias_ : path_->back(); }
1032
1033 const Scope* scope() const override { return scope_; }
1034 void bind(Scopes&) const override;
1035 void emit(Emitter&) const override;
1036 void stream(fe::Tab&, std::ostream&) const override;
1037
1038private:
1039 /// The module this decl refers to; `nullptr` if it doesn't resolve - the error has already been emitted.
1040 const Scope* module(Scopes&) const;
1041
1042 Tok::Tag tag_;
1043 Ptr<Path> path_;
1044 Dbg alias_;
1045 Sym file_path_;
1046 const File* file_ = nullptr;
1047 bool splice_;
1048 mutable const Scope* scope_ = nullptr;
1049};
1050
1051/// `let ptrn = value;`
1052class LetDecl : public ValDecl {
1053public:
1055 : ValDecl(loc, mods)
1056 , ptrn_(ptrn)
1057 , value_(value) {}
1058
1059 const Ptrn* ptrn() const { return ptrn_.get(); }
1060 const Expr* value() const { return value_.get(); }
1061
1062 void bind(Scopes&) const override;
1063 void emit(Emitter&) const override;
1064 void stream(fe::Tab&, std::ostream&) const override;
1065
1066private:
1067 Ptr<Ptrn> ptrn_;
1068 Ptr<Expr> value_;
1069};
1070
1071/// `axm dbg: type, normalizer, curry, trip;` or a family `axm (name, ...): type, normalizer, curry, trip;`.
1072/// A family prefixed with `tag.` binds as a module and nests its names as subtags of the annex `tag`.
1073class AxmDecl : public ValDecl, public fe::VLA<AxmDecl> {
1074public:
1075 /// `dbg = alias_0 = ... = alias_n-1` - one axiom of the family, which each of its names binds to.
1076 class Name : public Decl, public fe::VLA<Name> {
1077 public:
1078 using VLA_Types = std::tuple<Dbg>;
1079
1081 : Decl(loc) {}
1082
1083 auto names() const { return vla<0>(); }
1084 Dbg dbg() const override { return names().front(); }
1085 auto aliases() const { return names().subspan(1); }
1086 bool is_anx() const override { return true; }
1087 std::pair<AnnexInfo*, sub_t> annex_sub() const override { return {annex_, sub_}; }
1088
1089 void stream(fe::Tab&, std::ostream&) const override;
1090
1091 private:
1092 mutable AnnexInfo* annex_ = nullptr;
1093 mutable sub_t sub_ = 0;
1094
1095 friend class AxmDecl;
1096 };
1097
1098 using VLA_Types = std::tuple<Ptr<Name>>;
1099
1100 AxmDecl(Loc l, Vis v, Dbg mod, Scope* members, bool is_family, Ptr<Expr> type, Dbg normalizer, Tok curry, Tok trip)
1101 : ValDecl(l, Mods{v, /*is_extern=*/false, /*is_anx=*/true})
1102 , mod_(mod)
1103 , members_(members)
1104 , is_family_(is_family)
1105 , type_(type)
1106 , normalizer_(normalizer)
1107 , curry_(curry)
1108 , trip_(trip) {}
1109
1110 /// The `mod.` prefix, if any.
1111 Dbg dbg() const override { return mod_; }
1112 const Scope* scope() const override { return members_; }
1113 auto names() const { return vla<0>(); }
1114 /// Whether the names are spelled as a parenthesized list, even if it is just one.
1115 bool is_family() const { return is_family_; }
1116 const Expr* type() const { return type_.get(); }
1117 Dbg normalizer() const { return normalizer_; }
1118 Tok curry() const { return curry_; }
1119 Tok trip() const { return trip_; }
1120
1121 void bind(Scopes&) const override;
1122 void emit(Emitter&) const override;
1123 void stream(fe::Tab&, std::ostream&) const override;
1124
1125private:
1126 Dbg mod_;
1127 Scope* members_;
1128 bool is_family_;
1129 Ptr<Expr> type_;
1130 Dbg normalizer_;
1131 Tok curry_, trip_;
1132};
1133
1134/// `rec dbg = body;`
1135class RecDecl : public ValDecl {
1136public:
1138 : ValDecl(loc, mods)
1139 , dbg_(dbg)
1140 , body_(body) {}
1141
1142 Dbg dbg() const override { return dbg_; }
1143 const Expr* body() const { return body_.get(); }
1144 /// Only such a body is emitted as a mutable, so only it may refer to the declaration itself.
1145 bool has_mut_body() const;
1146
1147 void bind(Scopes&) const override;
1148 virtual void bind_decl(Scopes&) const;
1149 virtual void bind_body(Scopes&) const;
1150
1151 void emit(Emitter&) const override;
1152 virtual void emit_decl(Emitter&) const;
1153 virtual void emit_body(Emitter&) const;
1154
1155 void stream(fe::Tab&, std::ostream&) const override;
1156 /// Streams this declaration without modifiers and without the trailing `;`.
1157 virtual void stream_(fe::Tab&, std::ostream&) const;
1158 std::pair<AnnexInfo*, sub_t> annex_sub() const override { return {annex_, sub_}; }
1159
1160protected:
1161 mutable AnnexInfo* annex_ = nullptr;
1162 mutable sub_t sub_ = 0;
1163
1164private:
1165 Dbg dbg_;
1166 Ptr<Expr> body_;
1167};
1168
1169/// `nom dbg = body;` - a nominal newtype.
1170class NomDecl : public RecDecl {
1171public:
1174
1175 /// The visibility of this `nom`'s representation: that of the enclosing top-level declaration.
1176 Vis rep_vis() const { return rep_vis_; }
1177
1178 void bind_body(Scopes&) const override;
1179 void emit_decl(Emitter&) const override;
1180 void emit_body(Emitter&) const override;
1181 /// Emits a `nom` without a mutable body as soon as a sibling refers to it; `nullptr` on a cycle.
1182 const Def* emit_ahead(Emitter&) const;
1183 /// Sets @p lam's body to this LamDecl::nom_sugar before emitting the latter's body.
1184 void emit_sugar(Emitter&, Lam* lam) const;
1185 void stream_(fe::Tab&, std::ostream&) const override;
1186
1187private:
1188 void emit_nom(Emitter&, const Def* body) const;
1189
1190 mutable bool emitting_ = false;
1191 mutable Vis rep_vis_ = Vis::Pub;
1192};
1193
1194/// `tag dbg dom_0 ... dom_n-1: codom = body;` with LamDecl::tag `lam`/`con`/`fun` or anonymous `λ`/`cn`/`fn`.
1195class LamDecl : public RecDecl, public fe::VLA<LamDecl> {
1196public:
1197 /// One `dom` of a LamDecl: `ptrn@(filter)` with an optional `: ret` type.
1198 class Dom : public PiExpr::Dom {
1199 public:
1201 : PiExpr::Dom(loc, ptrn, ret_type)
1202 , filter_(filter)
1203 , ret_(ret) {}
1204
1205 const Expr* filter() const { return filter_.get(); }
1206 const IdDecl* ret() const { return ret_.get(); }
1207
1208 void bind(Scopes&, bool quiet = false) const override;
1209 Lam* emit_value(Emitter&) const;
1210 void stream(fe::Tab&, std::ostream&) const override;
1211
1212 private:
1213 Ptr<Expr> filter_;
1214 Ptr<IdDecl> ret_;
1215 mutable Lam* lam_;
1216
1217 friend class LamDecl;
1218 };
1219
1220 using VLA_Types = std::tuple<Ptr<Dom>>;
1221
1223 : RecDecl(loc, mods, dbg, body)
1224 , tag_(tag)
1225 , codom_(codom)
1226 , nom_sugar_(nom_sugar) {}
1227
1228 Tok::Tag tag() const { return tag_; }
1229 auto doms() const { return vla<0>(); }
1230 const Dom* dom(size_t i) const { return doms()[i].get(); }
1231 size_t num_doms() const { return doms().size(); }
1232 const Expr* codom() const { return codom_.get(); }
1233 /// The `nom` of `lam I dom+ = nom I = e; I` if `nom I dom+ = e` desugared to this; within `e`, `I` is this LamDecl.
1234 const NomDecl* nom_sugar() const { return nom_sugar_; }
1235
1236 void bind_decl(Scopes&) const override;
1237 void bind_body(Scopes&) const override;
1238 void emit_decl(Emitter&) const override;
1239 void emit_body(Emitter&) const override;
1240 void stream_(fe::Tab&, std::ostream&) const override;
1241
1242private:
1243 Tok::Tag tag_;
1244 Ptr<Expr> codom_;
1245 const NomDecl* nom_sugar_;
1246};
1247
1248/// `mutual decl* end` groups RecDecl%s that may refer to each other.
1249class MutualDecl : public ValDecl, public fe::VLA<MutualDecl> {
1250public:
1251 using VLA_Types = std::tuple<Ptr<RecDecl>>;
1252
1254 : ValDecl(loc) {}
1255
1256 auto decls() const { return vla<0>(); }
1257
1258 void bind(Scopes&) const override;
1259 void emit(Emitter&) const override;
1260 void stream(fe::Tab&, std::ostream&) const override;
1261};
1262
1263/// `anx dbg = path;` - a compiler-exposed alias sharing its target's annex slot.
1264class AliasDecl : public ValDecl {
1265public:
1267 : ValDecl(loc, Mods{vis, /*is_extern=*/false, /*is_anx=*/true})
1268 , dbg_(dbg)
1269 , path_(path) {}
1270
1271 Dbg dbg() const override { return dbg_; }
1272 const Path* path() const { return path_.get(); }
1273
1274 void bind(Scopes&) const override;
1275 void emit(Emitter&) const override;
1276 void stream(fe::Tab&, std::ostream&) const override;
1277 std::pair<AnnexInfo*, sub_t> annex_sub() const override { return {annex_, sub_}; }
1278
1279private:
1280 Dbg dbg_;
1281 Ptr<Path> path_;
1282 mutable AnnexInfo* annex_ = nullptr;
1283 mutable sub_t sub_ = 0;
1284 mutable Sym foreign_; ///< Qualified name of a ForeignAlias, which is registered in its own plugin.
1285};
1286
1287/// `rule dbg var: lhs when guard => rhs;` or `norm` instead of `rule` if RuleDecl::is_normalizer.
1288class RuleDecl : public ValDecl {
1289public:
1291 : ValDecl(loc, mods)
1292 , dbg_(dbg)
1293 , var_(var)
1294 , lhs_(lhs)
1295 , rhs_(rhs)
1296 , guard_(guard)
1297 , is_norm_(is_norm) {}
1298
1299 Dbg dbg() const override { return dbg_; }
1300 const Ptrn* var() const { return var_.get(); }
1301 const Expr* lhs() const { return lhs_.get(); }
1302 const Expr* rhs() const { return rhs_.get(); }
1303 const Expr* guard() const { return guard_.get(); }
1304 bool is_norm() const { return is_norm_; }
1305
1306 void bind(Scopes&) const override;
1307 void stream(fe::Tab&, std::ostream&) const override;
1308
1309private:
1310 void emit(Emitter&) const override;
1311
1312 Dbg dbg_;
1313 Ptr<Ptrn> var_;
1314 Ptr<Expr> lhs_;
1315 Ptr<Expr> rhs_;
1316 Ptr<Expr> guard_;
1317 bool is_norm_;
1318};
1319
1320/// `mod dbg decls end`; also the base of the anonymous File.
1321class ModDecl : public ValDecl {
1322public:
1323 // A ModDecl is pure AST grouping - it never represents a single value, so it's never `extern`/`anx`.
1325 : ValDecl(loc, Mods{vis})
1326 , dbg_(dbg)
1327 , decls_(decls)
1328 , members_(&members) {}
1329
1330 Dbg dbg() const override { return dbg_; }
1331 auto decls() const { return decls_; }
1332
1333 const Scope* scope() const override { return members_; }
1334 void bind(Scopes&) const override;
1335 void emit(Emitter&) const override;
1336 void stream(fe::Tab&, std::ostream&) const override;
1337
1338protected:
1339 Scope& members() const { return *members_; }
1340 void bind_decls(Scopes&) const;
1341 void emit_decls(Emitter&) const;
1342
1343private:
1344 Dbg dbg_;
1345 fe::View<Ptr<ValDecl>> decls_;
1346 Scope* members_;
1347};
1348
1349/*
1350 * File
1351 */
1352
1353/// The AST of one source file: an anonymous ModDecl that a UseDecl binds under a name of its own.
1354/// Unlike a nested ModDecl, its Scope is a barrier: a file must not see whoever imports it.
1355class File : public ModDecl {
1356public:
1358 : ModDecl(loc, Vis::Priv, Dbg(loc), members, decls) {}
1359
1360 /// Imports the driver was told about via `-p`; they precede everything the file itself declares.
1361 auto implicit_imports() const { return implicit_imports_; }
1362
1363 void add_implicit_imports(fe::View<Ptr<UseDecl>> imports) const { implicit_imports_ = imports; }
1364
1365 void compile(AST&) const;
1366 void bind(AST&) const;
1367 void bind(Scopes&) const override;
1368 void emit(AST&) const;
1369 void emit(Emitter&) const override;
1370 void stream(fe::Tab&, std::ostream&) const override;
1371
1372private:
1373 mutable fe::View<Ptr<UseDecl>> implicit_imports_;
1374 // A file is parsed, bound, and emitted exactly once, no matter how many UseDecls alias it.
1375 mutable bool bound_ = false, emitted_ = false;
1376};
1377
1378AST load_plugins(World&, fe::View<std::string>);
1379inline AST load_plugin(World& w, std::string_view plugin) {
1380 return load_plugins(w, fe::View<std::string>({std::string(plugin)}));
1381}
1382
1383} // namespace mim::ast
Base class for all Defs.
Definition def.h:289
Some "global" variables needed all over the place.
Definition driver.h:64
A function.
Definition lam.h:91
A dependent function type.
Definition lam.h:14
A sum type whose cases are positional: unlike a Join, they are neither sorted nor deduplicated.
Definition union.h:86
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:43
Driver & driver()
Definition world.h:107
Owns the arena all AST nodes live in as well as the AnnexInfos of all plugins.
Definition ast.h:107
Scope & scope()
A fresh Scope for a ModDecl; owned here, as an AST node never runs a destructor.
Definition ast.h:144
friend void swap(AST &a1, AST &a2) noexcept
Definition ast.h:179
fe::View< T > copy(const R &range)
An Arena-allocated copy of range - for the few lists that do not sit behind a node.
Definition ast.h:138
AnnexInfo * name2annex(Scopes &s, Dbg dbg, sub_t *sub_id, const Expr *type=nullptr)
Definition bind.cpp:359
auto ptr(Args &&... args)
The VLA ranges of a fe::VLA node come last, in the order its VLA_Types declares them.
Definition ast.h:132
void bootstrap_py(Sym plugin, std::ostream &h)
Definition ast.cpp:202
World & world() const
Definition ast.h:116
Sym sym(std::string_view s)
Definition ast.h:124
const auto & plugin2annexes(Sym plugin)
Definition ast.h:161
void add_foreign_alias(Sym plugin, ForeignAlias alias)
Definition ast.h:169
void bootstrap(Sym plugin, std::ostream &h)
Definition ast.cpp:66
const auto & plugin2foreign_aliases(Sym plugin)
Definition ast.h:170
Sym sym_return()
"return".
Definition ast.h:126
Error & error() const
Definition ast.h:118
Sym sym(const char *s)
Definition ast.h:123
Driver & driver() const
Definition ast.h:117
AST(const AST &)=delete
const AnnexInfo * annex
Definition ast.h:166
Sym sym_error()
"_error_".
Definition ast.h:127
std::pair< Ptr< File > &, bool > file(const fe::Src *src)
Definition ast.cpp:25
Sym sym(const std::string &s)
Definition ast.h:125
An anx alias in one plugin for an annex of another, e.g. anx M = core.M; in mem.
Definition ast.h:164
void emit(Emitter &) const override
Definition emit.cpp:919
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1271
std::pair< AnnexInfo *, sub_t > annex_sub() const override
The (AnnexInfo, sub) slot this decl registered itself under as an annex; {nullptr,...
Definition ast.h:1277
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:292
void bind(Scopes &) const override
Definition bind.cpp:461
const Path * path() const
Definition ast.h:1272
AliasDecl(Loc loc, Vis vis, Dbg dbg, Ptr< Path > path)
Definition ast.h:1266
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:242
const Def * emit_type(Emitter &) const override
Definition emit.cpp:284
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
AliasPtrn(Loc loc, Ptr< Ptrn > ptrn, Dbg dbg)
Definition ast.h:404
bool is_implicit() const override
Definition ast.h:411
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:181
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:81
void bind(Scopes &) const override
Definition bind.cpp:304
AppExpr(Loc loc, Ptr< Expr > callee, Ptr< Expr > arg)
Definition ast.h:858
const Def * emit_(Emitter &) const override
Definition emit.cpp:774
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
bool is_anx() const override
Whether this decl is registered as a compiler-exposed annex (anx).
Definition ast.h:1086
std::tuple< Dbg > VLA_Types
Definition ast.h:1078
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:1084
auto names() const
Definition ast.h:1083
auto aliases() const
Definition ast.h:1085
friend class AxmDecl
Definition ast.h:1095
std::pair< AnnexInfo *, sub_t > annex_sub() const override
The (AnnexInfo, sub) slot this decl registered itself under as an annex; {nullptr,...
Definition ast.h:1087
void emit(Emitter &) const override
Definition emit.cpp:882
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
AxmDecl(Loc l, Vis v, Dbg mod, Scope *members, bool is_family, Ptr< Expr > type, Dbg normalizer, Tok curry, Tok trip)
Definition ast.h:1100
const Scope * scope() const override
Non-nullptr if this Decl is a module whose members a Path may walk into.
Definition ast.h:1112
Tok curry() const
Definition ast.h:1118
std::tuple< Ptr< Name > > VLA_Types
Definition ast.h:1098
void bind(Scopes &) const override
Definition bind.cpp:413
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
Dbg dbg() const override
The mod. prefix, if any.
Definition ast.h:1111
const Expr * expr() const
Definition ast.h:577
auto decls() const
Definition ast.h:575
DeclExpr(Loc loc, Ptr< Expr > expr, bool is_where)
Definition ast.h:570
const Def * emit_(Emitter &) const override
Definition emit.cpp:445
std::tuple< Ptr< ValDecl > > VLA_Types
Definition ast.h:568
void bind(Scopes &) const override
Definition bind.cpp:247
bool is_where() const
Definition ast.h:576
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:146
Base class of all declarations; caches the emitted Decl::def.
Definition ast.h:250
virtual bool is_anx() const
Whether this decl is registered as a compiler-exposed annex (anx).
Definition ast.h:269
virtual std::pair< AnnexInfo *, sub_t > annex_sub() const
The (AnnexInfo, sub) slot this decl registered itself under as an annex; {nullptr,...
Definition ast.h:263
Decl(Loc loc)
Definition ast.h:252
virtual Vis vis() const
A ValDecl's own Vis; Pub for anything else (Ptrn, Import, ...), which the priv/pub system ignores.
Definition ast.h:265
virtual bool is_extern() const
Whether this decl crosses the Mim/native boundary (extern); body presence picks which side supplies i...
Definition ast.h:267
virtual const Scope * scope() const
Non-nullptr if this Decl is a module whose members a Path may walk into.
Definition ast.h:261
virtual Dbg dbg() const
The name this Decl introduces; anonymous if it has none.
Definition ast.h:259
const Def * def_
Definition ast.h:272
const Def * def() const
Definition ast.h:256
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:112
void bind(Scopes &) const override
Definition bind.cpp:233
ErrorExpr(Loc loc)
Definition ast.h:460
const Def * emit_(Emitter &) const override
Definition emit.cpp:340
const Def * emit_type(Emitter &) const override
Definition emit.cpp:277
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:223
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:171
ErrorPtrn(Loc loc)
Definition ast.h:338
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:80
Base class of all expressions.
Definition ast.h:227
const Def * emit(Emitter &) const
Definition emit.cpp:325
const Def * emit_decl(Emitter &, const Def *type) const
Definition emit.cpp:330
virtual const Def * emit_decl_(Emitter &, const Def *) const
Definition ast.h:245
virtual void bind(Scopes &) const =0
Expr(Loc loc)
Definition ast.h:229
virtual const Def * emit_(Emitter &) const =0
void emit_body(Emitter &, const Def *decl) const
Definition emit.cpp:335
virtual void emit_body_(Emitter &, const Def *) const
Definition ast.h:246
The AST of one source file: an anonymous ModDecl that a UseDecl binds under a name of its own.
Definition ast.h:1355
void add_implicit_imports(fe::View< Ptr< UseDecl > > imports) const
Definition ast.h:1363
void compile(AST &) const
Definition ast.cpp:286
auto implicit_imports() const
Imports the driver was told about via -p; they precede everything the file itself declares.
Definition ast.h:1361
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:74
void bind(AST &) const
Definition bind.cpp:151
File(Loc loc, Scope &members, fe::View< Ptr< ValDecl > > decls)
Definition ast.h:1357
void emit(AST &) const
Definition emit.cpp:188
const Def * emit_type(Emitter &) const override
Definition emit.cpp:287
GrpPtrn(Dbg dbg, const IdPtrn *id)
Definition ast.h:383
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:172
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:240
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:82
const IdPtrn * id() const
Definition ast.h:389
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:388
void bind(Scopes &) const override
Definition bind.cpp:234
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:113
const Def * emit_(Emitter &) const override
Definition emit.cpp:341
HoleExpr(Loc loc)
Definition ast.h:473
dbg bound to a Def whose type the binding construct dictates; hence, it carries no annotation.
Definition ast.h:276
IdDecl(Dbg dbg)
Definition ast.h:278
const Def * emit(const Def *) const
Definition emit.cpp:238
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 bind(Scopes &, bool quiet=false) const
Definition bind.cpp:179
dbg: type
Definition ast.h:348
Vis vis() const override
Mirrors the enclosing LetDecl::vis/is_anx, since a let's Ptrn - not the LetDecl - is what a Path reso...
Definition ast.h:359
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:84
const Def * emit_type(Emitter &) const override
Definition emit.cpp:279
friend class GrpPtrn
Definition ast.h:377
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:174
IdPtrn(Loc loc, Dbg dbg, Ptr< Expr > type)
Definition ast.h:350
friend class LetDecl
Definition ast.h:376
std::pair< AnnexInfo *, sub_t > annex_sub() const override
The (AnnexInfo, sub) slot this decl registered itself under as an annex; {nullptr,...
Definition ast.h:357
Dbg dbg() const override
The name this Decl introduces; anonymous if it has none.
Definition ast.h:355
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:234
const Expr * type() const
Definition ast.h:356
bool is_anx() const override
Whether this decl is registered as a compiler-exposed annex (anx).
Definition ast.h:360
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:460
void bind(Scopes &) const override
Definition bind.cpp:259
static const InfixExpr * isa_op(Tok::Tag tag, const Expr *expr)
Definition ast.h:665
const Expr * callee() const
Definition ast.h:662
const Expr * rhs() const
Definition ast.h:661
const Def * emit_(Emitter &) const override
Definition emit.cpp:571
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:455
const Expr * lhs() const
Definition ast.h:659
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:167
InfixExpr(Loc loc, Ptr< Expr > lhs, Tok op, Ptr< Expr > rhs, Ptr< Expr > callee)
callee is the `op a MIM_INFIX_SUGAR operator desugars to and nullptr for MIM_INFIX_CORE.
Definition ast.h:652
Tok op() const
Definition ast.h:660
One dom of a LamDecl: ptrn@(filter) with an optional : ret type.
Definition ast.h:1198
Lam * emit_value(Emitter &) const
Definition emit.cpp:1013
const Expr * filter() const
Definition ast.h:1205
friend class LamDecl
Definition ast.h:1217
Dom(Loc loc, Ptr< Ptrn > ptrn, Ptr< Expr > filter, Ptr< Expr > ret_type, Ptr< IdDecl > ret)
Definition ast.h:1200
const IdDecl * ret() const
Definition ast.h:1206
tag dbg dom_0 ... dom_n-1: codom = body; with LamDecl::tag lam/con/fun or anonymous λ/cn/fn.
Definition ast.h:1195
Tok::Tag tag() const
Definition ast.h:1228
void bind_body(Scopes &) const override
Definition bind.cpp:583
auto doms() const
Definition ast.h:1229
const Expr * codom() const
Definition ast.h:1232
std::tuple< Ptr< Dom > > VLA_Types
Definition ast.h:1220
LamDecl(Loc loc, Mods mods, Tok::Tag tag, Dbg dbg, Ptr< Expr > codom, Ptr< Expr > body, const NomDecl *nom_sugar)
Definition ast.h:1222
void emit_decl(Emitter &) const override
Definition emit.cpp:1029
size_t num_doms() const
Definition ast.h:1231
void emit_body(Emitter &) const override
Definition emit.cpp:1058
void bind_decl(Scopes &) const override
Definition bind.cpp:553
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
void bind(Scopes &) const override
Definition bind.cpp:299
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:766
const Def * emit_(Emitter &) const override
Definition emit.cpp:768
const LamDecl * lam() const
Definition ast.h:842
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:765
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:212
LamExpr(Ptr< LamDecl > lam)
Definition ast.cpp:268
void bind(Scopes &) const override
Definition bind.cpp:491
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:315
LetDecl(Loc loc, Mods mods, Ptr< Ptrn > ptrn, Ptr< Expr > value)
Definition ast.h:1054
const Expr * value() const
Definition ast.h:1060
const Ptrn * ptrn() const
Definition ast.h:1059
void emit(Emitter &) const override
Definition emit.cpp:942
Tok tok() const
Definition ast.h:551
const Expr * type() const
Definition ast.h:553
const Def * emit_(Emitter &) const override
Definition emit.cpp:423
LitExpr(Loc loc, Tok tok, Ptr< Expr > type)
Definition ast.h:546
Tok::Tag tag() const
Definition ast.h:552
void bind(Scopes &) const override
Definition bind.cpp:238
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:118
ptrn => body, ctor ptrn => body, or index [ptrn] => body of a MatchExpr.
Definition ast.h:692
const Expr * body() const
Definition ast.h:702
Dbg ctor() const
The constructor in Cons (h, t); a bare Nil is an unannotated IdPtrn instead.
Definition ast.h:706
const Ptrn * ptrn() const
Definition ast.h:701
Arm(Loc loc, std::optional< nat_t > index, Dbg ctor, Ptr< Ptrn > ptrn, Ptr< Expr > body)
Definition ast.h:694
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
void bind(Scopes &) const override
Definition bind.cpp:281
const Def * emit_(Emitter &) const override
Definition emit.cpp:698
std::tuple< Ptr< Arm > > VLA_Types
Definition ast.h:720
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
MatchExpr(Loc loc, Ptr< Expr > scrutinee)
Definition ast.h:722
size_t num_arms() const
Definition ast.h:729
void bind_decls(Scopes &) const
Definition bind.cpp:594
void bind(Scopes &) const override
Definition bind.cpp:601
void emit_decls(Emitter &) const
Definition emit.cpp:929
void emit(Emitter &) const override
Definition emit.cpp:936
ModDecl(Loc loc, Vis vis, Dbg dbg, Scope &members, fe::View< Ptr< ValDecl > > decls)
Definition ast.h:1324
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:297
Scope & members() const
Definition ast.h:1339
auto decls() const
Definition ast.h:1331
const Scope * scope() const override
Non-nullptr if this Decl is a module whose members a Path may walk into.
Definition ast.h:1333
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
std::tuple< Ptr< RecDecl > > VLA_Types
Definition ast.h:1251
MutualDecl(Loc loc)
Definition ast.h:1253
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:328
void bind(Scopes &) const override
Definition bind.cpp:511
void emit(Emitter &) const override
Definition emit.cpp:954
virtual void stream(fe::Tab &, std::ostream &) const =0
void dump() const
Definition stream.cpp:63
Loc loc() const
Definition ast.h:217
Node(Loc loc)
Definition ast.h:208
nom dbg = body; - a nominal newtype.
Definition ast.h:1170
void emit_sugar(Emitter &, Lam *lam) const
Sets lam's body to this LamDecl::nom_sugar before emitting the latter's body.
Definition emit.cpp:997
const Def * emit_ahead(Emitter &) const
Emits a nom without a mutable body as soon as a sibling refers to it; nullptr on a cycle.
Definition emit.cpp:992
void bind_body(Scopes &) const override
Definition bind.cpp:542
void emit_body(Emitter &) const override
Definition emit.cpp:980
Vis rep_vis() const
The visibility of this nom's representation: that of the enclosing top-level declaration.
Definition ast.h:1176
NomDecl(Loc loc, Mods mods, Dbg dbg, Ptr< Expr > body)
Definition ast.h:1172
void emit_decl(Emitter &) const override
Definition emit.cpp:974
void stream_(fe::Tab &, std::ostream &) const override
Streams this declaration without modifiers and without the trailing ;.
Definition stream.cpp:326
const Def * emit_(Emitter &) const override
Definition emit.cpp:343
const Path * path() const
Definition ast.h:510
void bind(Scopes &) const override
Definition bind.cpp:230
PathExpr(Ptr< Path > path)
Definition ast.h:506
Dbg dbg() const
Definition ast.h:511
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:111
const Decl * decl() const
Definition ast.h:512
dbg_0.....dbg_n-1.
Definition ast.h:484
auto dbgs() const
Definition ast.h:491
void bind(Scopes &, bool quiet=false) const
Definition bind.cpp:195
std::tuple< Dbg > VLA_Types
Definition ast.h:486
Path(Loc loc)
Definition ast.h:488
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:109
const Decl * decl() const
Definition ast.h:494
Dbg front() const
Definition ast.h:492
Dbg back() const
Definition ast.h:493
One dom of a PiExpr: ptrn with an optional -> ret type.
Definition ast.h:787
virtual void emit_type(Emitter &) const
Definition emit.cpp:729
const Expr * ret_type() const
Definition ast.h:796
Dom(Loc loc, Ptr< Ptrn > ptrn, Ptr< Expr > ret_type)
Definition ast.h:789
friend class PiExpr
Definition ast.h:810
bool is_implicit() const
Definition ast.h:794
const Ptrn * ptrn() const
Definition ast.h:795
const Def * emit_(Emitter &) const override
Definition emit.cpp:757
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:206
void bind(Scopes &) const override
Definition bind.cpp:292
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:751
PiExpr(Loc loc, Tok::Tag tag, Ptr< Dom > dom, Ptr< Expr > codom)
Definition ast.h:813
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:755
Tok op() const
Definition ast.h:635
const Expr * rhs() const
Definition ast.h:636
PrefixExpr(Loc loc, Tok op, Ptr< Expr > rhs)
Definition ast.h:630
const Def * emit_(Emitter &) const override
Definition emit.cpp:523
void bind(Scopes &) const override
Definition bind.cpp:257
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:163
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:114
const Def * emit_(Emitter &) const override
Definition emit.cpp:366
Tok::Tag tag() const
Definition ast.h:532
void bind(Scopes &) const override
Definition bind.cpp:235
PrimaryExpr(Loc loc, Tok::Tag tag)
Definition ast.h:526
PrimaryExpr(Tok tok)
Definition ast.h:529
Base class of all patterns.
Definition ast.h:317
static Ptr< Expr > to_expr(AST &, Ptr< Ptrn >)
Definition ast.cpp:276
virtual void bind(Scopes &, bool rebind, bool quiet) const =0
virtual const Def * emit_value(Emitter &, const Def *) const =0
Ptrn(Loc loc)
Definition ast.h:319
const Def * emit_proj(Emitter &, const Def *def, size_t n, size_t i) const
Ptrn::emit_value on def's i-th of n projections - with this Ptrn's Loc, so the projection is blamed o...
Definition emit.cpp:246
virtual const Def * emit_type(Emitter &) const =0
virtual bool is_implicit() const
Definition ast.h:322
void emit(Emitter &) const override
Definition emit.cpp:949
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:319
virtual void emit_body(Emitter &) const
Definition emit.cpp:967
virtual void bind_body(Scopes &) const
Definition bind.cpp:540
bool has_mut_body() const
Only such a body is emitted as a mutable, so only it may refer to the declaration itself.
Definition bind.cpp:524
virtual void emit_decl(Emitter &) const
Definition emit.cpp:961
virtual void bind_decl(Scopes &) const
Definition bind.cpp:529
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
RecDecl(Loc loc, Mods mods, Dbg dbg, Ptr< Expr > body)
Definition ast.h:1137
const Expr * body() const
Definition ast.h:1143
AnnexInfo * annex_
Definition ast.h:1161
void bind(Scopes &) const override
Definition bind.cpp:506
std::pair< AnnexInfo *, sub_t > annex_sub() const override
The (AnnexInfo, sub) slot this decl registered itself under as an annex; {nullptr,...
Definition ast.h:1158
const Ptrn * ptrn() const
Definition ast.h:886
const Expr * arg() const
Definition ast.h:888
void bind(Scopes &) const override
Definition bind.cpp:309
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:216
const Def * emit_(Emitter &) const override
Definition emit.cpp:780
RetExpr(Loc loc, Ptr< Ptrn > ptrn, Ptr< Expr > callee, Ptr< Expr > arg, Ptr< Expr > body)
Definition ast.h:879
const Expr * body() const
Definition ast.h:889
const Expr * callee() const
Definition ast.h:887
void bind(Scopes &) const override
Definition bind.cpp:646
const Ptrn * var() const
Definition ast.h:1300
const Expr * guard() const
Definition ast.h:1303
bool is_norm() const
Definition ast.h:1304
RuleDecl(Loc loc, Mods mods, Dbg dbg, Ptr< Ptrn > var, Ptr< Expr > lhs, Ptr< Expr > rhs, Ptr< Expr > guard, bool is_norm)
Definition ast.h:1290
const Expr * rhs() const
Definition ast.h:1302
const Expr * lhs() const
Definition ast.h:1301
void emit(Emitter &) const override
Definition emit.cpp:1116
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 bind(Scopes &) const override
Definition bind.cpp:232
RuleExpr(Loc loc, Ptr< Expr > dom)
Definition ast.h:610
const Def * emit_(Emitter &) const override
Definition emit.cpp:361
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
SeqExpr(Loc loc, bool is_pack, Ptr< IdDecl > index, Ptr< Expr > shape, Ptr< Expr > body)
Definition ast.h:946
void bind(Scopes &) const override
Definition bind.cpp:329
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:224
const Def * emit_(Emitter &) const override
Definition emit.cpp:840
const Expr * shape() const
Definition ast.h:955
const TuplePtrn * ptrn() const
Definition ast.h:911
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:808
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:809
const Def * emit_(Emitter &) const override
Definition emit.cpp:810
void bind(Scopes &) const override
Definition bind.cpp:318
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:221
SigmaExpr(Ptr< TuplePtrn > ptrn)
Definition ast.h:907
bool is_wrap() const
Definition ast.h:978
void bind(Scopes &) const override
Definition bind.cpp:337
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:230
SingleExpr(Loc loc, bool is_wrap, Ptr< Expr > body)
Definition ast.h:973
const Def * emit_(Emitter &) const override
Definition emit.cpp:873
const Expr * body() const
Definition ast.h:979
static constexpr Tok::Tag delim_l2r(Tag tag)
Definition tok.h:288
auto elems() const
Definition ast.h:932
const Expr * elem(size_t i) const
Definition ast.h:933
void bind(Scopes &) const override
Definition bind.cpp:324
const Def * emit_(Emitter &) const override
Definition emit.cpp:835
TupleExpr(Loc loc)
Definition ast.h:929
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:222
std::tuple< Ptr< Expr > > VLA_Types
Definition ast.h:927
size_t num_elems() const
Definition ast.h:934
(ptrn_0, ..., ptrn_n-1), [ptrn_0, ..., ptrn_n-1], or {ptrn_0, ..., ptrn_n-1}
Definition ast.h:424
bool is_implicit() const override
Definition ast.h:435
void bind(Scopes &, bool rebind, bool quiet) const override
Definition bind.cpp:186
const Ptrn * ptrn(size_t i) const
Definition ast.h:438
std::tuple< Ptr< Ptrn > > VLA_Types
Definition ast.h:426
Tok::Tag delim_r() const
Definition ast.h:433
const Def * emit_type(Emitter &) const override
Definition emit.cpp:289
const Def * emit_decl(Emitter &, const Def *type) const
Definition emit.cpp:315
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:95
auto ptrns() const
Definition ast.h:437
TuplePtrn(Loc loc, Tok::Tag delim_l)
Definition ast.h:428
size_t num_ptrns() const
Definition ast.h:440
Sym field(size_t i) const
The field name of ptrn(i), or the empty Sym if it binds none.
Definition ast.cpp:263
const Def * emit_value(Emitter &, const Def *) const override
Definition emit.cpp:260
Tok::Tag delim_l() const
Definition ast.h:432
const Def * emit_body(Emitter &, const Def *decl) const
Definition emit.cpp:291
bool is_brckt() const
Definition ast.h:434
const Def * emit_(Emitter &) const override
Definition emit.cpp:356
const Expr * level() const
Definition ast.h:596
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:160
TypeExpr(Loc loc, Ptr< Expr > level)
Definition ast.h:592
void bind(Scopes &) const override
Definition bind.cpp:231
Dbg dbg() const override
The name this decl introduces; anonymous if it splices instead.
Definition ast.h:1031
UseDecl(Loc loc, Mods mods, Ptr< Path > path, Dbg alias)
use path [as alias|*];; no alias means as *.
Definition ast.h:1003
const Scope * scope() const override
Non-nullptr if this Decl is a module whose members a Path may walk into.
Definition ast.h:1033
void emit(Emitter &) const override
Definition emit.cpp:207
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
void bind(Scopes &) const override
Definition bind.cpp:626
bool is_file_path() const
Definition ast.h:1026
UseDecl(Loc loc, Mods mods, Tok::Tag tag, Ptr< Path > path, Sym file_path, Dbg alias, bool splice, const File *file)
import/plugin; name is the module name, derived from file_path if there is one.
Definition ast.h:1012
const File * file() const
Definition ast.h:1027
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
virtual void bind(Scopes &) const =0
ValDecl(Loc loc, Mods mods={})
Definition ast.h:295
const Mods & mods() const
Definition ast.h:303
bool is_extern() const override
Whether this decl crosses the Mim/native boundary (extern); body presence picks which side supplies i...
Definition ast.h:301
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
virtual void emit(Emitter &) const =0
bool is_anx() const override
Whether this decl is registered as a compiler-exposed annex (anx).
Definition ast.h:302
dbg: type of a VariantExpr.
Definition ast.h:745
const Expr * type() const
nullptr if omitted.
Definition ast.h:753
Ctor(Loc loc, Dbg dbg, Ptr< Expr > type)
Definition ast.h:747
auto ctors() const
Definition ast.h:767
void stream(fe::Tab &, std::ostream &) const override
Definition stream.cpp:185
void emit_body_(Emitter &, const Def *decl) const override
Definition emit.cpp:829
const Ctor * ctor(size_t i) const
Definition ast.h:768
void bind(Scopes &) const override
Definition bind.cpp:276
const Def * emit_decl_(Emitter &, const Def *type) const override
Definition emit.cpp:825
const Def * emit_(Emitter &) const override
Definition emit.cpp:819
std::tuple< Ptr< Ctor > > VLA_Types
Definition ast.h:762
size_t num_ctors() const
Definition ast.h:769
VariantExpr(Loc loc)
Definition ast.h:764
Definition ast.h:16
fe::SymMap< Bind > Scope
Maps a name to the Binding introducing it.
Definition ast.h:51
Vis vis
Definition ast.h:48
Vis
Visibility tier of a ValDecl.
Definition ast.h:42
AST load_plugins(World &, fe::View< std::string >)
Definition ast.cpp:293
fe::Vector< Dbg > Dbgs
Definition ast.h:35
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
AST load_plugin(World &w, std::string_view plugin)
Definition ast.h:1379
const Decl * decl
Definition ast.h:47
Tok::Tag Tag
Definition bind.cpp:11
fe::Vector< Ptr< T > > Ptrs
Definition ast.h:34
One name in a Scope: the Decl it introduces and the Vis of this binding.
Definition ast.h:46
u8 sub_t
Definition types.h:42
u64 flags_t
Definition types.h:39
fe::Vector< const Def * > DefVec
Definition def.h:98
u64 plugin_t
Definition types.h:40
u8 tag_t
Definition types.h:41
static constexpr flags_t flags(plugin_t p, tag_t t, sub_t s=0)
Assembles the full flags from its plugin, tag, and sub fields.
Definition plugin.h:266
static std::optional< plugin_t > mangle(std::string_view plugin)
Mangles s into a dense 48-bit representation.
Definition plugin.cpp:9
Bookkeeping of an annex introduced by an AxmDecl.
Definition ast.h:72
Sym qualified(Driver &driver, Sym own) const
Fully-qualified plugin.tag[.sub] name for own (this decl's own Dbg::sym), registered for by-name look...
Definition ast.h:84
struct mim::ast::AnnexInfo::@112046103026102051147230017206327014033073201371 sym
struct mim::ast::AnnexInfo::@177100250272201136376142224053244231100060214216 id
fe::Vector< Sym > names
The constructor or field names its variant or sigma declares, by index; an unnamed field is the empty...
Definition ast.h:99
plugin_t plugin_id() const
The mangled plugin part of the flags.
Definition ast.h:79
AnnexInfo(Sym sym_plugin, Sym sym_tag, tag_t id_tag)
Definition ast.h:73
flags_t base() const
The base flags (plugin + tag, no sub).
Definition ast.h:81
bool fields
Are AnnexInfo::names the fields of a sigma rather than the constructors of a variant?
Definition ast.h:100
std::optional< bool > pi
Definition ast.h:102
fe::Vector< fe::Vector< Sym > > subs
List of subs which is a list of aliases.
Definition ast.h:97
Raw, unvalidated combination of priv/pub/extern/anx modifiers written before a declaration.
Definition ast.h:56
Mods inherit(const Mods &group) const
group's modifiers as defaults, so an explicit priv/pub here overrides the group's.
Definition ast.h:66
bool any() const
Definition ast.h:64
bool is_anx
Definition ast.h:59
Vis resolved_vis() const
Definition ast.h:63
std::optional< Vis > vis
Definition ast.h:57
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