brewery
notashelf /
95baf44a9c4216e7ff7e1243195cf91f25853dd3

nixir

public

Import-resolving Nix IR plugin

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