MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
ast.cpp
Go to the documentation of this file.
1#include "mim/ast/ast.h"
2
3#include "mim/ast/parser.h"
4
5using namespace std::literals;
6
7namespace mim::ast {
8
10 assert(error().num_errors() == 0 && error().num_warnings() == 0
11 && "please encounter any errors before destroying this class");
12}
13
15 if (!dbg || dbg.sym()[0] != '%') return nullptr;
16
17 auto [plugin_s, tag_s, sub_s] = Annex::split(driver(), dbg.sym());
18 auto plugin_tag = driver().sym("%"s + plugin_s.str() + "."s + tag_s.str());
19 auto& sym2annex = plugin2sym2annex_[plugin_s];
20 auto tag_id = sym2annex.size();
21
22 if (plugin_s == sym_error()) error(dbg.loc(), "plugin name '{}' is reserved", dbg);
23 if (tag_id > std::numeric_limits<tag_t>::max())
24 error(dbg.loc(), "exceeded maxinum number of annexes in current plugin");
25
26 plugin_t plugin_id;
27 if (auto p = Annex::mangle(plugin_s))
28 plugin_id = *p;
29 else {
30 error(dbg.loc(), "invalid annex name '{}'", dbg);
31 plugin_s = sym_error();
32 plugin_id = *Annex::mangle(plugin_s);
33 }
34
35 auto [i, fresh] = sym2annex.emplace(plugin_tag, AnnexInfo{plugin_s, tag_s, plugin_id, (tag_t)sym2annex.size()});
36 auto annex = &i->second;
37
38 if (sub_s) {
39 if (sub_id) {
40 *sub_id = annex->subs.size();
41 auto& aliases = annex->subs.emplace_back();
42 aliases.emplace_back(sub_s);
43 } else {
44 error(dbg.loc(), "annex '{}' must not have a subtag", dbg);
45 }
46 }
47
48 if (!fresh) annex->fresh = false;
49 return annex;
50}
51
52void AST::bootstrap(Sym plugin, std::ostream& h) {
53 Tab tab;
54 tab.print(h, "#pragma once\n\n");
55 tab.print(h, "#include <mim/axm.h>\n"
56 "#include <mim/plugin.h>\n\n");
57
58 tab.print(h, "/// @namespace mim::plug::{} @ref {} \n", plugin, plugin);
59 tab.print(h, "namespace mim {{\n");
60 tab.print(h, "namespace plug::{} {{\n\n", plugin);
61
62 plugin_t plugin_id = *Annex::mangle(plugin);
63 std::vector<std::ostringstream> normalizers, outer_namespace;
64
65 tab.print(h, "static constexpr plugin_t Plugin_Id = 0x{x};\n\n", plugin_id);
66
67 const auto& unordered = plugin2annexes(plugin);
68 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
69 std::ranges::sort(infos, [&](const auto& p1, const auto& p2) { return p1.second.id.tag < p2.second.id.tag; });
70
71 // clang-format off
72 for (const auto& [key, annex] : infos) {
73 const auto& sym = annex.sym;
74 if (sym.plugin != plugin) continue; // this is from an import
75
76 tab.print(h, "/// @name %%{}.{}\n///@{{\n", plugin, sym.tag);
77 tab.print(h, "enum class {} : flags_t {{\n", sym.tag);
78 ++tab;
79 flags_t ax_id = plugin_id | (annex.id.tag << 8u);
80
81 auto& os = outer_namespace.emplace_back();
82 print(os, "template<> constexpr flags_t Annex::Base<plug::{}::{}> = 0x{x};\n", plugin, sym.tag, ax_id);
83
84 if (auto& subs = annex.subs; !subs.empty()) {
85 for (const auto& aliases : subs) {
86 const auto& sub = aliases.front();
87 tab.print(h, "{} = 0x{x},\n", sub, ax_id++);
88 for (size_t i = 1; i < aliases.size(); ++i) tab.print(h, "{} = {},\n", aliases[i], sub);
89
90 if (auto norm = annex.normalizer) {
91 auto& os = normalizers.emplace_back();
92 print(os, "normalizers[flags_t({}::{})] = &{}<{}::{}>;", sym.tag, sub, norm, sym.tag, sub);
93 }
94 }
95 } else {
96 if (auto norm = annex.normalizer)
97 print(normalizers.emplace_back(), "normalizers[flags_t(Annex::Base<{}>)] = &{};", sym.tag, norm);
98 }
99 --tab;
100 tab.print(h, "}};\n\n");
101
102 print(outer_namespace.emplace_back(), "template<> constexpr size_t Annex::Num<plug::{}::{}> = {};\n", plugin, sym.tag, annex.subs.size());
103
104 if (auto norm = annex.normalizer) {
105 if (auto& subs = annex.subs; !subs.empty()) {
106 tab.print(h, "template<{}>\nconst Def* {}(const Def*, const Def*, const Def*);\n\n", sym.tag, norm);
107 } else {
108 tab.print(h, "const Def* {}(const Def*, const Def*, const Def*);\n", norm);
109 }
110 }
111 tab.print(h, "///@}}\n\n");
112 }
113 // clang-format on
114
115 if (!normalizers.empty()) {
116 tab.print(h, "void register_normalizers(Normalizers& normalizers);\n\n");
117 tab.print(h, "#define MIM_{}_NORMALIZER_IMPL \\\n", plugin);
118 ++tab;
119 tab.print(h, "void register_normalizers(Normalizers& normalizers) {{\\\n");
120 ++tab;
121 for (const auto& normalizer : normalizers)
122 tab.print(h, "{} \\\n", normalizer.str());
123 --tab;
124 tab.print(h, "}}\n");
125 --tab;
126 }
127
128 tab.print(h, "}} // namespace plug::{}\n\n", plugin);
129
130 tab.print(h, "#ifndef DOXYGEN // don't include in Doxygen documentation\n\n");
131 for (const auto& line : outer_namespace)
132 tab.print(h, "{}", line.str());
133 tab.print(h, "\n");
134
135 // emit helpers for non-function axm
136 for (const auto& [tag, ax] : infos) {
137 auto sym = ax.sym;
138 if ((ax.pi && *ax.pi) || sym.plugin != plugin) continue; // from function or other plugin?
139 tab.print(h, "template<> struct Axm::IsANode<plug::{}::{}> {{ using type = Axm; }};\n", sym.plugin, sym.tag);
140 }
141
142 tab.print(h, "\n#endif\n");
143 tab.print(h, "}} // namespace mim\n\n");
144
145 tab.print(h, "#ifndef DOXYGEN // don't include in Doxygen documentation\n\n");
146 for (const auto& [key, annex] : infos) {
147 if (!annex.subs.empty()) {
148 auto sym = annex.sym;
149 tab.print(h, "template<> struct fe::is_bit_enum<mim::plug::{}::{}> : std::true_type {{}};\n", sym.plugin,
150 sym.tag);
151 }
152 }
153
154 tab.print(h, "\n#endif\n");
155}
156
157/*
158 * Other
159 */
160
162 : Expr(lam->loc())
163 , lam_(std::move(lam)) {}
164
165/*
166 * Ptrn::to_expr/to_ptrn
167 */
168
170 if (auto idp = ptrn->isa<IdPtrn>(); idp && !idp->dbg() && idp->type()) {
171 if (auto ide = idp->type()->isa<IdExpr>()) return ast.ptr<IdExpr>(ide->dbg());
172 } else if (auto tuple = ptrn->isa<TuplePtrn>(); tuple && tuple->is_brckt()) {
173 (void)ptrn.release();
174 return ast.ptr<SigmaExpr>(Ptr<TuplePtrn>(tuple));
175 }
176 return {};
177}
178
180 if (auto sigma = expr->isa<SigmaExpr>())
181 return std::move(const_cast<SigmaExpr*>(sigma)->ptrn_); // TODO get rid off const_cast
182 return {};
183}
184
185void Module::compile(AST& ast) const {
186 bind(ast);
187 ast.error().ack();
188 emit(ast);
189 if (ast.error().num_warnings() != 0) std::cerr << ast.error();
190}
191
192AST load_plugins(World& world, View<Sym> plugins) {
193 auto tag = Tok::Tag::K_import;
194 if (!world.driver().flags().bootstrap) {
195 for (auto plugin : plugins)
196 world.driver().load(plugin);
197 tag = Tok::Tag::K_plugin;
198 }
199
200 auto ast = AST(world);
201 auto parser = Parser(ast);
202 auto imports = Ptrs<Import>();
203
204 for (auto plugin : plugins)
205 if (auto mod = parser.import(plugin, nullptr))
206 imports.emplace_back(ast.ptr<Import>(mod->loc(), tag, Dbg(plugin), std::move(mod)));
207
208 if (!plugins.empty()) {
209 auto mod = ast.ptr<Module>(imports.front()->loc() + imports.back()->loc(), std::move(imports), Ptrs<ValDecl>());
210 mod->compile(ast);
211 }
212
213 return ast;
214}
215
216} // namespace mim::ast
void load(Sym name)
Definition driver.cpp:45
Flags & flags()
Definition driver.h:23
Keeps track of indentation level.
Definition print.h:206
std::ostream & print(std::ostream &os, const char *s, Args &&... args)
Definition print.h:223
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
const Driver & driver() const
Definition world.h:91
Driver & driver()
Definition ast.h:62
AnnexInfo * name2annex(Dbg dbg, sub_t *)
Definition ast.cpp:14
const auto & plugin2annexes(Sym plugin)
Definition ast.h:94
void bootstrap(Sym plugin, std::ostream &h)
Definition ast.cpp:52
Error & error()
Definition ast.h:63
Sym sym(const char *s)
Definition ast.h:69
Sym sym_error()
"_error_".
Definition ast.h:74
Expr(Loc loc)
Definition ast.h:133
dbg: type
Definition ast.h:217
Dbg dbg() const
Definition ast.h:224
LamExpr(Ptr< LamDecl > &&lam)
Definition ast.cpp:161
const LamDecl * lam() const
Definition ast.h:630
void emit(AST &) const
Definition emit.cpp:38
void bind(AST &) const
Definition bind.cpp:77
void compile(AST &) const
Definition ast.cpp:185
Loc loc() const
Definition ast.h:122
Parses Mim code as AST.
Definition parser.h:30
static Ptr< Ptrn > to_ptrn(Ptr< Expr > &&)
Definition ast.cpp:179
static Ptr< Expr > to_expr(AST &, Ptr< Ptrn > &&)
Definition ast.cpp:169
Just wraps TuplePtrn as Expr.
Definition ast.h:696
(ptrn_0, ..., ptrn_n-1), [ptrn_0, ..., ptrn_n-1], or {ptrn_0, ..., ptrn_n-1}
Definition ast.h:290
bool is_brckt() const
Definition ast.h:300
Definition ast.h:14
fe::Arena::Ptr< const T > Ptr
Definition ast.h:22
AST load_plugins(World &, View< Sym >)
Definition ast.cpp:192
std::deque< Ptr< T > > Ptrs
Definition ast.h:24
u8 sub_t
Definition types.h:48
std::ostream & print(std::ostream &os, const char *s)
Base case.
Definition print.cpp:5
u64 flags_t
Definition types.h:45
Span< const T, N > View
Definition span.h:98
bool bootstrap
Definition flags.h:16
u64 plugin_t
Definition types.h:46
u8 tag_t
Definition types.h:47
Definition span.h:122
static std::tuple< Sym, Sym, Sym > split(Driver &, Sym)
Definition plugin.cpp:58
static std::optional< plugin_t > mangle(Sym plugin)
Mangles s into a dense 48-bit representation.
Definition plugin.cpp:9