Skip to content

Instantly share code, notes, and snippets.

@latachz
Created May 16, 2018 18:42
Show Gist options
  • Save latachz/bdbb24d8b20d7045594135e114924e13 to your computer and use it in GitHub Desktop.
Save latachz/bdbb24d8b20d7045594135e114924e13 to your computer and use it in GitHub Desktop.
macros.elchemy.ex
# Compiled using Elchemy v0.6.6
defmodule Elchemy.Macros do
use Elchemy
@moduledoc """
This module is responsible for defining and using macros in Plugins system for Elchemy.
To use this module you need to import it to your module and use its constructs in the
`meta` definition of your module.
@docs Macro, Do, macro, use, behaviour
"""
def use_macro(mod) do
module = :"Elixir.#{mod}"
quote do
use unquote(module)
end
end
def behaviour_macro(mod) do
module = :"Elixir.#{mod}"
quote do
@behaviour unquote(module)
end
end
def strip_meta(mod) do
mod
|> Module.split
|> Enum.drop(-1)
|> Module.concat
end
@typedoc """
Type of macro expression that go into 'meta' function in a module
"""
@type macro :: :macro
@typedoc """
Declares a block that doesn't get evaluated eagerly but rather passed as an AST to be used later in a macro
"""
@type do__(x) :: {:do, x}
@doc """
FFI function that creates a new macro calling an Elixir function that returns Elixir ast.
For instance:
myMacro =
macro "ModuleContainingAstFunction" "ast_function"
Notice that the function *always* returns a Macro type so that it can only be used in `meta` definition
of a module. That ensures that macros are only called top level, everything in deeper scopes -
like inside functions should only be handled using functions.
"""
@spec macro(String.t, String.t) :: any
curry macro/2
def macro(x1, x2) do
(Elchemy.XDebug.crash("You can't use macro in a browser")).(x1).(x2)
end
@doc """
Use macro is a simple wrapper around Elixir.SpecialForms.use
"""
@spec use(String.t) :: macro
curry use/1
def use(x1) do
(macro("Elchemy.Macros", "use_macro")).(x1)
end
@doc """
Use macro is a simple wrapper around @behaviour module attribute.
"""
@spec behaviour(String.t) :: macro
curry behaviour/1
def behaviour(x1) do
(macro("Elchemy.Macros", "behaviour_macro")).(x1)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment