You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

80 lines
1.9 KiB

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