Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions src/libexpr-c/nix_api_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,56 +42,56 @@ nix_err nix_libexpr_init(nix_c_context * context)
}

nix_err nix_expr_eval_from_string(
nix_c_context * context, EvalState * state, const char * expr, const char * path, Value * value)
nix_c_context * context, EvalState * state, const char * expr, const char * path, nix_value * value)
{
if (context)
context->last_err_code = NIX_OK;
try {
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);
state->state.eval(parsedExpr, value->value);
state->state.forceValue(value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}

nix_err nix_value_call(nix_c_context * context, EvalState * state, Value * fn, Value * arg, Value * value)
nix_err nix_value_call(nix_c_context * context, EvalState * state, Value * fn, nix_value * arg, nix_value * value)
{
if (context)
context->last_err_code = NIX_OK;
try {
state->state.callFunction(*(nix::Value *) fn, *(nix::Value *) arg, *(nix::Value *) value, nix::noPos);
state->state.forceValue(*(nix::Value *) value, nix::noPos);
state->state.callFunction(fn->value, arg->value, value->value, nix::noPos);
state->state.forceValue(value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}

nix_err nix_value_call_multi(nix_c_context * context, EvalState * state, Value * fn, size_t nargs, Value ** args, Value * value)
nix_err nix_value_call_multi(nix_c_context * context, EvalState * state, nix_value * fn, size_t nargs, nix_value ** args, nix_value * value)
{
if (context)
context->last_err_code = NIX_OK;
try {
state->state.callFunction(*(nix::Value *) fn, nargs, (nix::Value * *)args, *(nix::Value *) value, nix::noPos);
state->state.forceValue(*(nix::Value *) value, nix::noPos);
state->state.callFunction(fn->value, nargs, (nix::Value * *)args, value->value, nix::noPos);
state->state.forceValue(value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}

nix_err nix_value_force(nix_c_context * context, EvalState * state, Value * value)
nix_err nix_value_force(nix_c_context * context, EvalState * state, nix_value * value)
{
if (context)
context->last_err_code = NIX_OK;
try {
state->state.forceValue(*(nix::Value *) value, nix::noPos);
state->state.forceValue(value->value, nix::noPos);
}
NIXC_CATCH_ERRS
}

nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, Value * value)
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value)
{
if (context)
context->last_err_code = NIX_OK;
try {
state->state.forceValueDeep(*(nix::Value *) value);
state->state.forceValueDeep(value->value);
}
NIXC_CATCH_ERRS
}
Expand Down Expand Up @@ -181,6 +181,15 @@ nix_err nix_gc_decref(nix_c_context * context, const void *)
void nix_gc_now() {}
#endif

nix_err nix_value_incref(nix_c_context * context, nix_value *x)
{
return nix_gc_incref(context, (const void *) x);
}
nix_err nix_value_decref(nix_c_context * context, nix_value *x)
{
return nix_gc_decref(context, (const void *) x);
}

void nix_gc_register_finalizer(void * obj, void * cd, void (*finalizer)(void * obj, void * cd))
{
#ifdef HAVE_BOEHMGC
Expand Down
42 changes: 27 additions & 15 deletions src/libexpr-c/nix_api_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,23 @@ extern "C" {
* @see nix_state_create
*/
typedef struct EvalState EvalState; // nix::EvalState
/**
* @brief Represents a value in the Nix language.

/** @brief A Nix language value, or thunk that may evaluate to a value.
*
* Values are the primary objects manipulated in the Nix language.
* They are considered to be immutable from a user's perspective, but the process of evaluating a value changes its
* ValueType if it was a thunk. After a value has been evaluated, its ValueType does not change.
*
* Evaluation in this context refers to the process of evaluating a single value object, also called "forcing" the
* value; see `nix_value_force`.
*
* The evaluator manages its own memory, but your use of the C API must follow the reference counting rules.
*
* Owned by the garbage collector.
* @struct Value
* @see value_manip
* @see nix_value_incref, nix_value_decref
*/
typedef void Value; // nix::Value
typedef struct nix_value nix_value;
[[deprecated("use nix_value instead")]] typedef nix_value Value;

// Function prototypes
/**
Expand Down Expand Up @@ -65,7 +74,7 @@ nix_err nix_libexpr_init(nix_c_context * context);
* @return NIX_OK if the evaluation was successful, an error code otherwise.
*/
nix_err nix_expr_eval_from_string(
nix_c_context * context, EvalState * state, const char * expr, const char * path, Value * value);
nix_c_context * context, EvalState * state, const char * expr, const char * path, nix_value * value);

/**
* @brief Calls a Nix function with an argument.
Expand All @@ -79,7 +88,7 @@ nix_err nix_expr_eval_from_string(
* @see nix_init_apply() for a similar function that does not performs the call immediately, but stores it as a thunk.
* Note the different argument order.
*/
nix_err nix_value_call(nix_c_context * context, EvalState * state, Value * fn, Value * arg, Value * value);
nix_err nix_value_call(nix_c_context * context, EvalState * state, nix_value * fn, nix_value * arg, nix_value * value);

/**
* @brief Calls a Nix function with multiple arguments.
Expand All @@ -98,7 +107,7 @@ nix_err nix_value_call(nix_c_context * context, EvalState * state, Value * fn, V
* @see NIX_VALUE_CALL For a macro that wraps this function for convenience.
*/
nix_err nix_value_call_multi(
nix_c_context * context, EvalState * state, Value * fn, size_t nargs, Value ** args, Value * value);
nix_c_context * context, EvalState * state, nix_value * fn, size_t nargs, nix_value ** args, nix_value * value);

/**
* @brief Calls a Nix function with multiple arguments.
Expand All @@ -116,20 +125,18 @@ nix_err nix_value_call_multi(
*/
#define NIX_VALUE_CALL(context, state, value, fn, ...) \
do { \
Value * args_array[] = {__VA_ARGS__}; \
nix_value * args_array[] = {__VA_ARGS__}; \
size_t nargs = sizeof(args_array) / sizeof(args_array[0]); \
nix_value_call_multi(context, state, fn, nargs, args_array, value); \
} while (0)

/**
* @brief Forces the evaluation of a Nix value.
*
* The Nix interpreter is lazy, and not-yet-evaluated Values can be
* 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 these Values into their final type.
*
* @note This function is mainly needed before calling @ref getters, but not for API calls that return a `Value`.
* This function mutates such a `nix_value`, so that, if successful, it has its final type.
*
* @param[out] context Optional, stores error information
* @param[in] state The state of the evaluation.
Expand All @@ -138,7 +145,7 @@ nix_err nix_value_call_multi(
* @return NIX_OK if the force operation was successful, an error code
* otherwise.
*/
nix_err nix_value_force(nix_c_context * context, EvalState * state, Value * value);
nix_err nix_value_force(nix_c_context * context, EvalState * state, nix_value * value);

/**
* @brief Forces the deep evaluation of a Nix value.
Expand All @@ -154,7 +161,7 @@ nix_err nix_value_force(nix_c_context * context, EvalState * state, Value * valu
* @return NIX_OK if the deep force operation was successful, an error code
* otherwise.
*/
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, Value * value);
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value);

/**
* @brief Create a new Nix language evaluator state.
Expand Down Expand Up @@ -188,6 +195,11 @@ void nix_state_free(EvalState * state);
* you're done with a value returned by the evaluator.
* @{
*/

// TODO: Deprecate nix_gc_incref in favor of the type-specific reference counting functions?
// e.g. nix_value_incref.
// It gives implementors more flexibility, and adds safety, so that generated
// bindings can be used without fighting the host type system (where applicable).
/**
* @brief Increment the garbage collector reference counter for the given object.
*
Expand Down
5 changes: 5 additions & 0 deletions src/libexpr-c/nix_api_expr_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ struct ListBuilder
nix::ListBuilder builder;
};

struct nix_value
{
nix::Value value;
};

struct nix_string_return
{
std::string str;
Expand Down
Loading