defmodule A.Vector.Tail do @moduledoc false alias A.Vector.CodeGen, as: C require C alias A.Vector.Node @type t(value) :: Node.t(value | nil) def pop_last(tail, i) do {elem(tail, i), put_elem(tail, i, nil)} end for i <- C.range() do # def partial_map({arg1, arg2, arg3, arg4}, fun, 2) do # {fun.(arg1), fun.(arg2), arg3, arg4} # end def partial_map(unquote(C.array()), fun, unquote(i)) do unquote( C.map_until(i, C.apply_mapper(C.var(fun))) |> C.array() ) end end def partial_filter(tail, fun, i, acc) do do_partial_filter(tail, fun, acc, 1, i + 1) |> :lists.reverse() end @compile {:inline, do_partial_filter: 5} def do_partial_filter(_tail, _fun, acc, stop, stop), do: acc def do_partial_filter(tail, fun, acc, erl_index, stop) do value = :erlang.element(erl_index, tail) new_acc = if fun.(value) do [value | acc] else acc end do_partial_filter(tail, fun, new_acc, erl_index + 1, stop) end for i <- C.range() do # def partial_to_list({arg1, arg2, _arg3, _arg4}, 2) do # [arg1, arg2] # end def partial_to_list(unquote(C.array_with_wildcards(i)), unquote(i)) do unquote(C.arguments(i)) end end C.def_foldl_tail partial_reverse(arg, acc) do [arg | acc] end for i <- C.range() do # def partial_duplicate(value, 2) do # {value, value, nil, nil} # end def partial_duplicate(value, unquote(i)) do unquote( List.duplicate(C.var(value), i) |> C.fill_with(nil) |> C.array() ) end end # def partial_member?({arg1, arg2, arg3, _arg4}, size, value) do # cond do # arg1 === value -> true # size === 1 -> false # arg2 === value -> true # size === 2 -> false # arg3 === value -> true # size === 3 -> false # arg4 === value -> true # true -> false # end # end def partial_member?(unquote(C.array()), size, value) do C.find_cond_tail arg, size do arg === value -> true _ -> false end end # def partial_any?({arg1, arg2, arg3, arg4}, size) do # cond do # arg1 -> true # size === 1 -> false # arg2 -> true # size === 2 -> false # arg3 -> true # size === 3 -> false # arg4 -> true # true -> false # end # end def partial_any?(unquote(C.array()), size) do C.find_cond_tail arg, size do arg -> true _ -> false end end # def partial_any?({arg1, arg2, arg3, arg4}, size, fun) do # cond do # fun.(arg1) -> true # size === 1 -> false # fun.(arg2) -> true # size === 2 -> false # fun.(arg3) -> true # size === 3 -> false # fun.(arg4) -> true # true -> false # end # end def partial_any?(unquote(C.array()), size, fun) do C.find_cond_tail arg, size do fun.(arg) -> true _ -> false end end # def partial_all?({arg1, arg2, arg3, arg4}, size) do # cond do # !arg1 -> false # size === 1 -> true # !arg2 -> false # size === 2 -> true # !arg3 -> false # size === 3 -> true # !arg4 -> false # true -> true # end # end def partial_all?(unquote(C.array()), size) do C.find_cond_tail arg, size do !arg -> false _ -> true end end # def partial_all?({arg1, arg2, arg3, arg4}, size, fun) do # cond do # !fun.(arg1) -> false # size === 1 -> true # !fun.(arg2) -> false # size === 2 -> true # !fun.(arg3) -> false # size === 3 -> true # !fun.(arg4) -> false # true -> true # end # end def partial_all?(unquote(C.array()), size, fun) do C.find_cond_tail arg, size do !fun.(arg) -> false _ -> true end end def partial_find(unquote(C.array()), size, fun) do C.find_cond_tail arg, size do fun.(arg) -> {:ok, arg} _ -> nil end end def partial_find_value(unquote(C.array()), size, fun) do C.find_cond_tail arg, size do value = fun.(arg) -> value _ -> nil end end # def partial_sum({arg1, arg2, arg3, arg4}, size, acc) do # case size do # 1 -> acc + arg1 # 2 -> (acc + arg1) + arg2) # 3 -> ((acc + arg1) + arg2) + arg3 # 4 -> (((acc + arg1) + arg2) + arg3) + arg4 # end # end C.def_foldl_tail partial_sum(arg, acc) do acc + arg end C.def_foldl_tail partial_product(arg, acc) do acc * arg end def partial_intersperse(tail, size, separator) do value = :erlang.element(size, tail) do_partial_intersperse(tail, size - 1, separator, [value]) end @compile {:inline, do_partial_intersperse: 4} defp do_partial_intersperse(_tail, _erl_index = 0, _separator, acc), do: acc defp do_partial_intersperse(tail, erl_index, separator, acc) do value = :erlang.element(erl_index, tail) new_acc = [value, separator | acc] do_partial_intersperse(tail, erl_index - 1, separator, new_acc) end def partial_join_as_iodata(tail, size, separator) do value = :erlang.element(size, tail) |> to_string() do_partial_join_as_iodata(tail, size - 1, separator, [value]) end @compile {:inline, do_partial_join_as_iodata: 4} defp do_partial_join_as_iodata(_tail, _erl_index = 0, _separator, acc), do: acc defp do_partial_join_as_iodata(tail, erl_index, separator, acc) do value = :erlang.element(erl_index, tail) |> to_string() new_acc = [value, separator | acc] do_partial_join_as_iodata(tail, erl_index - 1, separator, new_acc) end def complete_tail(tail, tail_size, values) def complete_tail(tail, _tail_size, []) do {tail, 0, []} end for i <- C.range() do # def complete_tail({arg1, arg2, _arg3, _arg4}, 2, [arg3, arg4 | rest]) do # {{arg1, arg2, arg3, arg4}, 2, rest} # end def complete_tail( unquote(C.array_with_wildcards(i)), unquote(i), unquote(Enum.drop(C.arguments(), i) |> C.list_with_rest(C.var(rest))) ) do {unquote(C.array()), unquote(C.branch_factor() - i), rest} end end for i <- C.range() do # def complete_tail(tail, tail_size, [arg1, arg2]) do # new_tail = put_elem(put_elem(tail, tail_size, arg1), tail_size + 1, arg2) # {new_tail, 2, []} # end def complete_tail(tail, tail_size, unquote(C.arguments(i))) do new_tail = unquote( C.arguments(i) |> Enum.with_index() |> Enum.reduce(C.var(tail), fn {arg, index}, acc -> quote do put_elem(unquote(acc), var!(tail_size) + unquote(index), unquote(arg)) end end) ) {new_tail, unquote(i), []} end end def slice(tail, start, last) do do_slice(tail, start, last, []) end @compile {:inline, do_slice: 4} defp do_slice(tail, i, i, acc) do [elem(tail, i) | acc] end defp do_slice(tail, start, i, acc) do new_acc = [elem(tail, i) | acc] do_slice(tail, start, i - 1, new_acc) end def partial_with_index(tail, tail_size, offset) for i <- C.range() do # def partial_with_index({arg1, arg2, _arg3, _arg4}, 2, offset) do # {{arg1, offset + 0}, {arg2, offset + 1}, nil, nil} # end def partial_with_index(unquote(C.array_with_wildcards(i)), unquote(i), offset) do unquote( C.arguments_with_nils(i) |> Enum.with_index() |> Enum.map(fn {nil, _} -> nil {arg, i} -> quote do {unquote(arg), var!(offset) + unquote(i)} end end) |> C.array() ) end end end