View Source Routex.Branching (Phoenix Routes Extension Framework v0.3.0-alpha.4)

Provides a function to build branched variants of macro's

Summary

Functions

Takes a list of match patterns and creates the AST for branching variants for all arities of macro in module by wrapping them in a case statement.

Functions

Link to this function

branch_macro(patterns, match_binding, module, macro, opts \\ [])

View Source

Takes a list of match patterns and creates the AST for branching variants for all arities of macro in module by wrapping them in a case statement.

Args

  • patterns: the match patterns to be used as case clauses
  • match_binding: ast inserted as case [match_binding] do
  • module: the module name
  • macro: the macro name
  • opts: list of options

Options

  • arities: a list of arities to transform, default: all arities
  • as: name of the branching variant. default: the macro name
  • arg_post: function to calculate the replaced argument position. default: 0

The clauses and arguments can be transformed by providing MFA's. The transformers receive as arguments the pattern, the banched arg and any other argument provided in a.

  • clause_transformer: {m,f,a}. transforms a pattern; used as case clause in the macro body.
  • arg_transformer: {m,f,a}. transforms a branched argument; used in the macro body.

Example

We want to create a branching variant of the url macro in Phoenix,.VerifiedRoutes module. The original macro generates code that simply prints the given path argument, but we want to it to write multiple clauses and prefix the given argument based on the clause.

defmacro url(path, opts \ []) do -> quote do IO.puts(path) end

Given this code:

defmodule MyMod do

def transform_arg(pattern, arg, extra), do: "/" <> extra <> "/europe/" <> pattern <> "/" <> arg end

end

patterns = ["en", "nl"] match_binding = var!(external_var) arg_pos = fn arity -> arity - 1 end) arg_transformer = {MyMod, transform_arg, ["my_extra"]} opts = [as: :url, orig: :url_original, arg_pos: arg_pos, arg_transformer: arg_transformer]

branch_macro(patterns, match_binding, OriginalModule, :url, opts)

A new macro is build which outputs the AST of the original macro, wrapped in a case clause given transformed arguments.

defmacro url(path, opts \ []) do

  quote do
    case external_var do
         "en" -> Original.Module.url( "/" <> "my_extra" <> "/europe/en/" <> path, opts)
         "nl" -> Original.Module.url("/" <> "my_extra" <> "/europe/nl/" <> path, opts)
     end
 end

end

For more examples, please see the test module Routex.BranchingTest.