brewery
notashelf /
af17da34da03b077d596c6f9a3350ca4fa918a03

nixir

public

Import-resolving Nix IR plugin

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