Skip to content

Commit

Permalink
Defd_: derive fun info for omitted default arguments (lower arities)
Browse files Browse the repository at this point in the history
  • Loading branch information
arnodirlam committed Dec 10, 2024
1 parent bb7515e commit 7fb63d9
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 10 deletions.
2 changes: 2 additions & 0 deletions lib/dx/defd_.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ defmodule Dx.Defd_ do
end
```
`args` options will also be derived for functions with omitted default arguments.
2. Using the `@moduledx_` module attribute for module-wide defaults (can only be set once per module):
```elixir
Expand Down
25 changes: 23 additions & 2 deletions lib/dx/defd_/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Dx.Defd_.Compiler do

alias Dx.Defd.Ast

def __compile__(%Macro.Env{module: module}, moduledx_, fun_infos) do
def __compile__(%Macro.Env{module: module}, moduledx_, defd_s) do
existing_clauses =
case Module.get_definition(module, {:__dx_fun_info, 2}) do
{:v1, :def, _meta, clauses} ->
Expand All @@ -29,9 +29,30 @@ defmodule Dx.Defd_.Compiler do
[]
end

# derive fun info for omitting default arguments
fun_infos =
Enum.reduce(defd_s, defd_s, fn
{{name, _arity} = key, %{defaults: defaults, fun_info: fun_info}}, acc ->
defaults
|> Map.keys()
|> Enum.sort(:desc)
|> Enum.reduce({fun_info, acc}, fn arg_index, {fun_info, acc} ->
fun_info = %{
fun_info
| args: List.delete_at(fun_info.args, arg_index),
arity: fun_info.arity - 1
}

acc = Map.put_new(acc, {name, fun_info.arity}, fun_info)
{fun_info, acc}
end)
|> elem(1)
|> Map.put(key, fun_info)
end)

annotated_clauses =
Enum.flat_map(fun_infos, fn
{{name, arity}, %{fun_info: fun_info}} ->
{{name, arity}, fun_info} ->
quote do
def __dx_fun_info(unquote(name), unquote(arity)) do
unquote(Macro.escape(fun_info))
Expand Down
14 changes: 6 additions & 8 deletions test/dx/defd__test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,10 @@ defmodule Dx.Defd_Test do
fun_info(Moduledx_Test, :run, 1)
end

test "with default args" do
test "infers lower arity fun info for default args" do
defmodule DefaultArgsTest do
use Dx.Defd_

@moduledx_ args: %{all: :preload_scope}

@dx_ args: %{0 => :preload_scope, 1 => :fn}
defd_ run(enum, mapper \\ nil) do
if mapper do
Expand All @@ -126,16 +124,16 @@ defmodule Dx.Defd_Test do

assert %FunInfo{
args: [
%ArgInfo{preload_scope: true}
%ArgInfo{preload_scope: true},
%ArgInfo{fn: %FunInfo{}, preload_scope: false}
]
} = fun_info(DefaultArgsTest, :run, 1)
} = fun_info(DefaultArgsTest, :run, 2)

assert %FunInfo{
args: [
%ArgInfo{preload_scope: true},
%ArgInfo{fn: %FunInfo{}, preload_scope: false}
%ArgInfo{preload_scope: true}
]
} = fun_info(DefaultArgsTest, :run, 2)
} = fun_info(DefaultArgsTest, :run, 1)
end
end
end

0 comments on commit 7fb63d9

Please sign in to comment.