<commit_before>defmodule Phoenix.Router.Mapper do
  alias Phoenix.Router.Path
  alias Phoenix.Controller

  @moduledoc """
  Adds Macros for Route match definitions. All routes are
  compiled to patterm matched def match() definitions for fast
  and efficient lookup by the VM.

  # Examples

  defmodule Router do
    use Phoenix.Router, port: 4000

    get "pages/:page", PagesController, :show, as: :page
    resources "users", UsersController
  end

  Compiles to

    get "pages/:page", PagesController, :show, as: :page

    -> defmatch({:get, "pages/:page", PagesController, :show, [as: :page]})
       defroute_aliases({:get, "pages/:page", PagesController, :show, [as: :page]})

    --> def(match(conn, :get, ["pages", page])) do
          conn = conn.params(Dict.merge(conn.params(), [{"page", page}]))
          apply(PagesController, :show, [conn])
        end
  """

  defmacro __using__(_options) do
    quote do
      Module.register_attribute __MODULE__, :routes, accumulate: true,
                                                     persist: false
      import unquote(__MODULE__)
      @before_compile unquote(__MODULE__)
    end
  end

  defmacro __before_compile__(env) do
    routes = Enum.reverse(Module.get_attribute(env.module, :routes))
    routes_ast = Enum.reduce routes, nil, fn route, acc ->
      quote do
        defmatch(unquote(route))
        defroute_aliases(unquote(route))
        unquote(acc)
      end
    end

    quote do
      unquote(routes_ast)
      def match(conn, method, path), do: Controller.not_found(conn, method, path)
    end
  end

  defmacro defmatch({http_method, path, controller, action, options}) do
    path_args = Path.matched_arg_list_with_ast_bindings(path)
    params_list_with_bindings = Path.params_with_ast_bindings(path)

    quote do
      def unquote(:match)(conn, unquote(http_method), unquote(path_args)) do
        conn = conn.params(Dict.merge(conn.params, unquote(params_list_with_bindings)))

        apply(unquote(controller), unquote(action), [conn])
      end
    end
  end

  defmacro defroute_aliases({http_method, path, controller, action, options}) do
    alias_name = options[:as]
    quote do
      if unquote(alias_name) do
        def unquote(binary_to_atom "#{alias_name}_path")(params) do
          Path.build(unquote(path), params)
        end
        # TODO: use config based domain for URL
        def unquote(binary_to_atom "#{alias_name}_url")(params) do
          Path.build(unquote(path), params)
        end
      end
    end
  end

  defmacro get(path, controller, action, options // []) do
    add_route(:get, path, controller, action, options)
  end

  defmacro post(path, controller, action, options // []) do
    add_route(:post, path, controller, action, options)
  end

  defmacro put(path, controller, action, options // []) do
    add_route(:put, path, controller, action, options)
  end

  defmacro patch(path, controller, action, options // []) do
    add_route(:patch, path, controller, action, options)
  end

  defmacro delete(path, controller, action, options // []) do
    add_route(:delete, path, controller, action, options)
  end

  defp add_route(verb, path, controller, action, options // []) do
    quote bind_quoted: [verb: verb,
                        path: path,
                        controller: controller,
                        action: action,
                        options: options] do
      @routes {
        verb,
        Phoenix.Router.Context.current_prefix(path, __MODULE__),
        controller,
        action,
        options
      }
    end
  end

  defmacro resources(prefix, controller, options // []) do
    nested_route  = Keyword.get(options, :do)
    options       = Keyword.delete(options, :do)

    quote unquote: true, bind_quoted: [options: options,
                                       prefix: prefix,
                                       controller: controller] do

      get    "#{prefix}/:id", controller, :show, options
      get    "#{prefix}/new", controller, :new, options
      get    "#{prefix}",     controller, :index, options
      post   "#{prefix}",     controller, :create, options
      put    "#{prefix}/:id", controller, :update, options
      patch  "#{prefix}/:id", controller, :update, options
      delete "#{prefix}/:id", controller, :destroy, options


      Phoenix.Router.Context.push(prefix, __MODULE__)
      unquote(nested_route)
      Phoenix.Router.Context.pop(__MODULE__)
    end
  end
end

<commit_msg>Preserve routes as list for runtime.<commit_after>defmodule Phoenix.Router.Mapper do
  alias Phoenix.Router.Path
  alias Phoenix.Controller

  @moduledoc """
  Adds Macros for Route match definitions. All routes are
  compiled to patterm matched def match() definitions for fast
  and efficient lookup by the VM.

  # Examples

  defmodule Router do
    use Phoenix.Router, port: 4000

    get "pages/:page", PagesController, :show, as: :page
    resources "users", UsersController
  end

  Compiles to

    get "pages/:page", PagesController, :show, as: :page

    -> defmatch({:get, "pages/:page", PagesController, :show, [as: :page]})
       defroute_aliases({:get, "pages/:page", PagesController, :show, [as: :page]})

    --> def(match(conn, :get, ["pages", page])) do
          conn = conn.params(Dict.merge(conn.params(), [{"page", page}]))
          apply(PagesController, :show, [conn])
        end
  """

  defmacro __using__(_options) do
    quote do
      Module.register_attribute __MODULE__, :routes, accumulate: true,
                                                     persist: false
      import unquote(__MODULE__)
      @before_compile unquote(__MODULE__)
    end
  end

  defmacro __before_compile__(env) do
    routes = Enum.reverse(Module.get_attribute(env.module, :routes))
    routes_ast = Enum.reduce routes, nil, fn route, acc ->
      quote do
        defmatch(unquote(route))
        defroute_aliases(unquote(route))
        unquote(acc)
      end
    end

    quote do
      def routes do
        [unquote_splicing(Macro.escape(routes))]
      end
      unquote(routes_ast)
      def match(conn, method, path), do: Controller.not_found(conn, method, path)
    end
  end

  defmacro defmatch({http_method, path, controller, action, options}) do
    path_args = Path.matched_arg_list_with_ast_bindings(path)
    params_list_with_bindings = Path.params_with_ast_bindings(path)

    quote do
      def unquote(:match)(conn, unquote(http_method), unquote(path_args)) do
        conn = conn.params(Dict.merge(conn.params, unquote(params_list_with_bindings)))

        apply(unquote(controller), unquote(action), [conn])
      end
    end
  end

  defmacro defroute_aliases({http_method, path, controller, action, options}) do
    alias_name = options[:as]
    quote do
      if unquote(alias_name) do
        def unquote(binary_to_atom "#{alias_name}_path")(params) do
          Path.build(unquote(path), params)
        end
        # TODO: use config based domain for URL
        def unquote(binary_to_atom "#{alias_name}_url")(params) do
          Path.build(unquote(path), params)
        end
      end
    end
  end

  defmacro get(path, controller, action, options // []) do
    add_route(:get, path, controller, action, options)
  end

  defmacro post(path, controller, action, options // []) do
    add_route(:post, path, controller, action, options)
  end

  defmacro put(path, controller, action, options // []) do
    add_route(:put, path, controller, action, options)
  end

  defmacro patch(path, controller, action, options // []) do
    add_route(:patch, path, controller, action, options)
  end

  defmacro delete(path, controller, action, options // []) do
    add_route(:delete, path, controller, action, options)
  end

  defp add_route(verb, path, controller, action, options // []) do
    quote bind_quoted: [verb: verb,
                        path: path,
                        controller: controller,
                        action: action,
                        options: options] do
      @routes {
        verb,
        Phoenix.Router.Context.current_prefix(path, __MODULE__),
        controller,
        action,
        options
      }
    end
  end

  defmacro resources(prefix, controller, options // []) do
    nested_route  = Keyword.get(options, :do)
    options       = Keyword.delete(options, :do)

    quote unquote: true, bind_quoted: [options: options,
                                       prefix: prefix,
                                       controller: controller] do

      get    "#{prefix}/:id", controller, :show, options
      get    "#{prefix}/new", controller, :new, options
      get    "#{prefix}",     controller, :index, options
      post   "#{prefix}",     controller, :create, options
      put    "#{prefix}/:id", controller, :update, options
      patch  "#{prefix}/:id", controller, :update, options
      delete "#{prefix}/:id", controller, :destroy, options


      Phoenix.Router.Context.push(prefix, __MODULE__)
      unquote(nested_route)
      Phoenix.Router.Context.pop(__MODULE__)
    end
  end
end


{'fraction_non_alphanumeric': 0.11182038300682369, 'fraction_numerical': 0.0008804754567466431, 'mean_word_length': 2.63625450180072, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7363558', 'n_tokens_mistral': 2697, 'n_tokens_neox': 2638, 'n_words': 714}