mirror of
https://github.com/NixOS/nix.git
synced 2024-11-25 08:12:29 +00:00
C API: add a way to throw errors from primops
This commit is contained in:
parent
3d79f38709
commit
ab9250286a
@ -58,7 +58,7 @@ Nix version: 2.17
|
||||
|
||||
# Writing a Nix language plug-in
|
||||
In this example we add a custom primitive operation (*primop*) to `builtins`.
|
||||
It will increment the argument if it is an integer and return `null` otherwise.
|
||||
It will increment the argument if it is an integer and throw an error otherwise.
|
||||
|
||||
**plugin.c:**
|
||||
```C
|
||||
@ -66,18 +66,18 @@ It will increment the argument if it is an integer and return `null` otherwise.
|
||||
#include <nix_api_expr.h>
|
||||
#include <nix_api_value.h>
|
||||
|
||||
void increment(State* state, int pos, Value** args, Value* v) {
|
||||
void increment(void* user_data, nix_c_context* ctx, State* state, Value** args, Value* v) {
|
||||
nix_value_force(NULL, state, args[0]);
|
||||
if (nix_get_type(NULL, args[0]) == NIX_TYPE_INT) {
|
||||
nix_set_int(NULL, v, nix_get_int(NULL, args[0]) + 1);
|
||||
} else {
|
||||
nix_set_null(NULL, v);
|
||||
nix_set_err_msg(ctx, NIX_ERR_UNKNOWN, "First argument should be an integer.");
|
||||
}
|
||||
}
|
||||
|
||||
void nix_plugin_entry() {
|
||||
const char* args[] = {"n", NULL};
|
||||
PrimOp *p = nix_alloc_primop(NULL, increment, 1, "increment", args, "Example custom built-in function: increments an integer");
|
||||
PrimOp *p = nix_alloc_primop(NULL, increment, 1, "increment", args, "Example custom built-in function: increments an integer", NULL);
|
||||
nix_register_primop(NULL, p);
|
||||
nix_gc_decref(NULL, p);
|
||||
}
|
||||
|
@ -42,7 +42,12 @@ static nix::Value & check_value_not_null(Value * value)
|
||||
static void nix_c_primop_wrapper(
|
||||
PrimOpFun f, void * userdata, nix::EvalState & state, const nix::PosIdx pos, nix::Value ** args, nix::Value & v)
|
||||
{
|
||||
f(userdata, (State *) &state, *reinterpret_cast<const int *>(&pos), (Value **) args, (Value *) &v);
|
||||
nix_c_context ctx;
|
||||
f(userdata, &ctx, (State *) &state, (Value **) args, (Value *) &v);
|
||||
/* TODO: In the future, this should throw different errors depending on the error code */
|
||||
if (ctx.last_err_code != NIX_OK)
|
||||
state.debugThrowLastTrace(nix::Error(
|
||||
{.msg = nix::hintfmt("Error from builtin function: %s", *ctx.last_err), .errPos = state.positions[pos]}));
|
||||
}
|
||||
|
||||
PrimOp * nix_alloc_primop(
|
||||
|
@ -65,15 +65,17 @@ typedef struct ExternalValue ExternalValue;
|
||||
* @{
|
||||
*/
|
||||
/** @brief Function pointer for primops
|
||||
* @param[in] user_data Arbitrary data, passed to nix_alloc_primop and stored.
|
||||
* When you want to return an error, call nix_set_err_msg(context, NIX_ERR_UNKNOWN, "your error message here").
|
||||
*
|
||||
* @param[in] user_data Arbitrary data that was initially supplied to nix_alloc_primop
|
||||
* @param[out] context Stores error information.
|
||||
* @param[in] state Evaluator state
|
||||
* @param[in] pos Call position, opaque index into the state's position table.
|
||||
* @param[in] args list of arguments. Note that these can be thunks and should be forced using nix_value_force before
|
||||
* use.
|
||||
* @param[out] ret return value
|
||||
* @see nix_alloc_primop, nix_set_primop
|
||||
*/
|
||||
typedef void (*PrimOpFun)(void * user_data, State * state, int pos, Value ** args, Value * ret);
|
||||
typedef void (*PrimOpFun)(void * user_data, nix_c_context * context, State * state, Value ** args, Value * ret);
|
||||
|
||||
/** @brief Allocate a PrimOp
|
||||
*
|
||||
@ -86,7 +88,7 @@ typedef void (*PrimOpFun)(void * user_data, State * state, int pos, Value ** arg
|
||||
* @param[in] name function name
|
||||
* @param[in] args array of argument names, NULL-terminated
|
||||
* @param[in] doc optional, documentation for this primop
|
||||
* @param[in] user_data optional, arbitrary data, passed to the function when it's called
|
||||
* @param[in] user_data optional, arbitrary data, passed to the callback when it's called
|
||||
* @return primop, or null in case of errors
|
||||
* @see nix_set_primop
|
||||
*/
|
||||
|
@ -263,6 +263,20 @@ nix_err nix_err_name(nix_c_context * context, const nix_c_context * read_context
|
||||
*/
|
||||
nix_err nix_err_code(const nix_c_context * read_context);
|
||||
|
||||
/**
|
||||
* @brief Set an error message on a nix context.
|
||||
*
|
||||
* This should be used when you want to throw an error from a PrimOp callback.
|
||||
*
|
||||
* All other use is internal to the API.
|
||||
*
|
||||
* @param context context to write the error message to, or NULL
|
||||
* @param err The error code to set and return
|
||||
* @param msg The error message to set.
|
||||
* @returns the error code set
|
||||
*/
|
||||
nix_err nix_set_err_msg(nix_c_context * context, nix_err err, const char * msg);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -17,18 +17,6 @@ struct nix_c_context
|
||||
|
||||
nix_err nix_context_error(nix_c_context * context);
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*
|
||||
* Sets the most recent error message.
|
||||
*
|
||||
* @param context context to write the error message to, or NULL
|
||||
* @param err The error code to set and return
|
||||
* @param msg The error message to set.
|
||||
* @returns the error code set
|
||||
*/
|
||||
nix_err nix_set_err_msg(nix_c_context * context, nix_err err, const char * msg);
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user