about summary refs log tree commit diff
path: root/third_party/nix/src/libexpr/eval-inline.hh
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/src/libexpr/eval-inline.hh')
-rw-r--r--third_party/nix/src/libexpr/eval-inline.hh90
1 files changed, 90 insertions, 0 deletions
diff --git a/third_party/nix/src/libexpr/eval-inline.hh b/third_party/nix/src/libexpr/eval-inline.hh
new file mode 100644
index 000000000000..5162ab3971a3
--- /dev/null
+++ b/third_party/nix/src/libexpr/eval-inline.hh
@@ -0,0 +1,90 @@
+#pragma once
+
+#include "libexpr/eval.hh"
+
+#define LocalNoInline(f)              \
+  static f __attribute__((noinline)); \
+  f
+#define LocalNoInlineNoReturn(f)                \
+  static f __attribute__((noinline, noreturn)); \
+  f
+
+namespace nix {
+
+LocalNoInlineNoReturn(void throwEvalError(const char* s, const Pos& pos)) {
+  throw EvalError(format(s) % pos);
+}
+
+LocalNoInlineNoReturn(void throwTypeError(const char* s, const Value& v)) {
+  throw TypeError(format(s) % showType(v));
+}
+
+LocalNoInlineNoReturn(void throwTypeError(const char* s, const Value& v,
+                                          const Pos& pos)) {
+  throw TypeError(format(s) % showType(v) % pos);
+}
+
+void EvalState::forceValue(Value& v, const Pos& pos) {
+  if (v.type == tThunk) {
+    Env* env = v.thunk.env;
+    Expr* expr = v.thunk.expr;
+    try {
+      v.type = tBlackhole;
+      // checkInterrupt();
+      expr->eval(*this, *env, v);
+    } catch (...) {
+      v.type = tThunk;
+      v.thunk.env = env;
+      v.thunk.expr = expr;
+      throw;
+    }
+  } else if (v.type == tApp) {
+    callFunction(*v.app.left, *v.app.right, v, noPos);
+  } else if (v.type == tBlackhole) {
+    throwEvalError("infinite recursion encountered, at %1%", pos);
+  }
+}
+
+inline void EvalState::forceAttrs(Value& v) {
+  forceValue(v);
+  if (v.type != tAttrs) {
+    throwTypeError("value is %1% while a set was expected", v);
+  }
+}
+
+inline void EvalState::forceAttrs(Value& v, const Pos& pos) {
+  forceValue(v);
+  if (v.type != tAttrs) {
+    throwTypeError("value is %1% while a set was expected, at %2%", v, pos);
+  }
+}
+
+inline void EvalState::forceList(Value& v) {
+  forceValue(v);
+  if (!v.isList()) {
+    throwTypeError("value is %1% while a list was expected", v);
+  }
+}
+
+inline void EvalState::forceList(Value& v, const Pos& pos) {
+  forceValue(v);
+  if (!v.isList()) {
+    throwTypeError("value is %1% while a list was expected, at %2%", v, pos);
+  }
+}
+
+/* Note: Various places expect the allocated memory to be zeroed. */
+inline void* allocBytes(size_t n) {
+  void* p;
+#if HAVE_BOEHMGC
+  p = GC_MALLOC(n);
+#else
+  p = calloc(n, 1);
+#endif
+  if (!p) {
+    throw std::bad_alloc();
+  }
+  return p;
+}
+
+}  // namespace nix