defmodule Kinda.CodeGen.NIFDecl do alias Kinda.CodeGen.KindDecl @type dirty() :: :io | :cpu | false @type t() :: %__MODULE__{ wrapper_name: nil | String.t(), zig_name: nil | String.t(), nif_name: nil | String.t(), arity: integer(), ret: String.t(), dirty: dirty() } defstruct zig_name: nil, nif_name: nil, arity: 0, ret: nil, dirty: false, wrapper_name: nil defp arity({:fn, _fn_opts, [name: _name, params: [:...], type: _ret]}), do: 0 defp arity({:fn, _fn_opts, [name: _name, params: params, type: _ret]}), do: length(params) def from_function( {:fn, _fn_opts, [ name: name, params: _params, type: ret ]} = f ) do %__MODULE__{ wrapper_name: name, zig_name: name, arity: arity(f), ret: ret } end # TODO: make this extensible def from_resource_kind(%KindDecl{module_name: module_name, kind_functions: kind_functions}) do for {f, a} <- [ ptr: 1, ptr_to_opaque: 1, opaque_ptr: 1, array: 1, mut_array: 1, primitive: 1, make: 1, dump: 1, make_from_opaque_ptr: 2, array_as_opaque: 1 ] ++ kind_functions do %__MODULE__{ nif_name: Module.concat(module_name, f), arity: a } end end # if zig_name is nil this NIF should be registered by other way. For instance, functions of resource kinds. def gen(%__MODULE__{zig_name: nil}), do: "" def gen(%__MODULE__{zig_name: zig_name, nif_name: nif_name, arity: arity, dirty: dirty}) do dirty_flag = case dirty do :cpu -> "1" :io -> "2" false -> "0" end """ e.ErlNifFunc{.name = "#{nif_name}", .arity = #{arity}, .fptr = #{zig_name}, .flags = #{dirty_flag}}, """ end end