@@ -20,15 +20,15 @@ static const nix::Value & check_value_not_null(const nix_value * value)
2020 if (!value) {
2121 throw std::runtime_error (" nix_value is null" );
2222 }
23- return *(( const nix::Value *) value) ;
23+ return *value-> value ;
2424}
2525
2626static nix::Value & check_value_not_null (nix_value * value)
2727{
2828 if (!value) {
2929 throw std::runtime_error (" nix_value is null" );
3030 }
31- return value->value ;
31+ return * value->value ;
3232}
3333
3434static const nix::Value & check_value_in (const nix_value * value)
@@ -58,9 +58,14 @@ static nix::Value & check_value_out(nix_value * value)
5858 return v;
5959}
6060
61- static inline nix_value * as_nix_value_ptr (nix::Value * v)
61+ static inline nix_value * new_nix_value (nix::Value * v, nix::EvalMemory & mem )
6262{
63- return reinterpret_cast <nix_value *>(v);
63+ nix_value * ret = new (mem.allocBytes (sizeof (nix_value))) nix_value{
64+ .value = v,
65+ .mem = &mem,
66+ };
67+ nix_gc_incref (nullptr , ret);
68+ return ret;
6469}
6570
6671/* *
@@ -69,7 +74,13 @@ static inline nix_value * as_nix_value_ptr(nix::Value * v)
6974 * Deals with errors and converts arguments from C++ into C types.
7075 */
7176static void nix_c_primop_wrapper (
72- PrimOpFun f, void * userdata, nix::EvalState & state, const nix::PosIdx pos, nix::Value ** args, nix::Value & v)
77+ PrimOpFun f,
78+ void * userdata,
79+ int arity,
80+ nix::EvalState & state,
81+ const nix::PosIdx pos,
82+ nix::Value ** args,
83+ nix::Value & v)
7384{
7485 nix_c_context ctx;
7586
@@ -85,8 +96,15 @@ static void nix_c_primop_wrapper(
8596 // ok because we don't see a need for this yet (e.g. inspecting thunks,
8697 // or maybe something to make blackholes work better; we don't know).
8798 nix::Value vTmp;
99+ nix_value * vTmpPtr = new_nix_value (&vTmp, state.mem );
88100
89- f (userdata, &ctx, (EvalState *) &state, (nix_value **) args, (nix_value *) &vTmp);
101+ std::vector<nix_value *> external_args;
102+ external_args.reserve (arity);
103+ for (int i = 0 ; i < arity; i++) {
104+ nix_value * external_arg = new_nix_value (args[i], state.mem );
105+ external_args.push_back (external_arg);
106+ }
107+ f (userdata, &ctx, (EvalState *) &state, external_args.data (), vTmpPtr);
90108
91109 if (ctx.last_err_code != NIX_OK) {
92110 /* TODO: Throw different errors depending on the error code */
@@ -135,7 +153,7 @@ PrimOp * nix_alloc_primop(
135153 .args = {},
136154 .arity = (size_t ) arity,
137155 .doc = doc,
138- .fun = std::bind (nix_c_primop_wrapper, fun, user_data, _1, _2, _3, _4)};
156+ .fun = std::bind (nix_c_primop_wrapper, fun, user_data, arity, _1, _2, _3, _4)};
139157 if (args)
140158 for (size_t i = 0 ; args[i]; i++)
141159 p->args .emplace_back (*args);
@@ -160,8 +178,7 @@ nix_value * nix_alloc_value(nix_c_context * context, EvalState * state)
160178 if (context)
161179 context->last_err_code = NIX_OK;
162180 try {
163- nix_value * res = as_nix_value_ptr (state->state .allocValue ());
164- nix_gc_incref (nullptr , res);
181+ nix_value * res = new_nix_value (state->state .allocValue (), state->state .mem );
165182 return res;
166183 }
167184 NIXC_CATCH_ERRS_NULL
@@ -331,10 +348,10 @@ nix_value * nix_get_list_byidx(nix_c_context * context, const nix_value * value,
331348 return nullptr ;
332349 }
333350 auto * p = v.listView ()[ix];
334- nix_gc_incref ( nullptr , p);
335- if (p != nullptr )
336- state->state .forceValue (*p, nix::noPos);
337- return as_nix_value_ptr (p );
351+ if (p == nullptr )
352+ return nullptr ;
353+ state->state .forceValue (*p, nix::noPos);
354+ return new_nix_value (p, state-> state . mem );
338355 }
339356 NIXC_CATCH_ERRS_NULL
340357}
@@ -352,9 +369,8 @@ nix_get_list_byidx_lazy(nix_c_context * context, const nix_value * value, EvalSt
352369 return nullptr ;
353370 }
354371 auto * p = v.listView ()[ix];
355- nix_gc_incref (nullptr , p);
356372 // Note: intentionally NOT calling forceValue() to keep the element lazy
357- return as_nix_value_ptr (p );
373+ return new_nix_value (p, state-> state . mem );
358374 }
359375 NIXC_CATCH_ERRS_NULL
360376}
@@ -369,9 +385,8 @@ nix_value * nix_get_attr_byname(nix_c_context * context, const nix_value * value
369385 nix::Symbol s = state->state .symbols .create (name);
370386 auto attr = v.attrs ()->get (s);
371387 if (attr) {
372- nix_gc_incref (nullptr , attr->value );
373388 state->state .forceValue (*attr->value , nix::noPos);
374- return as_nix_value_ptr (attr->value );
389+ return new_nix_value (attr->value , state-> state . mem );
375390 }
376391 nix_set_err_msg (context, NIX_ERR_KEY, " missing attribute" );
377392 return nullptr ;
@@ -390,9 +405,8 @@ nix_get_attr_byname_lazy(nix_c_context * context, const nix_value * value, EvalS
390405 nix::Symbol s = state->state .symbols .create (name);
391406 auto attr = v.attrs ()->get (s);
392407 if (attr) {
393- nix_gc_incref (nullptr , attr->value );
394408 // Note: intentionally NOT calling forceValue() to keep the attribute lazy
395- return as_nix_value_ptr (attr->value );
409+ return new_nix_value (attr->value , state-> state . mem );
396410 }
397411 nix_set_err_msg (context, NIX_ERR_KEY, " missing attribute" );
398412 return nullptr ;
@@ -440,9 +454,8 @@ nix_get_attr_byidx(nix_c_context * context, nix_value * value, EvalState * state
440454 }
441455 const nix::Attr & a = (*v.attrs ())[i];
442456 *name = state->state .symbols [a.name ].c_str ();
443- nix_gc_incref (nullptr , a.value );
444457 state->state .forceValue (*a.value , nix::noPos);
445- return as_nix_value_ptr (a.value );
458+ return new_nix_value (a.value , state-> state . mem );
446459 }
447460 NIXC_CATCH_ERRS_NULL
448461}
@@ -461,9 +474,8 @@ nix_value * nix_get_attr_byidx_lazy(
461474 }
462475 const nix::Attr & a = (*v.attrs ())[i];
463476 *name = state->state .symbols [a.name ].c_str ();
464- nix_gc_incref (nullptr , a.value );
465477 // Note: intentionally NOT calling forceValue() to keep the attribute lazy
466- return as_nix_value_ptr (a.value );
478+ return new_nix_value (a.value , state-> state . mem );
467479 }
468480 NIXC_CATCH_ERRS_NULL
469481}
@@ -503,7 +515,7 @@ nix_err nix_init_string(nix_c_context * context, nix_value * value, const char *
503515 context->last_err_code = NIX_OK;
504516 try {
505517 auto & v = check_value_out (value);
506- v.mkString (std::string_view (str));
518+ v.mkString (std::string_view (str), *value-> mem );
507519 }
508520 NIXC_CATCH_ERRS
509521}
@@ -514,7 +526,7 @@ nix_err nix_init_path_string(nix_c_context * context, EvalState * s, nix_value *
514526 context->last_err_code = NIX_OK;
515527 try {
516528 auto & v = check_value_out (value);
517- v.mkPath (s->state .rootPath (nix::CanonPath (str)));
529+ v.mkPath (s->state .rootPath (nix::CanonPath (str)), s-> state . mem );
518530 }
519531 NIXC_CATCH_ERRS
520532}
0 commit comments