brewery
notashelf /
775bb42c63250b3ee17c160d78dd492b50a1c9eb

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git
src/irc/types.hC306 lines8.3 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
  IF = 0x40,
38
  LET = 0x50,
39
  LETREC = 0x51,
40
  ASSERT = 0x52,
41
  THUNK = 0x60,
42
  FORCE = 0x61,
43
  ERROR = 0xFF
44
};
45
46
enum class BinaryOp : uint8_t {
47
  ADD,
48
  SUB,
49
  MUL,
50
  DIV,
51
  CONCAT,
52
  EQ,
53
  NE,
54
  LT,
55
  GT,
56
  LE,
57
  GE,
58
  AND,
59
  OR,
60
  IMPL,
61
  MERGE
62
};
63
64
enum class UnaryOp : uint8_t { NEG, NOT };
65
66
// Forward declare Node for use in shared_ptr
67
class Node;
68
69
struct ConstIntNode {
70
  int64_t value;
71
  uint32_t line = 0;
72
  ConstIntNode(int64_t v = 0, uint32_t l = 0) : value(v), line(l) {}
73
};
74
75
struct ConstStringNode {
76
  std::string value;
77
  uint32_t line = 0;
78
  ConstStringNode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
79
};
80
81
struct ConstPathNode {
82
  std::string value;
83
  uint32_t line = 0;
84
  ConstPathNode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
85
};
86
87
struct ConstBoolNode {
88
  bool value;
89
  uint32_t line = 0;
90
  ConstBoolNode(bool v = false, uint32_t l = 0) : value(v), line(l) {}
91
};
92
93
struct ConstNullNode {
94
  uint32_t line = 0;
95
  ConstNullNode(uint32_t l = 0) : line(l) {}
96
};
97
98
struct ConstFloatNode {
99
  double value;
100
  uint32_t line = 0;
101
  ConstFloatNode(double v = 0.0, uint32_t l = 0) : value(v), line(l) {}
102
};
103
104
struct ConstURINode {
105
  std::string value;
106
  uint32_t line = 0;
107
  ConstURINode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
108
};
109
110
struct ConstLookupPathNode {
111
  std::string value; // e.g., "nixpkgs" or "nixpkgs/lib"
112
  uint32_t line = 0;
113
  ConstLookupPathNode(std::string v = "", uint32_t l = 0) : value(std::move(v)), line(l) {}
114
};
115
116
struct VarNode {
117
  uint32_t index = 0;
118
  std::optional<std::string> name;
119
  uint32_t line = 0;
120
  VarNode(uint32_t idx = 0, std::string n = "", uint32_t l = 0)
121
      : index(idx), name(n.empty() ? std::nullopt : std::optional<std::string>(n)), line(l) {}
122
};
123
124
struct LambdaNode {
125
  uint32_t arity = 1;
126
  std::shared_ptr<Node> body;
127
  std::optional<std::string> param_name;
128
  bool strict_pattern = true;
129
  uint32_t line = 0;
130
  LambdaNode(uint32_t a, std::shared_ptr<Node> b, uint32_t l = 0);
131
};
132
133
struct AppNode {
134
  std::shared_ptr<Node> func;
135
  std::shared_ptr<Node> arg;
136
  uint32_t line = 0;
137
  AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l = 0);
138
};
139
140
struct BinaryOpNode {
141
  BinaryOp op;
142
  std::shared_ptr<Node> left;
143
  std::shared_ptr<Node> right;
144
  uint32_t line = 0;
145
  BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r, uint32_t ln = 0);
146
};
147
148
struct UnaryOpNode {
149
  UnaryOp op;
150
  std::shared_ptr<Node> operand;
151
  uint32_t line = 0;
152
  UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l = 0);
153
};
154
155
struct AttrsetNode {
156
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> attrs;
157
  bool recursive = false;
158
  uint32_t line = 0;
159
  AttrsetNode(bool rec = false, uint32_t l = 0) : recursive(rec), line(l) {}
160
};
161
162
struct SelectNode {
163
  std::shared_ptr<Node> expr;
164
  std::shared_ptr<Node> attr;
165
  std::optional<std::shared_ptr<Node>> default_expr;
166
  uint32_t line = 0;
167
  SelectNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l = 0);
168
};
169
170
struct HasAttrNode {
171
  std::shared_ptr<Node> expr;
172
  std::shared_ptr<Node> attr;
173
  uint32_t line = 0;
174
  HasAttrNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l = 0);
175
};
176
177
struct WithNode {
178
  std::shared_ptr<Node> attrs;
179
  std::shared_ptr<Node> body;
180
  uint32_t line = 0;
181
  WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l = 0);
182
};
183
184
struct IfNode {
185
  std::shared_ptr<Node> cond;
186
  std::shared_ptr<Node> then_branch;
187
  std::shared_ptr<Node> else_branch;
188
  uint32_t line = 0;
189
  IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e, uint32_t l = 0);
190
};
191
192
struct LetNode {
193
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
194
  std::shared_ptr<Node> body;
195
  uint32_t line = 0;
196
  LetNode(std::shared_ptr<Node> b, uint32_t l = 0);
197
};
198
199
struct LetRecNode {
200
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
201
  std::shared_ptr<Node> body;
202
  uint32_t line = 0;
203
  LetRecNode(std::shared_ptr<Node> b, uint32_t l = 0);
204
};
205
206
struct AssertNode {
207
  std::shared_ptr<Node> cond;
208
  std::shared_ptr<Node> body;
209
  uint32_t line = 0;
210
  AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l = 0);
211
};
212
213
struct ImportNode {
214
  std::shared_ptr<Node> path; // Path expression to import
215
  uint32_t line = 0;
216
  ImportNode(std::shared_ptr<Node> p, uint32_t l = 0);
217
};
218
219
struct ThunkNode {
220
  std::shared_ptr<Node> expr;
221
  uint32_t line = 0;
222
  ThunkNode(std::shared_ptr<Node> e, uint32_t l = 0);
223
};
224
225
struct ForceNode {
226
  std::shared_ptr<Node> expr;
227
  uint32_t line = 0;
228
  ForceNode(std::shared_ptr<Node> e, uint32_t l = 0);
229
};
230
231
// Node wraps a variant for type-safe AST
232
class Node {
233
public:
234
  using Variant =
235
      std::variant<ConstIntNode, ConstFloatNode, ConstStringNode, ConstPathNode, ConstBoolNode,
236
                   ConstNullNode, ConstURINode, ConstLookupPathNode, VarNode, LambdaNode, AppNode,
237
                   BinaryOpNode, UnaryOpNode, ImportNode, AttrsetNode, SelectNode, HasAttrNode,
238
                   WithNode, IfNode, LetNode, LetRecNode, AssertNode, ThunkNode, ForceNode>;
239
240
  Variant data;
241
242
  template <typename T> Node(T&& value) : data(std::forward<T>(value)) {}
243
244
  template <typename T> T* get_if() { return std::get_if<T>(&data); }
245
246
  template <typename T> const T* get_if() const { return std::get_if<T>(&data); }
247
248
  template <typename T> bool holds() const { return std::holds_alternative<T>(data); }
249
};
250
251
// Constructor implementations
252
inline LambdaNode::LambdaNode(uint32_t a, std::shared_ptr<Node> b, uint32_t l)
253
    : arity(a), body(std::move(b)), line(l) {}
254
255
inline AppNode::AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l)
256
    : func(std::move(f)), arg(std::move(a)), line(l) {}
257
258
inline BinaryOpNode::BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r,
259
                                  uint32_t ln)
260
    : op(o), left(std::move(l)), right(std::move(r)), line(ln) {}
261
262
inline UnaryOpNode::UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l)
263
    : op(o), operand(std::move(operand)), line(l) {}
264
265
inline SelectNode::SelectNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l)
266
    : expr(std::move(e)), attr(std::move(a)), line(l) {}
267
268
inline HasAttrNode::HasAttrNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l)
269
    : expr(std::move(e)), attr(std::move(a)), line(l) {}
270
271
inline WithNode::WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l)
272
    : attrs(std::move(a)), body(std::move(b)), line(l) {}
273
274
inline IfNode::IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e,
275
                      uint32_t l)
276
    : cond(std::move(c)), then_branch(std::move(t)), else_branch(std::move(e)), line(l) {}
277
278
inline LetNode::LetNode(std::shared_ptr<Node> b, uint32_t l) : body(std::move(b)), line(l) {}
279
280
inline LetRecNode::LetRecNode(std::shared_ptr<Node> b, uint32_t l) : body(std::move(b)), line(l) {}
281
282
inline AssertNode::AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l)
283
    : cond(std::move(c)), body(std::move(b)), line(l) {}
284
285
inline ImportNode::ImportNode(std::shared_ptr<Node> p, uint32_t l) : path(std::move(p)), line(l) {}
286
287
inline ThunkNode::ThunkNode(std::shared_ptr<Node> e, uint32_t l) : expr(std::move(e)), line(l) {}
288
289
inline ForceNode::ForceNode(std::shared_ptr<Node> e, uint32_t l) : expr(std::move(e)), line(l) {}
290
291
struct SourceFile {
292
  std::string path;
293
  std::string content;
294
  std::shared_ptr<Node> ast;
295
};
296
297
struct IRModule {
298
  uint32_t version = IR_VERSION;
299
  std::vector<SourceFile> sources;
300
  std::vector<std::pair<std::string, std::string>> imports;
301
  std::shared_ptr<Node> entry;
302
  std::unordered_map<std::string, uint32_t> string_table;
303
};
304
305
} // namespace nix_irc
306
#endif