brewery
notashelf /
3387e0d822a24b85d7c7572e0b21b7dfd25d4230

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git
src/irc/types.hC292 lines7.8 KB
1
#ifndef NIX_IRC_TYPES_H
2
#define NIX_IRC_TYPES_H
3
4
#include <cstdint>
5
#include <fstream>
6
#include <memory>
7
#include <optional>
8
#include <sstream>
9
#include <string>
10
#include <unordered_map>
11
#include <utility>
12
#include <variant>
13
#include <vector>
14
15
namespace nix_irc {
16
17
constexpr uint32_t IR_MAGIC = 0x4E495258;
18
constexpr uint32_t IR_VERSION = 2;
19
20
enum class NodeType : uint8_t {
21
  CONST_INT = 0x01,
22
  CONST_FLOAT = 0x06,
23
  CONST_STRING = 0x02,
24
  CONST_PATH = 0x03,
25
  CONST_BOOL = 0x04,
26
  CONST_NULL = 0x05,
27
  CONST_URI = 0x07,
28
  VAR = 0x10,
29
  LAMBDA = 0x20,
30
  APP = 0x21,
31
  BINARY_OP = 0x22,
32
  UNARY_OP = 0x23,
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 VarNode {
111
  uint32_t index = 0;
112
  std::optional<std::string> name;
113
  uint32_t line = 0;
114
  VarNode(uint32_t idx = 0, std::string n = "", uint32_t l = 0)
115
      : index(idx), name(n.empty() ? std::nullopt : std::optional<std::string>(n)), line(l) {}
116
};
117
118
struct LambdaNode {
119
  uint32_t arity = 1;
120
  std::shared_ptr<Node> body;
121
  std::optional<std::string> param_name;
122
  bool strict_pattern = true;
123
  uint32_t line = 0;
124
  LambdaNode(uint32_t a, std::shared_ptr<Node> b, uint32_t l = 0);
125
};
126
127
struct AppNode {
128
  std::shared_ptr<Node> func;
129
  std::shared_ptr<Node> arg;
130
  uint32_t line = 0;
131
  AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l = 0);
132
};
133
134
struct BinaryOpNode {
135
  BinaryOp op;
136
  std::shared_ptr<Node> left;
137
  std::shared_ptr<Node> right;
138
  uint32_t line = 0;
139
  BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r, uint32_t ln = 0);
140
};
141
142
struct UnaryOpNode {
143
  UnaryOp op;
144
  std::shared_ptr<Node> operand;
145
  uint32_t line = 0;
146
  UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l = 0);
147
};
148
149
struct AttrsetNode {
150
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> attrs;
151
  bool recursive = false;
152
  uint32_t line = 0;
153
  AttrsetNode(bool rec = false, uint32_t l = 0) : recursive(rec), line(l) {}
154
};
155
156
struct SelectNode {
157
  std::shared_ptr<Node> expr;
158
  std::shared_ptr<Node> attr;
159
  std::optional<std::shared_ptr<Node>> default_expr;
160
  uint32_t line = 0;
161
  SelectNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l = 0);
162
};
163
164
struct HasAttrNode {
165
  std::shared_ptr<Node> expr;
166
  std::shared_ptr<Node> attr;
167
  uint32_t line = 0;
168
  HasAttrNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l = 0);
169
};
170
171
struct WithNode {
172
  std::shared_ptr<Node> attrs;
173
  std::shared_ptr<Node> body;
174
  uint32_t line = 0;
175
  WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l = 0);
176
};
177
178
struct IfNode {
179
  std::shared_ptr<Node> cond;
180
  std::shared_ptr<Node> then_branch;
181
  std::shared_ptr<Node> else_branch;
182
  uint32_t line = 0;
183
  IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e, uint32_t l = 0);
184
};
185
186
struct LetNode {
187
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
188
  std::shared_ptr<Node> body;
189
  uint32_t line = 0;
190
  LetNode(std::shared_ptr<Node> b, uint32_t l = 0);
191
};
192
193
struct LetRecNode {
194
  std::vector<std::pair<std::string, std::shared_ptr<Node>>> bindings;
195
  std::shared_ptr<Node> body;
196
  uint32_t line = 0;
197
  LetRecNode(std::shared_ptr<Node> b, uint32_t l = 0);
198
};
199
200
struct AssertNode {
201
  std::shared_ptr<Node> cond;
202
  std::shared_ptr<Node> body;
203
  uint32_t line = 0;
204
  AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l = 0);
205
};
206
207
struct ThunkNode {
208
  std::shared_ptr<Node> expr;
209
  uint32_t line = 0;
210
  ThunkNode(std::shared_ptr<Node> e, uint32_t l = 0);
211
};
212
213
struct ForceNode {
214
  std::shared_ptr<Node> expr;
215
  uint32_t line = 0;
216
  ForceNode(std::shared_ptr<Node> e, uint32_t l = 0);
217
};
218
219
// Node wraps a variant for type-safe AST
220
class Node {
221
public:
222
  using Variant =
223
      std::variant<ConstIntNode, ConstFloatNode, ConstStringNode, ConstPathNode, ConstBoolNode,
224
                   ConstNullNode, ConstURINode, VarNode, LambdaNode, AppNode, BinaryOpNode,
225
                   UnaryOpNode, AttrsetNode, SelectNode, HasAttrNode, WithNode, IfNode, LetNode,
226
                   LetRecNode, AssertNode, ThunkNode, ForceNode>;
227
228
  Variant data;
229
230
  template <typename T> Node(T&& value) : data(std::forward<T>(value)) {}
231
232
  template <typename T> T* get_if() { return std::get_if<T>(&data); }
233
234
  template <typename T> const T* get_if() const { return std::get_if<T>(&data); }
235
236
  template <typename T> bool holds() const { return std::holds_alternative<T>(data); }
237
};
238
239
// Constructor implementations
240
inline LambdaNode::LambdaNode(uint32_t a, std::shared_ptr<Node> b, uint32_t l)
241
    : arity(a), body(std::move(b)), line(l) {}
242
243
inline AppNode::AppNode(std::shared_ptr<Node> f, std::shared_ptr<Node> a, uint32_t l)
244
    : func(std::move(f)), arg(std::move(a)), line(l) {}
245
246
inline BinaryOpNode::BinaryOpNode(BinaryOp o, std::shared_ptr<Node> l, std::shared_ptr<Node> r,
247
                                  uint32_t ln)
248
    : op(o), left(std::move(l)), right(std::move(r)), line(ln) {}
249
250
inline UnaryOpNode::UnaryOpNode(UnaryOp o, std::shared_ptr<Node> operand, uint32_t l)
251
    : op(o), operand(std::move(operand)), line(l) {}
252
253
inline SelectNode::SelectNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l)
254
    : expr(std::move(e)), attr(std::move(a)), line(l) {}
255
256
inline HasAttrNode::HasAttrNode(std::shared_ptr<Node> e, std::shared_ptr<Node> a, uint32_t l)
257
    : expr(std::move(e)), attr(std::move(a)), line(l) {}
258
259
inline WithNode::WithNode(std::shared_ptr<Node> a, std::shared_ptr<Node> b, uint32_t l)
260
    : attrs(std::move(a)), body(std::move(b)), line(l) {}
261
262
inline IfNode::IfNode(std::shared_ptr<Node> c, std::shared_ptr<Node> t, std::shared_ptr<Node> e,
263
                      uint32_t l)
264
    : cond(std::move(c)), then_branch(std::move(t)), else_branch(std::move(e)), line(l) {}
265
266
inline LetNode::LetNode(std::shared_ptr<Node> b, uint32_t l) : body(std::move(b)), line(l) {}
267
268
inline LetRecNode::LetRecNode(std::shared_ptr<Node> b, uint32_t l) : body(std::move(b)), line(l) {}
269
270
inline AssertNode::AssertNode(std::shared_ptr<Node> c, std::shared_ptr<Node> b, uint32_t l)
271
    : cond(std::move(c)), body(std::move(b)), line(l) {}
272
273
inline ThunkNode::ThunkNode(std::shared_ptr<Node> e, uint32_t l) : expr(std::move(e)), line(l) {}
274
275
inline ForceNode::ForceNode(std::shared_ptr<Node> e, uint32_t l) : expr(std::move(e)), line(l) {}
276
277
struct SourceFile {
278
  std::string path;
279
  std::string content;
280
  std::shared_ptr<Node> ast;
281
};
282
283
struct IRModule {
284
  uint32_t version = IR_VERSION;
285
  std::vector<SourceFile> sources;
286
  std::vector<std::pair<std::string, std::string>> imports;
287
  std::shared_ptr<Node> entry;
288
  std::unordered_map<std::string, uint32_t> string_table;
289
};
290
291
} // namespace nix_irc
292
#endif