Skip to content

Commit

Permalink
Merge pull request #94 from florius0/refator/use-witchcraft
Browse files Browse the repository at this point in the history
Refator/use witchcraft
  • Loading branch information
jechol authored Nov 18, 2021
2 parents 1c634c3 + 95aeed5 commit c2b3e86
Show file tree
Hide file tree
Showing 19 changed files with 135 additions and 242 deletions.
19 changes: 9 additions & 10 deletions lib/witchcraft.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,13 @@ defmodule Witchcraft do
the dependency chart (above).
"""

defmacro __using__(opts \\ []) do
quote do
use Witchcraft.Arrow, unquote(opts)
use Witchcraft.Monoid, unquote(opts)
use Witchcraft.Bifunctor, unquote(opts)
use Witchcraft.Traversable, unquote(opts)
use Witchcraft.Monad, unquote(opts)
use Witchcraft.Comonad, unquote(opts)
end
end
use Witchcraft.Internal,
deps: [
Witchcraft.Arrow,
Witchcraft.Monoid,
Witchcraft.Bifunctor,
Witchcraft.Traversable,
Witchcraft.Monad,
Witchcraft.Comonad
]
end
12 changes: 3 additions & 9 deletions lib/witchcraft/applicative.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,12 @@ defclass Witchcraft.Applicative do
"""

alias __MODULE__
extend Witchcraft.Apply

@type t :: any()
extend Witchcraft.Apply

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]
use Witchcraft.Internal, deps: [Witchcraft.Apply]

quote do
use Witchcraft.Apply, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end
@type t :: any()

where do
@doc """
Expand Down
16 changes: 5 additions & 11 deletions lib/witchcraft/apply.ex
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,18 @@ defclass Witchcraft.Apply do
"""

alias __MODULE__
use Quark

alias Witchcraft.Functor

extend Witchcraft.Functor

use Witchcraft.Internal, deps: [Witchcraft.Functor]

use Witchcraft.Functor
use Quark

@type t :: any()
@type fun :: any()

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]

quote do
use Witchcraft.Functor, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end

where do
@doc """
Pipe arguments to functions, when both are wrapped in the same
Expand Down
12 changes: 3 additions & 9 deletions lib/witchcraft/arrow.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,12 @@ defclass Witchcraft.Arrow do

alias __MODULE__
extend Witchcraft.Category
use Witchcraft.Category

@type t :: fun()
use Witchcraft.Internal, deps: [Witchcraft.Category]

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]
use Witchcraft.Category

quote do
use Witchcraft.Category, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end
@type t :: fun()

where do
@doc """
Expand Down
14 changes: 4 additions & 10 deletions lib/witchcraft/bifunctor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,16 @@ defclass Witchcraft.Bifunctor do
"""

alias __MODULE__

extend Witchcraft.Functor

alias __MODULE__
use Witchcraft.Internal

use Quark

@type t :: any()

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]

quote do
use Witchcraft.Functor, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end

where do
@doc """
`map` separate fuctions over two fields in a product type.
Expand Down
11 changes: 2 additions & 9 deletions lib/witchcraft/category.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,9 @@ defclass Witchcraft.Category do

extend Witchcraft.Semigroupoid

@type t :: any()

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]
use Witchcraft.Internal, deps: [Witchcraft.Semigroupoid]

quote do
use Witchcraft.Semigroupoid, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end
@type t :: any()

where do
@doc """
Expand Down
13 changes: 4 additions & 9 deletions lib/witchcraft/chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,16 @@ defclass Witchcraft.Chain do
"""

alias __MODULE__

extend Witchcraft.Apply

use Witchcraft.Internal, deps: [Witchcraft.Apply]

use Witchcraft.Apply

@type t :: any()
@type link :: (any() -> Chain.t())

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]

quote do
use Witchcraft.Apply, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end

where do
@doc """
Sequentially compose actions, piping values through successive function chains.
Expand Down
13 changes: 4 additions & 9 deletions lib/witchcraft/comonad.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,14 @@ defclass Witchcraft.Comonad do
"""

alias __MODULE__

extend Witchcraft.Extend
use Quark

@type t :: any()
use Witchcraft.Internal, deps: [Witchcraft.Extend]

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]
use Quark

quote do
use Witchcraft.Extend, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end
@type t :: any()

where do
@doc """
Expand Down
12 changes: 3 additions & 9 deletions lib/witchcraft/extend.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,18 @@ defclass Witchcraft.Extend do
"""

alias __MODULE__

alias Witchcraft.Functor

extend Witchcraft.Functor

use Witchcraft.Internal, deps: [Witchcraft.Functor]

use Quark

@type t :: any()
@type colink :: (Extend.t() -> any())

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]

quote do
use Witchcraft.Functor, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end

where do
@doc """
Wrap some nestable data structure in another layer of itself
Expand Down
30 changes: 2 additions & 28 deletions lib/witchcraft/foldable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,43 +30,17 @@ defclass Witchcraft.Foldable do
alias __MODULE__
alias Witchcraft.{Apply, Ord, Monad, Monoid, Semigroup, Unit}

import Kernel, except: [length: 1, max: 2, min: 2]
import Exceptional.Safe, only: [safe: 1]

require Foldable.EmptyError

use Witchcraft.Internal, overrides: [min: 2, max: 2, length: 1], deps: [Semigroup, Ord]

use Witchcraft.Applicative
use Quark

@type t :: any()

defmacro __using__(opts \\ []) do
overrides = [length: 1, max: 2, min: 2]
excepts = Keyword.get(opts, :except, [])

if Access.get(opts, :override_kernel, true) do
kernel_imports = Macro.escape(except: overrides -- excepts)
module_imports = Macro.escape(except: excepts)

quote do
use Witchcraft.Semigroup, unquote(opts)
use Witchcraft.Ord, unquote(opts)

import Kernel, unquote(kernel_imports)
import unquote(__MODULE__), unquote(module_imports)
end
else
module_imports = Macro.escape(except: Enum.uniq(overrides ++ excepts))

quote do
use Witchcraft.Semigroup, unquote(opts)
use Witchcraft.Ord, unquote(opts)

import unquote(__MODULE__), unquote(module_imports)
end
end
end

where do
@doc ~S"""
Right-associative fold over a structure to alter the structure and/or reduce
Expand Down
11 changes: 3 additions & 8 deletions lib/witchcraft/functor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,12 @@ defclass Witchcraft.Functor do
"""

alias __MODULE__
use Quark

@type t :: any()
use Witchcraft.Internal

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]
use Quark

quote do
import unquote(__MODULE__), unquote(module_imports)
end
end
@type t :: any()

where do
@doc ~S"""
Expand Down
77 changes: 77 additions & 0 deletions lib/witchcraft/internal.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
defmodule Witchcraft.Internal do
@moduledoc """
A module for handling `use Witchcraft` and other modules
Provides support for overriding `Kernel` functions and for auto dependencies using via `__using__/1` macro.
"""

@doc ~S"""
Generates `Kernel` import and `__using__/1` macro in module where used.
## Options
- `:overrides` – List of overrides in module where used
- `:deps` – List of modules that will be used in generated `__using__/1` macro
## Generated `__using__(opts \\ [])` macro supports the following options:
- `:override_kernel` – If true, overrides function from `Kernel` in module where used. Defaults to true
- `:except` and `:only` – Keyword of functions (Like in [import](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#import/2-selector)). Example: `[fun: <arity>]` where `<arity>` is function `fun` arity
"""
defmacro __using__(opts \\ []) do
overrides = Keyword.get(opts, :overrides, [])
deps = Keyword.get(opts, :deps, [])

quote do
@overrides unquote(overrides)

import Kernel, except: unquote(overrides)

defmacro __using__(opts \\ []) do
Witchcraft.Internal.import_helper(opts, unquote(overrides), unquote(deps), __MODULE__)
end
end
end

@doc false
def import_helper(opts, overrides, deps, module) do
excepts = Keyword.get(opts, :except, [])
only = Keyword.get(opts, :only)
deps_quoted = use_multi(deps, opts)

if Keyword.get(opts, :override_kernel, true) do
kernel_imports = kernel_imports(overrides -- excepts, only)
module_imports = module_imports(excepts, only)

quote do
import Kernel, unquote(kernel_imports)

unquote(deps_quoted)

import unquote(module), unquote(module_imports)
end
else
module_imports = module_imports(Enum.uniq(overrides ++ excepts), only)

quote do
unquote(deps_quoted)

import unquote(module), unquote(module_imports)
end
end
end

defp use_multi(modules, opts) do
for module <- modules do
quote do
use unquote(module), unquote(opts)
end
end
end

defp kernel_imports(excepts, nil), do: Macro.escape(except: excepts)
defp kernel_imports(_, only), do: Macro.escape(except: only)

defp module_imports(excepts, nil), do: Macro.escape(except: excepts)
defp module_imports(excepts, only), do: Macro.escape(only: only -- excepts)
end
12 changes: 2 additions & 10 deletions lib/witchcraft/monad.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,11 @@ defclass Witchcraft.Monad do
extend Witchcraft.Applicative
extend Witchcraft.Chain

use Witchcraft.Internal, deps: [Witchcraft.Applicative, Witchcraft.Chain]

use Witchcraft.Applicative
use Witchcraft.Chain

defmacro __using__(opts \\ []) do
module_imports = [except: Keyword.get(opts, :except, [])]

quote do
use Witchcraft.Applicative, unquote(opts)
use Witchcraft.Chain, unquote(opts)
import unquote(__MODULE__), unquote(module_imports)
end
end

properties do
import Witchcraft.Applicative
import Witchcraft.Chain
Expand Down
Loading

0 comments on commit c2b3e86

Please sign in to comment.