brewery
notashelf /
da9be4b014df0b5e0dcaf19b0fd97474e226c6f6

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git
src/plugin.cppCpp166 lines4.0 KB
1
#ifdef unix
2
#undef unix
3
#endif
4
5
#include "nix/expr/eval.hh"
6
#include "nix/expr/primops.hh"
7
#include "nix/expr/value.hh"
8
#include "nix/store/store-api.hh"
9
#include "nix/util/source-path.hh"
10
11
#include "irc/ir_gen.h"
12
#include "irc/parser.h"
13
#include "irc/resolver.h"
14
#include "irc/serializer.h"
15
#include "irc/types.h"
16
#include "irc/evaluator.h"
17
18
#include <fstream>
19
#include <iostream>
20
#include <memory>
21
#include <optional>
22
23
namespace nix_ir_plugin {
24
25
using namespace nix;
26
using namespace nix_irc;
27
28
/**
29
 * Load and evaluate a pre-compiled IR bundle
30
 * Usage: builtins.nixIR.loadIR "/path/to/file.nixir"
31
 */
32
static void prim_loadIR(EvalState &state, const PosIdx pos, Value **args,
33
                        Value &v) {
34
  auto path = state.forceStringNoCtx(
35
      *args[0], pos,
36
      "while evaluating the first argument to builtins.nixIR.loadIR");
37
38
  std::string pathStr(path);
39
40
  Deserializer deserializer;
41
  IRModule module;
42
43
  try {
44
    module = deserializer.deserialize(pathStr);
45
  } catch (const std::exception &e) {
46
    state.error<EvalError>("failed to deserialize IR bundle: %s", e.what())
47
        .atPos(pos)
48
        .debugThrow();
49
  }
50
51
  if (!module.entry) {
52
    state.error<EvalError>("IR bundle has no entry point")
53
        .atPos(pos)
54
        .debugThrow();
55
  }
56
57
  try {
58
    Evaluator evaluator(state);
59
    evaluator.eval_to_nix(module.entry, v);
60
  } catch (const std::exception &e) {
61
    state.error<EvalError>("failed to evaluate IR: %s", e.what())
62
        .atPos(pos)
63
        .debugThrow();
64
  }
65
}
66
67
/**
68
 * Compile Nix source to IR on-the-fly
69
 * Usage: builtins.nixIR.compile "{ x = 1; }"
70
 */
71
static void prim_compileNix(EvalState &state, const PosIdx pos, Value **args,
72
                            Value &v) {
73
  auto source = state.forceStringNoCtx(
74
      *args[0], pos,
75
      "while evaluating the first argument to builtins.nixIR.compile");
76
77
  std::string sourceStr(source);
78
79
  try {
80
    Parser parser;
81
    auto ast = parser.parse(sourceStr, "<inline>");
82
83
    if (!ast) {
84
      state.error<EvalError>("failed to parse Nix expression")
85
          .atPos(pos)
86
          .debugThrow();
87
    }
88
89
    IRGenerator ir_gen;
90
    auto ir = ir_gen.generate(ast);
91
92
    Evaluator evaluator(state);
93
    evaluator.eval_to_nix(ir, v);
94
95
  } catch (const std::exception &e) {
96
    state.error<EvalError>("IR compilation failed: %s", e.what())
97
        .atPos(pos)
98
        .debugThrow();
99
  }
100
}
101
102
/**
103
 * Get information about the IR plugin
104
 * Usage: builtins.nixIR.info
105
 */
106
static void prim_info(EvalState &state, const PosIdx pos, Value **args,
107
                      Value &v) {
108
  auto bindings = state.buildBindings(3);
109
110
  Value *vName = state.allocValue();
111
  vName->mkString("nix-ir-plugin");
112
  bindings.insert(state.symbols.create("name"), vName);
113
114
  Value *vVersion = state.allocValue();
115
  vVersion->mkString("0.1.0");
116
  bindings.insert(state.symbols.create("version"), vVersion);
117
118
  Value *vStatus = state.allocValue();
119
  vStatus->mkString("runtime-active");
120
  bindings.insert(state.symbols.create("status"), vStatus);
121
122
  v.mkAttrs(bindings.finish());
123
}
124
125
// Register primops on plugin load
126
static RegisterPrimOp rp_loadIR({
127
    .name = "__nixIR_loadIR",
128
    .args = {"path"},
129
    .arity = 1,
130
    .doc = R"(
131
      Load a pre-compiled IR bundle from the given path.
132
      Returns an attrset with information about the loaded bundle.
133
134
    )",
135
    .fun = prim_loadIR,
136
});
137
138
static RegisterPrimOp rp_compileNix({
139
    .name = "__nixIR_compile",
140
    .args = {"source"},
141
    .arity = 1,
142
    .doc = R"(
143
      Compile Nix source code to IR on-the-fly.
144
      Returns an attrset with information about the compiled IR.
145
146
    )",
147
    .fun = prim_compileNix,
148
});
149
150
static RegisterPrimOp rp_info({
151
    .name = "__nixIR_info",
152
    .args = {},
153
    .arity = 0,
154
    .doc = R"(
155
      Get information about the IR plugin.
156
      Returns an attrset with plugin name, version, and status.
157
    )",
158
    .fun = prim_info,
159
});
160
161
} // namespace nix_ir_plugin
162
163
// Plugin initialization message
164
__attribute__((constructor)) static void init_plugin() {
165
  std::cerr << "nix-ir-plugin loaded" << std::endl;
166
}