Current section

Files

Jump to
zigler lib zig templates basic.zig.eex
Raw

lib/zig/templates/basic.zig.eex

<% needs_make? = @params |> Map.values |> Enum.any?(&Type.needs_make?(&1.type)) %>
fn <%= @name %>(env: beam.env, argc: c_int, args: [*c] const e.ErlNifTerm) callconv(.C) e.ErlNifTerm {
<%= cond do %>
<% allocator = @allocator -> %>
const allocator = nif.<%= allocator %>();
<% @leak_check -> %>
var gpa = beam.make_debug_allocator_instance();
const allocator = gpa.allocator();
<% :else -> %>
const allocator = beam.allocator;
<% end %>
beam.context = .{
.env = env,
.mode = .<%= context(@concurrency) %>,
.allocator = allocator
};
<%= if needs_make? do %>
var error_info = beam.make_empty_list(.{});
<% end %>
<%= for {index, param} <- @params, do: Parameter.render_accessory_variables(param, index) %>
const return_value = execution_block: {
const payload_opts = .{
<%= for {index, param} <- @params, do: Parameter.render_payload_options(param, index) %>
};
var error_index: u8 = undefined;
const payload = beam.payload.build(nif.<%= @alias || @name %>, argc, args, &error_index, payload_opts) catch |err| {
if (err == error.OutOfMemory) return e.enif_raise_exception(env, beam.make(.{err, error_index}, .{}).v);
<%= if needs_make? do %>
return e.enif_raise_exception(env, beam.make(.{err, error_index, error_info}, .{}).v);
<% else %>
unreachable;
<% end %>
};
defer {
beam.payload.cleanup(payload, .{
<%= for {index, param} <- @params, do: Parameter.render_cleanup(param, index) %>
});
}
const result = @call(.auto, nif.<%= @alias || @name %>, payload) <%= Nif.maybe_catch(@return.type) %>;
<%= Return.render_return(@return) %>
};
<%= if @leak_check do %>
if (gpa.deinit() == .leak) {
return e.enif_raise_exception(env, beam.make(.{
.__struct__ = .@"Elixir.RuntimeError",
.message = "memory leak detected in function `<%= inspect @module %>.<%= @alias || @name %>/<%= map_size(@params) %>`",
.__exception__ = true
}, .{}).v);
}
<% end %>
return return_value;
}