brewery
notashelf /
8a093aa9e806dbdbe1adbcbe8e8214fbdd2cf7e2

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git
src/irc/types.hC330 lines9.1 KB
1
#ifndef NIX_IRC_TYPES_H
2
#define NIX_IRC_TYPES_H
3
4
#include <cstdint>
5
#include <memory>
6
#include <optional>
7
#include <string>
8
#include <unordered_map>
9
#include <utility>
10
#include <variant>
11
#include <vector>
12
13
namespace nix_irc {
14
15
constexpr uint32_t IR_MAGIC = 0x4E495258;
16
constexpr uint32_t IR_VERSION = 2;
17
18
enum class NodeType : uint8_t {
19
  CONST_INT = 0x01,
20
  CONST_FLOAT = 0x06,
21
  CONST_STRING = 0x02,
22
  CONST_PATH = 0x03,
23
  CONST_BOOL = 0x04,
24
  CONST_NULL = 0x05,
25
  CONST_URI = 0x07,
26
  CONST_LOOKUP_PATH = 0x08,
27
  VAR = 0x10,
28
  LAMBDA = 0x20,
29
  APP = 0x21,
30
  BINARY_OP = 0x22,
31
  UNARY_OP = 0x23,
32
  IMPORT = 0x24,
33
  ATTRSET = 0x30,
34
  SELECT = 0x31,
35
  HAS_ATTR = 0x34,
36
  WITH = 0x32,
37
  LIST = 0x33,
38
  IF = 0x40,
39
  LET = 0x50,
40
  LETREC = 0x51,
41
  ASSERT = 0x52,
42
  THUNK = 0x60,
43
  FORCE = 0x61,
44
  ERROR = 0xFF
45
};
46
47
enum class BinaryOp : uint8_t {
48
  ADD,
49
  SUB,
50
  MUL,
51
  DIV,
52
  CONCAT,
53
  EQ,
54
  NE,
55
  LT,
56
  GT,
57
  LE,
58
  GE,
59
  AND,
60
  OR,
61
  IMPL,
62
  MERGE
63
};
64
65
enum class UnaryOp : uint8_t { NEG, NOT };
66
67
// Forward declare Node for use in shared_ptr
68
class Node;
69
70
struct ConstIntNode {
71
  int64_t value;
72
  uint32_t line = 0;
73
  ConstIntNode(int64_t v = 0, uint32_t l = 0) : value(v), line(l) {}
74
};
75
76
struct ConstStringNode {
77
  std::string value;
78
  uint32_t line = 0;
79
  ConstStringNode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
80
};
81
82
struct ConstPathNode {
83
  std::string value;
84
  uint32_t line = 0;
85
  ConstPathNode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
86
};
87
88
struct ConstBoolNode {
89
  bool value;
90
  uint32_t line = 0;
91
  ConstBoolNode(bool v = false, uint32_t l = 0) : value(v), line(l) {}
92
};
93
94
struct ConstNullNode {
95
  uint32_t line = 0;
96
  ConstNullNode(uint32_t l = 0) : line(l) {}
97
};
98
99
struct ConstFloatNode {
100
  double value;
101
  uint32_t line = 0;
102
  ConstFloatNode(double v = 0.0, uint32_t l = 0) : value(v), line(l) {}
103
};
104
105
struct ConstURINode {
106
  std::string value;
107
  uint32_t line = 0;
108
  ConstURINode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
109
};
110
111
struct ConstLookupPathNode {
112
  std::string value; // e.g., "nixpkgs" or "nixpkgs/lib"
113
  uint32_t line = 0;
114
  ConstLookupPathNode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
115
};
116
117
struct VarNode {
118
  uint32_t index = 0;
119
  std::optional<std::string> name;
120
  uint32_t line = 0;
121
  VarNode(uint32_t idx = 0, std::string n = "", uint32_t l = 0)
122
      : index(idx), name(n.empty() ? std::nullopt : std::optional<std::string>(n)), line(l) {}
123
};
124
125
struct LambdaNode {
126
  uint32_t arity = 1;
127
  std::shared_ptr<Node> body;
128
  std::optional<std::string> param_name;
129
  bool strict_pattern = true;
130
  uint32_t line = 0;
131
  LambdaNode(uint32_t a, std::shared_ptr<Node> b, uint32_t l = 0);
132
};
133
134
struct AppNode {
135
  std::shared_ptr<Node> func;
136
  std::shared_ptr<Node> arg;
137
  uint32_t line = 0;
138
  AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l = 0);
139
};
140
141
struct BinaryOpNode {
142
  BinaryOp op;
143
  std::shared_ptr<Node> left;
144
  std::shared_ptr<Node> right;
145
  uint32_t line = 0;
146
  BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r, uint32_t ln = 0);
147
};
148
149
struct UnaryOpNode {
150
  UnaryOp op;
151
  std::shared_ptr<Node> operand;
152
  uint32_t line = 0;
153
  UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l = 0);
154
};
155
156
struct AttrBinding {
157
  std::optional<std::string> static_name; // Static key like "foo"
158
  std::shared_ptr<Node> dynamic_name;     // Dynamic key like ${expr}
159
  std::shared_ptr<Node> value;
160
161
  // Static attribute
162
  AttrBinding(std::string name, std::shared_ptr<Node> val)
163
      : static_name(std::move(name)), value(std::move(val)) {}
164
165
  // Dynamic attribute
166
  AttrBinding(std::shared_ptr<Node> name_expr, std::shared_ptr<Node> val)
167
      : dynamic_name(std::move(name_expr)), value(std::move(val)) {}
168
169
  bool is_dynamic() const { return !static_name.has_value(); }
170
};
171
172
struct AttrsetNode {
173
  std::vector<AttrBinding> attrs;
174
  bool recursive = false;
175
  uint32_t line = 0;
176
  AttrsetNode(bool rec = false, uint32_t l = 0) : recursive(rec), line(l) {}
177
};
178
179
struct SelectNode {
180
  std::shared_ptr<Node> expr;
181
  std::shared_ptr<Node> attr;
182
  std::optional<std::shared_ptr<Node>> default_expr;
183
  uint32_t line = 0;
184
  SelectNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l = 0);
185
};
186
187
struct HasAttrNode {
188
  std::shared_ptr<Node> expr;
189
  std::shared_ptr<Node> attr;
190
  uint32_t line = 0;
191
  HasAttrNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l = 0);
192
};
193
194
struct WithNode {
195
  std::shared_ptr<Node> attrs;
196
  std::shared_ptr<Node> body;
197
  uint32_t line = 0;
198
  WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l = 0);
199
};
200
201
struct IfNode {
202
  std::shared_ptr<Node> cond;
203
  std::shared_ptr<Node> then_branch;
204
  std::shared_ptr<Node> else_branch;
205
  uint32_t line = 0;
206
  IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e, uint32_t l = 0);
207
};
208
209
struct LetNode {
210
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
211
  std::shared_ptr<Node> body;
212
  uint32_t line = 0;
213
  LetNode(std::shared_ptr<Node> b, uint32_t l = 0);
214
};
215
216
struct LetRecNode {
217
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
218
  std::shared_ptr<Node> body;
219
  uint32_t line = 0;
220
  LetRecNode(std::shared_ptr<Node> b, uint32_t l = 0);
221
};
222
223
struct AssertNode {
224
  std::shared_ptr<Node> cond;
225
  std::shared_ptr<Node> body;
226
  uint32_t line = 0;
227
  AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l = 0);
228
};
229
230
struct ImportNode {
231
  std::shared_ptr<Node> path; // Path expression to import
232
  uint32_t line = 0;
233
  ImportNode(std::shared_ptr<Node> p, uint32_t l = 0);
234
};
235
236
struct ThunkNode {
237
  std::shared_ptr<Node> expr;
238
  uint32_t line = 0;
239
  ThunkNode(std::shared_ptr<Node> e, uint32_t l = 0);
240
};
241
242
struct ForceNode {
243
  std::shared_ptr<Node> expr;
244
  uint32_t line = 0;
245
  ForceNode(std::shared_ptr<Node> e, uint32_t l = 0);
246
};
247
248
struct ListNode {
249
  std::vector<std::shared_ptr<Node>> elements;
250
  uint32_t line = 0;
251
  ListNode(std::vector<std::shared_ptr<Node>> elems = {}, uint32_t l = 0)
252
      : elements(std::move(elems)), line(l) {}
253
};
254
255
// Node wraps a variant for type-safe AST
256
class Node {
257
public:
258
  using Variant = std::variant<ConstIntNode, ConstFloatNode, ConstStringNode, ConstPathNode,
259
                               ConstBoolNode, ConstNullNode, ConstURINode, ConstLookupPathNode,
260
                               VarNode, LambdaNode, AppNode, BinaryOpNode, UnaryOpNode, ImportNode,
261
                               AttrsetNode, SelectNode, HasAttrNode, WithNode, IfNode, LetNode,
262
                               LetRecNode, AssertNode, ThunkNode, ForceNode, ListNode>;
263
264
  Variant data;
265
266
  template <typename T> Node(T&& value) : data(std::forward<T>(value)) {}
267
268
  template <typename T> T* get_if() { return std::get_if<T>(&data); }
269
270
  template <typename T> const T* get_if() const { return std::get_if<T>(&data); }
271
272
  template <typename T> bool holds() const { return std::holds_alternative<T>(data); }
273
};
274
275
// Constructor implementations
276
inline LambdaNode::LambdaNode(uint32_t a, std::shared_ptr<Node> b, uint32_t l)
277
    : arity(a), body(std::move(b)), line(l) {}
278
279
inline AppNode::AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l)
280
    : func(std::move(f)), arg(std::move(a)), line(l) {}
281
282
inline BinaryOpNode::BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r,
283
                                  uint32_t ln)
284
    : op(o), left(std::move(l)), right(std::move(r)), line(ln) {}
285
286
inline UnaryOpNode::UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l)
287
    : op(o), operand(std::move(operand)), line(l) {}
288
289
inline SelectNode::SelectNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l)
290
    : expr(std::move(e)), attr(std::move(a)), line(l) {}
291
292
inline HasAttrNode::HasAttrNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l)
293
    : expr(std::move(e)), attr(std::move(a)), line(l) {}
294
295
inline WithNode::WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l)
296
    : attrs(std::move(a)), body(std::move(b)), line(l) {}
297
298
inline IfNode::IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e,
299
                      uint32_t l)
300
    : cond(std::move(c)), then_branch(std::move(t)), else_branch(std::move(e)), line(l) {}
301
302
inline LetNode::LetNode(std::shared_ptr<Node> b, uint32_t l) : body(std::move(b)), line(l) {}
303
304
inline LetRecNode::LetRecNode(std::shared_ptr<Node> b, uint32_t l) : body(std::move(b)), line(l) {}
305
306
inline AssertNode::AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l)
307
    : cond(std::move(c)), body(std::move(b)), line(l) {}
308
309
inline ImportNode::ImportNode(std::shared_ptr<Node> p, uint32_t l) : path(std::move(p)), line(l) {}
310
311
inline ThunkNode::ThunkNode(std::shared_ptr<Node> e, uint32_t l) : expr(std::move(e)), line(l) {}
312
313
inline ForceNode::ForceNode(std::shared_ptr<Node> e, uint32_t l) : expr(std::move(e)), line(l) {}
314
315
struct SourceFile {
316
  std::string path;
317
  std::string content;
318
  std::shared_ptr<Node> ast;
319
};
320
321
struct IRModule {
322
  uint32_t version = IR_VERSION;
323
  std::vector<SourceFile> sources;
324
  std::vector<std::pair<std::string, std::string>> imports;
325
  std::shared_ptr<Node> entry;
326
  std::unordered_map<std::string, uint32_t> string_table;
327
};
328
329
} // namespace nix_irc
330
#endif