ExTorch.Native.Macros (extorch v0.1.0-pre0)

General purpose macros to automatically generate binding declarations and calls for both ExTorch callable functions and Rustler signature calls to the NIF library.

Link to this section Summary

Functions

Automatic binding generation.

Link to this section Functions

Link to this macro

defbindings(doc_section, list)

(macro)

Automatic binding generation.

This macro allows to define a bindings block under a given doc_section for a given set of function bindings. All binding declarations should be signaled using the defbinding function, which recieves the function signature, alongside an optional keyword list of parameter transformations that must be done before calling the native function (defined in ExTorch.Native).

Each defbinding declaration must declare its @spec and optionally its docstring @doc before the call. Additionally, the function binding signature can declare optional arguments. For example:

  # All function docstrings will be collected under :doc_section_name
  defbindings(:doc_section_name) do
    @doc """
    The docstring for func goes here
    """
    @spec func(type_1(), type_2(), type_3()) :: ret_type()
    defbinding(
      func(
        arg1,                    # Positional argument
        arg2 \\ optional_value,  # Optional argument
        arg3 \\ optional_value   # Optional argument
      )
    )

    @doc """
    The docstring for func2 goes here
    """
    @spec func2(type_1(), type_2(), type_3(), type_4()) :: ret_type()
    defbinding(
      func2(
        arg1 \\ optional_value,  # Positional argument with optional value
        arg2,                    # Positional argument
        arg3 \\ optional_value,  # Optional argument
        arg4 \\ optional_value   # Optional argument
      )
    )

    @doc """
    The docstring for func3 goes here
    """
    @spec func3(type_1(), type_2(), type_3(), type_4()) :: ret_type()
    defbinding(
      func3(
        arg1,                    # Positional argument
        arg2,                    # Positional argument
        arg3 \\ optional_value,  # Optional argument
        arg4 \\ optional_value   # Optional argument
      ),
      arg1: arg1[:value],
      arg3: call_to_some_transform(arg3, arg2),
    )
  end

In case optional arguments are defined, the macro will expand the declaration to allow optional arguments to be passed as a keyword list. For example, the function func will be expanded to the following function calls: func(arg1), func(arg1, kwargs), func(arg1, arg2), func(arg1, arg2, kwargs) and func(arg1, arg2, arg3), where kwargs correspond to arg2: value, arg3: value2 and arg3: value, respectively.

When the first argument is declared as optional, the macro will generate function calls that begin with the first argument as well as the second argument. In case there are multiple calls with the same arity, the macro will try to disambiguate them by computing the corresponding guards that distinguish each call from the others. In the case of func2, the expanded definitions would correspond to func2(arg2) func2(arg2, kwargs), func2(arg2, arg3, kwargs), func2(arg2, arg3, arg4), func2(arg1, arg2), func2(arg1, arg2, kwargs), func2(arg1, arg2, arg3), etc.

Finally, if transforms are defined (like func3), they will be assigned to the specified arguments before calling the native function.