MimIR
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 : Node(loc)
16 , dbg_(dbg)
17 , tag_(tag)
18 , module_(std::move(module)) {}
19
20Import::~Import() = default;
21
23 if (!dbg || dbg.sym()[0] != '%') return nullptr;
24
25 auto [plugin_s, tag_s, sub_s] = Annex::split(driver(), dbg.sym());
26 auto plugin_tag = driver().sym("%"s + plugin_s.str() + "."s + tag_s.str());
27 auto& sym2annex = plugin2sym2annex_[plugin_s];
28 auto tag_id = sym2annex.size();
29
30 if (plugin_s == sym_error()) error(dbg.loc(), "plugin name '{}' is reserved", dbg);
31 if (tag_id > std::numeric_limits<tag_t>::max())
32 error(dbg.loc(), "exceeded maxinum number of annexes in current plugin");
33
34 if (!Annex::mangle(plugin_s)) {
35 error(dbg.loc(), "invalid annex name '{}'", dbg);
36 plugin_s = sym_error();
37 }
38
39 auto sub = (tag_t)sym2annex.size();
40 auto [i, fresh] = sym2annex.try_emplace(plugin_tag, AnnexInfo{plugin_s, tag_s, sub});
41 auto annex = &i->second;
42
43 if (sub_s) {
44 if (sub_id) {
45 *sub_id = annex->subs.size();
46 auto& aliases = annex->subs.emplace_back();
47 aliases.emplace_back(sub_s);
48 } else {
49 error(dbg.loc(), "annex '{}' must not have a subtag", dbg);
50 }
51 }
52
53 if (!fresh) annex->fresh = false;
54 return annex;
55}
56
57void AST::bootstrap(Sym plugin, std::ostream& h) {
58 auto tab = fe::Tab::spaces();
59 std::println(h, "{}#pragma once\n", tab);
60 std::println(h, "{}#include <mim/axm.h>", tab);
61 std::println(h, "#include <mim/plugin.h>\n", tab);
62 std::println(h, "{}/// @namespace mim::plug::{} @ref {} ", tab, plugin, plugin);
63 std::println(h, "{}namespace mim {{", tab);
64 std::println(h, "{}namespace plug::{} {{\n", tab, plugin);
65
66 plugin_t plugin_id = *Annex::mangle(plugin);
67 std::vector<std::ostringstream> normalizers, outer_namespace;
68
69 std::println(h, "{}static constexpr plugin_t Plugin_Id = 0x{:x};\n", tab, plugin_id);
70
71 const auto& unordered = plugin2annexes(plugin);
72 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
73 std::ranges::sort(infos, [&](const auto& p1, const auto& p2) { return p1.second.id.tag < p2.second.id.tag; });
74
75 // clang-format off
76 for (const auto& [key, annex] : infos) {
77 const auto& sym = annex.sym;
78 if (sym.plugin != plugin) continue; // this is from an import
79
80 std::println(h, "{}/// @name %%{}.{}\n///@{{", tab, plugin, sym.tag);
81 std::println(h, "{}enum class {} : flags_t {{", tab, sym.tag);
82 ++tab;
83 flags_t ax_id = annex.base();
84
85 auto& os = outer_namespace.emplace_back();
86 std::print(os, "template<> constexpr flags_t Annex::Base<plug::{}::{}> = 0x{:x};\n", plugin, sym.tag, ax_id);
87
88 if (auto& subs = annex.subs; !subs.empty()) {
89 for (const auto& aliases : subs) {
90 auto id = ax_id++;
91 for (const auto alias : aliases)
92 std::println(h, "{}{} = 0x{:x},", tab, alias, id);
93
94 if (auto norm = annex.normalizer) {
95 auto sub = aliases.front();
96 auto& os = normalizers.emplace_back();
97 std::print(os, "normalizers[flags_t({}::{})] = &{}<{}::{}>;", sym.tag, sub, norm, sym.tag, sub);
98 }
99 }
100 } else {
101 if (auto norm = annex.normalizer)
102 std::print(normalizers.emplace_back(), "normalizers[flags_t(Annex::Base<{}>)] = &{};", sym.tag, norm);
103 }
104 --tab;
105 std::println(h, "{}}};\n", tab);
106
107 std::println(outer_namespace.emplace_back(), "template<> constexpr size_t Annex::Num<plug::{}::{}> = {};", plugin, sym.tag, annex.subs.size());
108
109 if (auto norm = annex.normalizer) {
110 if (auto& subs = annex.subs; !subs.empty()) {
111 std::println(h, "{}template<{}>\nconst Def* {}(const Def*, const Def*, const Def*);\n", tab, sym.tag,
112 norm);
113 } else {
114 std::println(h, "{}const Def* {}(const Def*, const Def*, const Def*);", tab, norm);
115 }
116 }
117 std::println(h, "{}///@}}\n", tab);
118 }
119 // clang-format on
120
121 if (!normalizers.empty()) {
122 std::println(h, "{}void register_normalizers(Normalizers& normalizers);\n", tab);
123 std::println(h, "{}#define MIM_{}_NORMALIZER_IMPL \\", tab, plugin);
124 ++tab;
125 std::println(h, "{}void register_normalizers(Normalizers& normalizers) {{\\", tab);
126 ++tab;
127 for (const auto& normalizer : normalizers)
128 std::println(h, "{}{} \\", tab, normalizer.str());
129 --tab;
130 std::println(h, "{}}}", tab);
131 --tab;
132 }
133
134 std::println(h, "{}}} // namespace plug::{}\n", tab, plugin);
135
136 std::println(h, "{}#ifndef DOXYGEN // don't include in Doxygen documentation\n", tab);
137 for (const auto& line : outer_namespace)
138 std::print(h, "{}{}", tab, line.str());
139 std::println(h, "{}", tab);
140
141 // emit helpers for non-function axm
142 for (const auto& [tag, ax] : infos) {
143 auto sym = ax.sym;
144 if ((ax.pi && *ax.pi) || sym.plugin != plugin) continue; // from function or other plugin?
145 std::println(h, "{}template<> struct Axm::IsANode<plug::{}::{}> {{ using type = Axm; }};", tab, sym.plugin,
146 sym.tag);
147 }
148
149 std::println(h, "{}\n#endif", tab);
150 std::println(h, "{}}} // namespace mim\n", tab);
151
152 std::println(h, "{}#ifndef DOXYGEN // don't include in Doxygen documentation\n", tab);
153 for (const auto& [key, annex] : infos) {
154 if (!annex.subs.empty()) {
155 auto sym = annex.sym;
156 std::println(h, "{}template<> struct fe::is_bit_enum<mim::plug::{}::{}> : std::true_type {{}};", tab,
157 sym.plugin, sym.tag);
158 }
159 }
160
161 std::println(h, "{}\n#endif", tab);
162}
163
164void AST::bootstrap_py(Sym plugin, std::ostream& h) {
165 fe::Tab tab;
166 plugin_t plugin_id = *Annex::mangle(plugin);
167
168 std::print(h, "from enum import IntEnum\n\n");
169 std::println(h, "class {}(IntEnum):", plugin);
170 ++tab;
171 std::println(h, "{}ID = 0x{:x}", tab, plugin_id);
172 std::vector<mim::ast::AnnexInfo> annexes_with_subs;
173
174 const auto& unordered = plugin2annexes(plugin);
175 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
176 std::ranges::sort(infos, [&](const auto& p1, const auto& p2) { return p1.second.id.tag < p2.second.id.tag; });
177 for (const auto& [key, annex] : infos) {
178 const auto& sym = annex.sym;
179 if (sym.plugin != plugin) continue;
180
181 flags_t ax_id = annex.base();
182
183 if (auto& subs = annex.subs; subs.empty())
184 std::println(h, "{}{} = 0x{:x}", tab, sym.tag, ax_id);
185 else
186 annexes_with_subs.push_back(annex);
187 }
188 std::print(h, "\n");
189
190 if (!annexes_with_subs.empty()) {
191 for (const auto& annex : annexes_with_subs) {
192 flags_t ax_id = annex.base();
193 std::println(h, "class _{}_{}(IntEnum):", plugin, annex.sym.tag);
194 ++tab;
195
196 for (const auto& aliases : annex.subs) {
197 auto id = ax_id++;
198 for (const auto alias : aliases)
199 std::println(h, "{}{} = 0x{:x}", tab, alias, id);
200 }
201
202 --tab;
203 std::println(h, "\n{}.{} = _{}_{}\n", plugin, annex.sym.tag, plugin, annex.sym.tag);
204 }
205 }
206}
207
208/*
209 * Other
210 */
211
213 : Expr(lam->loc())
214 , lam_(std::move(lam)) {}
215
216/*
217 * Ptrn::to_expr/to_ptrn
218 */
219
221 if (auto idp = ptrn->isa<IdPtrn>(); idp && !idp->dbg() && idp->type()) {
222 if (auto ide = idp->type()->isa<IdExpr>()) return ast.ptr<IdExpr>(ide->dbg());
223 } else if (auto tuple = ptrn->isa<TuplePtrn>(); tuple && tuple->is_brckt()) {
224 (void)ptrn.release();
225 return ast.ptr<SigmaExpr>(Ptr<TuplePtrn>(tuple));
226 }
227 return {};
228}
229
231 if (auto sigma = expr->isa<SigmaExpr>())
232 return std::move(const_cast<SigmaExpr*>(sigma)->ptrn_); // TODO get rid off const_cast
233 return {};
234}
235
236void Module::compile(AST& ast) const {
237 bind(ast);
238 ast.error().ack();
239 emit(ast);
240 if (ast.error().num_warnings() != 0) std::cerr << ast.error();
241}
242
243AST load_plugins(World& world, View<Sym> plugins) {
244 auto tag = world.driver().flags().bootstrap ? Tok::Tag::K_import : Tok::Tag::K_plugin;
245 auto ast = AST(world);
246 auto parser = Parser(ast);
247 auto imports = Ptrs<Import>();
248
249 for (auto plugin : plugins)
250 if (auto mod = parser.import(plugin.view(), tag))
251 imports.emplace_back(ast.ptr<Import>(mod->loc(), tag, Dbg(plugin), std::move(mod)));
252
253 if (!plugins.empty()) {
254 auto mod = ast.ptr<Module>(imports.front()->loc() + imports.back()->loc(), std::move(imports), Ptrs<ValDecl>());
255 mod->compile(ast);
256 }
257
258 return ast;
259}
260
261} // namespace mim::ast
Flags & flags()
Definition driver.h:34
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
const Driver & driver() const
Definition world.h:93
Driver & driver()
Definition ast.h:68
AnnexInfo * name2annex(Dbg dbg, sub_t *)
Definition ast.cpp:22
void bootstrap_py(Sym plugin, std::ostream &h)
Definition ast.cpp:164
const auto & plugin2annexes(Sym plugin)
Definition ast.h:100
void bootstrap(Sym plugin, std::ostream &h)
Definition ast.cpp:57
Error & error()
Definition ast.h:69
Sym sym(const char *s)
Definition ast.h:75
Sym sym_error()
"_error_".
Definition ast.h:80
Expr(Loc loc)
Definition ast.h:145
dbg: type
Definition ast.h:213
Dbg dbg() const
Definition ast.h:220
Import(Loc loc, Tok::Tag tag, Dbg dbg, Ptr< Module > &&module)
Definition ast.cpp:14
Dbg dbg() const
Definition ast.h:1095
Tok::Tag tag() const
Definition ast.h:1096
const Module * module() const
Definition ast.h:1097
LamExpr(Ptr< LamDecl > &&lam)
Definition ast.cpp:212
const LamDecl * lam() const
Definition ast.h:644
void emit(AST &) const
Definition emit.cpp:38
void bind(AST &) const
Definition bind.cpp:77
void compile(AST &) const
Definition ast.cpp:236
Loc loc() const
Definition ast.h:134
Node(Loc loc)
Definition ast.h:129
Parses Mim code as AST.
Definition parser.h:30
static Ptr< Ptrn > to_ptrn(Ptr< Expr > &&)
Definition ast.cpp:230
static Ptr< Expr > to_expr(AST &, Ptr< Ptrn > &&)
Definition ast.cpp:220
Just wraps TuplePtrn as Expr.
Definition ast.h:710
(ptrn_0, ..., ptrn_n-1), [ptrn_0, ..., ptrn_n-1], or {ptrn_0, ..., ptrn_n-1}
Definition ast.h:286
bool is_brckt() const
Definition ast.h:296
Definition ast.h:14
fe::Arena::Ptr< const T > Ptr
Definition ast.h:22
AST load_plugins(World &, View< Sym >)
Definition ast.cpp:243
std::deque< Ptr< T > > Ptrs
Definition ast.h:24
u8 sub_t
Definition types.h:42
u64 flags_t
Definition types.h:39
Span< const T, N > View
Definition span.h:98
bool bootstrap
Definition flags.h:15
u64 plugin_t
Definition types.h:40
u8 tag_t
Definition types.h:41
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