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