Code.require_file "../helpers/module_info.exs", __DIR__
|
|
|
|
defmodule Alchemist.API.Defl do
|
|
|
|
@moduledoc false
|
|
|
|
alias Alchemist.Helpers.ModuleInfo
|
|
|
|
def request(args) do
|
|
args
|
|
|> normalize
|
|
|> process
|
|
|> IO.puts
|
|
|
|
IO.puts "END-OF-DEFL"
|
|
end
|
|
|
|
def process([nil, function, [context: _, imports: [], aliases: _]]) do
|
|
look_for_kernel_functions(function)
|
|
end
|
|
|
|
def process([nil, function, [context: _, imports: imports, aliases: _ ]]) do
|
|
module = Enum.filter(imports, &ModuleInfo.has_function?(&1, function))
|
|
|> List.first
|
|
|
|
case module do
|
|
nil -> look_for_kernel_functions(function)
|
|
_ -> source(module)
|
|
end
|
|
end
|
|
|
|
def process([module, _function, [context: _, imports: _, aliases: aliases]]) do
|
|
if elixir_module?(module) do
|
|
module
|
|
|> Module.split
|
|
|> ModuleInfo.expand_alias(aliases)
|
|
else
|
|
module
|
|
end |> source
|
|
end
|
|
|
|
defp elixir_module?(module) do
|
|
module == Module.concat(Elixir, module)
|
|
end
|
|
|
|
defp look_for_kernel_functions(function) do
|
|
cond do
|
|
ModuleInfo.docs?(Kernel, function) ->
|
|
source(Kernel)
|
|
ModuleInfo.docs?(Kernel.SpecialForms, function) ->
|
|
source(Kernel.SpecialForms)
|
|
true -> ""
|
|
end
|
|
end
|
|
|
|
defp source([]), do: nil
|
|
defp source(module) when is_list(module) do
|
|
module
|
|
|> Module.concat
|
|
|> do_source
|
|
end
|
|
defp source(module), do: do_source(module)
|
|
|
|
defp do_source(module) do
|
|
if Code.ensure_loaded? module do
|
|
case module.module_info(:compile)[:source] do
|
|
nil -> nil
|
|
source -> List.to_string(source)
|
|
end
|
|
end
|
|
end
|
|
|
|
defp normalize(request) do
|
|
{{expr, context_info}, _} = Code.eval_string(request)
|
|
[module, function] = String.split(expr, ",", parts: 2)
|
|
{module, _} = Code.eval_string(module)
|
|
function = String.to_atom function
|
|
[module, function, context_info]
|
|
end
|
|
end
|