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)) %>
<% needs_size? = @params |> Enum.any?(fn {_index, param} -> Parameter.needs_size?(param) end) %>
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,
.io = beam.io.get(allocator),
};
<%= if needs_make? do %>
var error_info: ?beam.term = null;
<% end %>
<%= if needs_size? do %>
var payload_sizes: struct {
<%= for {index, param} <- @params, Parameter.needs_size?(param) do %>
arg<%= index %>: ?usize = null,
<% end %>
} = .{};
<% end %>
<%= for {index, param} <- @params, param.in_out do %>
var arg<%= index %>: <%= Parameter.render_in_out_type(param) %> = undefined;
<% end %>
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 orelse beam.make_empty_list(.{})}, .{}).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;
}