From 9cccb8bae0665a311c6d64e21b536c5e3a536115 Mon Sep 17 00:00:00 2001 From: Yorick van Pelt Date: Mon, 7 Aug 2023 15:09:50 +0200 Subject: [PATCH] nix_api_expr: always force values before giving them to the user --- src/libexpr/nix_api_expr.cc | 2 ++ src/libexpr/nix_api_expr.h | 6 +++++- src/libexpr/nix_api_value.cc | 5 ++++- src/libexpr/nix_api_value.h | 3 ++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libexpr/nix_api_expr.cc b/src/libexpr/nix_api_expr.cc index 880030380..a1c6d1acb 100644 --- a/src/libexpr/nix_api_expr.cc +++ b/src/libexpr/nix_api_expr.cc @@ -49,6 +49,7 @@ nix_err nix_expr_eval_from_string(nix_c_context *context, State *state, nix::Expr *parsedExpr = state->state.parseExprFromString( expr, state->state.rootPath(nix::CanonPath(path))); state->state.eval(parsedExpr, *(nix::Value *)value); + state->state.forceValue(*(nix::Value *)value, nix::noPos); } NIXC_CATCH_ERRS } @@ -60,6 +61,7 @@ nix_err nix_value_call(nix_c_context *context, State *state, Value *fn, try { state->state.callFunction(*(nix::Value *)fn, *(nix::Value *)arg, *(nix::Value *)value, nix::noPos); + state->state.forceValue(*(nix::Value *)value, nix::noPos); } NIXC_CATCH_ERRS } diff --git a/src/libexpr/nix_api_expr.h b/src/libexpr/nix_api_expr.h index 94eaa5a6c..77632de7c 100644 --- a/src/libexpr/nix_api_expr.h +++ b/src/libexpr/nix_api_expr.h @@ -100,7 +100,11 @@ nix_err nix_value_call(nix_c_context *context, State *state, Value *fn, * The Nix interpreter is lazy, and not-yet-evaluated Values can be * of type NIX_TYPE_THUNK instead of their actual value. * - * This function converts Values into their final type. + * This function converts these Values into their final type. + * + * @note You don't need this function for basic API usage, since all functions + * that return a value call it for you. The only place you will see a + * NIX_TYPE_THUNK is in the primop callback. * * @param[out] context Optional, stores error information * @param[in] state The state of the evaluation. diff --git a/src/libexpr/nix_api_value.cc b/src/libexpr/nix_api_value.cc index 6e02b3310..ead544a0b 100644 --- a/src/libexpr/nix_api_value.cc +++ b/src/libexpr/nix_api_value.cc @@ -201,7 +201,7 @@ ExternalValue *nix_get_external(nix_c_context *context, Value *value) { } Value *nix_get_list_byidx(nix_c_context *context, const Value *value, - unsigned int ix) { + State *state, unsigned int ix) { if (context) context->last_err_code = NIX_OK; try { @@ -209,6 +209,7 @@ Value *nix_get_list_byidx(nix_c_context *context, const Value *value, assert(v.type() == nix::nList); auto *p = v.listElems()[ix]; nix_gc_incref(nullptr, p); + state->state.forceValue(*p, nix::noPos); return (Value *)p; } NIXC_CATCH_ERRS_NULL @@ -225,6 +226,7 @@ Value *nix_get_attr_byname(nix_c_context *context, const Value *value, auto attr = v.attrs->get(s); if (attr) { nix_gc_incref(nullptr, attr->value); + state->state.forceValue(*attr->value, nix::noPos); return attr->value; } nix_set_err_msg(context, NIX_ERR_KEY, "missing attribute"); @@ -258,6 +260,7 @@ Value *nix_get_attr_byidx(nix_c_context *context, const Value *value, const nix::Attr &a = (*v.attrs)[i]; *name = ((const std::string &)(state->state.symbols[a.name])).c_str(); nix_gc_incref(nullptr, a.value); + state->state.forceValue(*a.value, nix::noPos); return a.value; } NIXC_CATCH_ERRS_NULL diff --git a/src/libexpr/nix_api_value.h b/src/libexpr/nix_api_value.h index 110dd086f..f47dafa6a 100644 --- a/src/libexpr/nix_api_value.h +++ b/src/libexpr/nix_api_value.h @@ -178,11 +178,12 @@ ExternalValue *nix_get_external(nix_c_context *context, Value *); * Owned by the GC. Use nix_gc_decref when you're done with the pointer * @param[out] context Optional, stores error information * @param[in] value Nix value to inspect + * @param[in] state nix evaluator state * @param[in] ix list element to get * @return value, NULL in case of errors */ Value *nix_get_list_byidx(nix_c_context *context, const Value *value, - unsigned int ix); + State *state, unsigned int ix); /** @brief Get an attr by name * * Owned by the GC. Use nix_gc_decref when you're done with the pointer