Fix typo in code formatter (#7582)

Fix typo in code formatter (#7582)

defmodule Code do
  @moduledoc """
  Utilities for managing code compilation, code evaluation, and code loading.

  This module complements Erlang's [`:code` module](http://www.erlang.org/doc/man/code.html)
  to add behaviour which is specific to Elixir. Almost all of the functions in this module
  have global side effects on the behaviour of Elixir.

  ## Working with files

  This module contains three functions for compiling and evaluating files.
  Here is a summary of them and their behaviour:

    * `require_file/2` - compiles a file and tracks its name. It does not
      compile the file again if it has been previously required.

    * `compile_file/2` - compiles a file without tracking its name. Compiles the
      file multiple times when invoked multiple times.

    * `eval_file/2` - evaluates the file contents without tracking its name. It
      returns the result of the last expression in the file, instead of the modules
      defined in it.

  In a nutshell, the first must be used when you want to keep track of the files
  handled by the system, to avoid the same file from being compiled multiple
  times. This is common in scripts.

  `compile_file/2` must be used when you are interested in the modules defined in a
  file, without tracking. `eval_file/2` should be used when you are intested on
  the result of evaluating the file rather than the modules it defines.
  """

  @doc """
  Lists all required files.

  ## Examples

      Code.require_file("../eex/test/eex_test.exs")
      List.first(Code.required_files()) =~ "eex_test.exs"
      #=> true

  """
  @since "1.7.0"
  @spec required_files() :: [binary]
  def required_files do
    :elixir_code_server.call(:required)
  end

  # TODO: Deprecate me on 1.9
  @doc false
  def loaded_files do
    required_files()
  end

  @doc """
  Removes files from the required files list.

  The modules defined in the file are not removed;
  calling this function only removes them from the list,
  allowing them to be required again.

  ## Examples

      # Require EEx test code
      Code.require_file("../eex/test/eex_test.exs")

      # Now unrequire all files
      Code.unrequire_files(Code.required_files())

      # Notice modules are still available
      function_exported?(EExTest.Compiled, :before_compile, 0)
      #=> true

  """
  @spec unrequire_files([binary]) :: :ok
  @since "1.7.0"
  def unrequire_files(files) do
    :elixir_code_server.cast({:unrequire_files, files})
  end

  # TODO: Deprecate me on 1.9
  @doc false
  def unload_files(files) do
    unrequire_files(files)
  end

  @doc """
  Appends a path to the end of the Erlang VM code path list.

  This is the list of directories the Erlang VM uses for
  finding module code.

  The path is expanded with `Path.expand/1` before being appended.
  If this path does not exist, an error is returned.

  ## Examples

      Code.append_path(".")
      #=> true

      Code.append_path("/does_not_exist")
      #=> {:error, :bad_directory}

  """
  @spec append_path(Path.t()) :: true | {:error, :bad_directory}
  def append_path(path) do
    :code.add_pathz(to_charlist(Path.expand(path)))
  end

  @doc """
  Prepends a path to the beginning of the Erlang VM code path list.

  This is the list of directories the Erlang VM uses for finding
  module code.

  The path is expanded with `Path.expand/1` before being prepended.
  If this path does not exist, an error is returned.

  ## Examples

      Code.prepend_path(".")
      #=> true

      Code.prepend_path("/does_not_exist")
      #=> {:error, :bad_directory}

  """
  @spec prepend_path(Path.t()) :: true | {:error, :bad_directory}
  def prepend_path(path) do
    :code.add_patha(to_charlist(Path.expand(path)))
  end

  @doc """
  Deletes a path from the Erlang VM code path list. This is the list of
  directories the Erlang VM uses for finding module code.

  The path is expanded with `Path.expand/1` before being deleted. If the
  path does not exist, this function returns `false`.

  ## Examples

      Code.prepend_path(".")
      Code.delete_path(".")
      #=> true

      Code.delete_path("/does_not_exist")
      #=> false

  """
  @spec delete_path(Path.t()) :: boolean
  def delete_path(path) do
    :code.del_path(to_charlist(Path.expand(path)))
  end

  @doc """
  Evaluates the contents given by `string`.

  The `binding` argument is a keyword list of variable bindings.
  The `opts` argument is a keyword list of environment options.

  **Warning**: `string` can be any Elixir code and will be executed with
  the same privileges as the Erlang VM: this means that such code could
  compromise the machine (for example by executing system commands).
  Don't use `eval_string/3` with untrusted input (such as strings coming
  from the network).

  ## Options

  Options can be:

    * `:file` - the file to be considered in the evaluation

    * `:line` - the line on which the script starts

  Additionally, the following scope values can be configured:

    * `:aliases` - a list of tuples with the alias and its target

    * `:requires` - a list of modules required

    * `:functions` - a list of tuples where the first element is a module
      and the second a list of imported function names and arity; the list
      of function names and arity must be sorted

    * `:macros` - a list of tuples where the first element is a module
      and the second a list of imported macro names and arity; the list
      of function names and arity must be sorted

  Notice that setting any of the values above overrides Elixir's default
  values. For example, setting `:requires` to `[]` will no longer
  automatically require the `Kernel` module. In the same way setting
  `:macros` will no longer auto-import `Kernel` macros like `Kernel.if/2`,
  `Kernel.SpecialForms.case/2`, and so on.

  Returns a tuple of the form `{value, binding}`,
  where `value` is the value returned from evaluating `string`.
  If an error occurs while evaluating `string` an exception will be raised.

  `binding` is a keyword list with the value of all variable bindings
  after evaluating `string`. The binding key is usually an atom, but it
  may be a tuple for variables defined in a different context.

  ## Examples

      iex> Code.eval_string("a + b", [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
      {3, [a: 1, b: 2]}

      iex> Code.eval_string("c = a + b", [a: 1, b: 2], __ENV__)
      {3, [a: 1, b: 2, c: 3]}

      iex> Code.eval_string("a = a + b", [a: 1, b: 2])
      {3, [a: 3, b: 2]}

  For convenience, you can pass `__ENV__/0` as the `opts` argument and
  all imports, requires and aliases defined in the current environment
  will be automatically carried over:

      iex> Code.eval_string("a + b", [a: 1, b: 2], __ENV__)
      {3, [a: 1, b: 2]}

  """
  @spec eval_string(List.Chars.t(), list, Macro.Env.t() | keyword) :: {term, binding :: list}
  def eval_string(string, binding \\ [], opts \\ [])

  def eval_string(string, binding, %Macro.Env{} = env) do
    {value, binding, _env, _scope} = :elixir.eval(to_charlist(string), binding, Map.to_list(env))
    {value, binding}
  end

  def eval_string(string, binding, opts) when is_list(opts) do
    validate_eval_opts(opts)
    {value, binding, _env, _scope} = :elixir.eval(to_charlist(string), binding, opts)
    {value, binding}
  end

  @doc ~S"""
  Formats the given code `string`.

  The formatter receives a string representing Elixir code and
  returns iodata representing the formatted code according to
  pre-defined rules.

  ## Options

    * `:file` - the file which contains the string, used for error
      reporting

    * `:line` - the line the string starts, used for error reporting

    * `:line_length` - the line length to aim for when formatting
      the document. Defaults to 98.

    * `:locals_without_parens` - a keyword list of name and arity
      pairs that should be kept without parens whenever possible.
      The arity may be the atom `:*`, which implies all arities of
      that name. The formatter already includes a list of functions
      and this option augments this list.

    * `:rename_deprecated_at` - rename all known deprecated functions
      at the given version to their non-deprecated equivalent. It
      expects a valid `Version` which is usually the minimum Elixir
      version supported by the project.

  ## Design principles

  The formatter was designed under three principles.

  First, the formatter never changes the semantics of the code by
  default. This means the input AST and the output AST are equivalent.
  Optional behaviour, such as `:rename_deprecated_at`, is allowed to
  break this guarantee.

  The second principle is to provide as little configuration as possible.
  This eases the formatter adoption by removing contention points while
  making sure a single style is followed consistently by the community as
  a whole.

  The formatter does not hard code names. The formatter will not behave
  specially because a function is named `defmodule`, `def`, etc. This
  principle mirrors Elixir's goal of being an extensible language where
  developers can extend the language with new constructs as if they were
  part of the language. When it is absolutely necessary to change behaviour
  based on the name, this behaviour should be configurable, such as the
  `:locals_without_parens` option.

  ## Keeping user's formatting

  The formatter respects the input format in some cases. Those are
  listed below:

    * Insignificant digits in numbers are kept as is. The formatter
      however always inserts underscores for decimal numbers with more
      than 5 digits and converts hexadecimal digits to uppercase

    * Strings, charlists, atoms and sigils are kept as is. No character
      is automatically escaped or unescaped. The choice of delimiter is
      also respected from the input

    * Newlines inside blocks are kept as in the input except for:
      1) expressions that take multiple lines will always have an empty
      line before and after and 2) empty lines are always squeezed
      together into a single empty line

    * The choice between `:do` keyword and `do/end` blocks is left
      to the user

    * Lists, tuples, bitstrings, maps, structs and function calls will be
      broken into multiple lines if they are followed by a newline in the
      opening bracket and preceded by a new line in the closing bracket

    * Pipeline operators, like `|>` and others with the same precedence,
      will span multiple lines if they spanned multiple lines in the input

  The behaviours above are not guaranteed. We may remove or add new
  rules in the future. The goal of documenting them is to provide better
  understanding on what to expect from the formatter.

  ## Adjusting formatted output

  The formatter attempts to fit the most it can on a single line.
  When the code does not fit a single line, the formatter introduces
  line breaks in the code.

  In some rare situations, this may lead to undesired formatting.
  For example, the code below:

      "this is a very long string ... #{inspect(some_value)}"

  may be formatted as:

      "this is a very long string ... #{
        inspect(some_value)
      }"

  This happens because the only place the formatter can introduce a
  new line without changing the code semantics is in the interpolation.
  In those scenarios, we recommend developers to directly adjust the
  code. Here we can use the binary concatenation operator `<>/2`:

      "this is a very long string " <>
        "... #{inspect(some_value)}"

  The string concatenation makes the code fit on a single line and also
  gives more options to the formatter.

  A similar example is when the formatter breaks a function definition
  over multiple clauses:

      def my_function(
        %User{name: name, age: age, ...},
        arg1,
        arg2
      ) do

  While the code above is completely valid, you may prefer to match on
  the struct variables inside the function body in order to keep the
  definition on a single line:

      def my_function(%User{} = user, arg1, arg2) do
        %{name: name, age: age, ...} = user

  Since the formatter cannot change the semantics of your code,
  sometimes it is necessary to tweak the code to get optimal formatting.

  ### Multi-line lists, maps, tuples, etc

  You can force lists, tuples, bitstrings, maps, structs and function
  calls to have one entry per line by adding a newline after the opening
  bracket and a new line before the closing bracket lines. For example:

      [
        foo,
        bar
      ]

  If there are no newlines around the brackets, then the formatter will
  try to fit everything on a single line, such that the snippet below

      [foo,
       bar]

  will be formatted as

      [foo, bar]

  You can also force function calls and keywords to be rendered on multiple
  lines by having each entry on its own line:

      defstruct name: nil,
                age: 0

  The code above will be kept with one keyword entry per line by the
  formatter. To avoid that, just squash everything into a single line.

  ### Parens and no parens in function calls

  Elixir has two syntaxes for function calls. With parens and no parens.
  By default, Elixir will add parens to all calls except for:

    1. calls that have do/end blocks
    2. local calls without parens where the name and arity of the local
       call is also listed under `:locals_without_parens`

  The choice of parens and no parens also affects indentation. When a
  function call with parens doesn't fit on the same line, the formatter
  introduces a newline around parens and indents the arguments with two
  spaces:

      some_call(
        arg1,
        arg2,
        arg3
      )

  On the other hand, function calls without parens are always indented
  by the function call length itself, like this:

      some_call arg1,
                arg2,
                arg3

  If the last argument is a data structure, such as maps and lists, and
  the beginning of the data structure fits on the same line as the function
  call, then no indentation happens, this allows code like this:

      Enum.reduce(some_collection, initial_value, fn element, acc ->
        # code
      end)

      some_funtion_without_parens %{
        foo: :bar,
        baz: :bat
      }

  ## Code comments

  The formatter also handles code comments in a way to guarantee a space
  is always added between the beginning of the comment (#) and the next
  character.

  The formatter also extracts all trailing comments to their previous line.
  For example, the code below

      hello # world

  will be rewritten to

      # world
      hello

  Because code comments are handled apart from the code representation (AST),
  there are some situations where code comments are seen as ambiguous by the
  code formatter. For example, the comment in the anonymous function below

      fn
        arg1 ->
          body1
          # comment

        arg2 ->
          body2
      end

  and in this one

      fn
        arg1 ->
          body1

        # comment
        arg2 ->
          body2
      end

  are considered equivalent (the nesting is discarded alongside most of
  user formatting). In such cases, the code formatter will always format to
  the latter.
  """
  @since "1.6.0"
  @spec format_string!(binary, keyword) :: iodata
  def format_string!(string, opts \\ []) when is_binary(string) and is_list(opts) do
    line_length = Keyword.get(opts, :line_length, 98)
    algebra = Code.Formatter.to_algebra!(string, opts)
    Inspect.Algebra.format(algebra, line_length)
  end

  @doc """
  Formats a file.

  See `format_string!/2` for more information on code formatting and
  available options.
  """
  @since "1.6.0"
  @spec format_file!(binary, keyword) :: iodata
  def format_file!(file, opts \\ []) when is_binary(file) and is_list(opts) do
    string = File.read!(file)
    formatted = format_string!(string, [file: file, line: 1] ++ opts)
    [formatted, ?\n]
  end

  @doc """
  Evaluates the quoted contents.

  **Warning**: Calling this function inside a macro is considered bad
  practice as it will attempt to evaluate runtime values at compile time.
  Macro arguments are typically transformed by unquoting them into the
  returned quoted expressions (instead of evaluated).

  See `eval_string/3` for a description of bindings and options.

  ## Examples

      iex> contents = quote(do: var!(a) + var!(b))
      iex> Code.eval_quoted(contents, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
      {3, [a: 1, b: 2]}

  For convenience, you can pass `__ENV__/0` as the `opts` argument and
  all options will be automatically extracted from the current environment:

      iex> contents = quote(do: var!(a) + var!(b))
      iex> Code.eval_quoted(contents, [a: 1, b: 2], __ENV__)
      {3, [a: 1, b: 2]}

  """
  @spec eval_quoted(Macro.t(), list, Macro.Env.t() | keyword) :: {term, binding :: list}
  def eval_quoted(quoted, binding \\ [], opts \\ [])

  def eval_quoted(quoted, binding, %Macro.Env{} = env) do
    {value, binding, _env, _scope} = :elixir.eval_quoted(quoted, binding, Map.to_list(env))
    {value, binding}
  end

  def eval_quoted(quoted, binding, opts) when is_list(opts) do
    validate_eval_opts(opts)
    {value, binding, _env, _scope} = :elixir.eval_quoted(quoted, binding, opts)
    {value, binding}
  end

  defp validate_eval_opts(opts) do
    if f = opts[:functions], do: validate_imports(:functions, f)
    if m = opts[:macros], do: validate_imports(:macros, m)
    if a = opts[:aliases], do: validate_aliases(:aliases, a)
    if r = opts[:requires], do: validate_requires(:requires, r)
  end

  defp validate_requires(kind, requires) do
    valid = is_list(requires) and Enum.all?(requires, &is_atom(&1))

    unless valid do
      raise ArgumentError, "expected :#{kind} option given to eval in the format: [module]"
    end
  end

  defp validate_aliases(kind, aliases) do
    valid = is_list(aliases) and Enum.all?(aliases, fn {k, v} -> is_atom(k) and is_atom(v) end)

    unless valid do
      raise ArgumentError,
            "expected :#{kind} option given to eval in the format: [{module, module}]"
    end
  end

  defp validate_imports(kind, imports) do
    valid =
      is_list(imports) and
        Enum.all?(imports, fn {k, v} ->
          is_atom(k) and is_list(v) and
            Enum.all?(v, fn {name, arity} -> is_atom(name) and is_integer(arity) end)
        end)

    unless valid do
      raise ArgumentError,
            "expected :#{kind} option given to eval in the format: [{module, [{name, arity}]}]"
    end
  end

  @doc """
  Converts the given string to its quoted form.

  Returns `{:ok, quoted_form}` if it succeeds,
  `{:error, {line, error, token}}` otherwise.

  ## Options

    * `:file` - the filename to be reported in case of parsing errors.
      Defaults to "nofile".

    * `:line` - the starting line of the string being parsed.
      Defaults to 1.

    * `:columns` - when `true`, attach a `:column` key to the quoted
      metadata. Defaults to `false`.

    * `:existing_atoms_only` - when `true`, raises an error
      when non-existing atoms are found by the tokenizer.
      Defaults to `false`.

  ## `Macro.to_string/2`

  The opposite of converting a string to its quoted form is
  `Macro.to_string/2`, which converts a quoted form to a string/binary
  representation.
  """
  @spec string_to_quoted(List.Chars.t(), keyword) ::
          {:ok, Macro.t()} | {:error, {line :: pos_integer, term, term}}
  def string_to_quoted(string, opts \\ []) when is_list(opts) do
    file = Keyword.get(opts, :file, "nofile")
    line = Keyword.get(opts, :line, 1)

    with {:ok, tokens} <- :elixir.string_to_tokens(to_charlist(string), line, file, opts) do
      :elixir.tokens_to_quoted(tokens, file, opts)
    end
  end

  @doc """
  Converts the given string to its quoted form.

  It returns the ast if it succeeds,
  raises an exception otherwise. The exception is a `TokenMissingError`
  in case a token is missing (usually because the expression is incomplete),
  `SyntaxError` otherwise.

  Check `string_to_quoted/2` for options information.
  """
  @spec string_to_quoted!(List.Chars.t(), keyword) :: Macro.t()
  def string_to_quoted!(string, opts \\ []) when is_list(opts) do
    file = Keyword.get(opts, :file, "nofile")
    line = Keyword.get(opts, :line, 1)
    :elixir.string_to_quoted!(to_charlist(string), line, file, opts)
  end

  @doc """
  Evals the given file.

  Accepts `relative_to` as an argument to tell where the file is located.

  While `require_file/2` and `compile_file/2` returns the loaded modules and their
  bytecode, `eval_file/2` simply evaluates the file contents and returns the
  evaluation result and its bindings (exactly the same return value as `eval_string/3`).
  """
  @spec eval_file(binary, nil | binary) :: {term, binding :: list}
  def eval_file(file, relative_to \\ nil) when is_binary(file) do
    file = find_file(file, relative_to)
    eval_string(File.read!(file), [], file: file, line: 1)
  end

  # TODO: Deprecate me on 1.9
  @doc false
  def load_file(file, relative_to \\ nil) when is_binary(file) do
    file = find_file(file, relative_to)
    :elixir_code_server.call({:acquire, file})
    loaded = :elixir_compiler.file(file)
    :elixir_code_server.cast({:required, file})
    loaded
  end

  @doc """
  Requires the given `file`.

  Accepts `relative_to` as an argument to tell where the file is located.
  If the file was already required, `require_file/2` doesn't do anything and
  returns `nil`.

  Notice that if `require_file/2` is invoked by different processes concurrently,
  the first process to invoke `require_file/2` acquires a lock and the remaining
  ones will block until the file is available. This means that if `require_file/2`
  is called more than once with a given file, that file will be compiled only once.
  The first process to call `require_file/2` will get the list of loaded modules,
  others will get `nil`.

  See `compile_file/2` if you would like to compile a file without tracking its
  filenames. Finally, if you would like to get the result of evaluating file rather
  than the modules defined in it, see `eval_file/2`.

  ## Examples

  If the file has not been required, it returns the list of modules:

      modules = Code.require_file("eex_test.exs", "../eex/test")
      List.first(modules)
      #=> {EExTest.Compiled, <<70, 79, 82, 49, ...>>}

  If the code has been required, it returns `nil`:

      Code.require_file("eex_test.exs", "../eex/test")
      #=> nil

  """
  @spec require_file(binary, nil | binary) :: [{module, binary}] | nil
  def require_file(file, relative_to \\ nil) when is_binary(file) do
    file = find_file(file, relative_to)

    # TODO: Simply block until :required or :proceed once load_file is removed in 2.0
    case :elixir_code_server.call({:acquire, file}) do
      :required ->
        nil

      {:queued, ref} ->
        receive do
          {:elixir_code_server, ^ref, :required} -> nil
        end

      :proceed ->
        loaded = :elixir_compiler.file(file)
        :elixir_code_server.cast({:required, file})
        loaded
    end
  end

  @doc """
  Gets the compilation options from the code server.

  Check `compiler_options/1` for more information.

  ## Examples

      Code.compiler_options()
      #=> %{debug_info: true, docs: true,
      #=>   warnings_as_errors: false, ignore_module_conflict: false}

  """
  @spec compiler_options() :: %{optional(atom) => boolean}
  def compiler_options do
    :elixir_config.get(:compiler_options)
  end

  @doc """
  Returns a list with the available compiler options.

  See `compiler_options/1` for more info.

  ## Examples

      iex> Code.available_compiler_options()
      [:docs, :debug_info, :ignore_module_conflict, :relative_paths, :warnings_as_errors]

  """
  @spec available_compiler_options() :: [atom]
  def available_compiler_options do
    [:docs, :debug_info, :ignore_module_conflict, :relative_paths, :warnings_as_errors]
  end

  @doc """
  Sets compilation options.

  These options are global since they are stored by Elixir's Code Server.

  Available options are:

    * `:docs` - when `true`, retain documentation in the compiled module.
      Defaults to `true`.

    * `:debug_info` - when `true`, retain debug information in the compiled
      module. This allows a developer to reconstruct the original source
      code. Defaults to `false`.

    * `:ignore_module_conflict` - when `true`, override modules that were
      already defined without raising errors. Defaults to `false`.

    * `:relative_paths` - when `true`, use relative paths in quoted nodes,
      warnings and errors generated by the compiler. Note disabling this option
      won't affect runtime warnings and errors. Defaults to `true`.

    * `:warnings_as_errors` - causes compilation to fail when warnings are
      generated. Defaults to `false`.

  It returns the new map of compiler options.

  ## Examples

      Code.compiler_options(debug_info: true)
      #=> %{debug_info: true, docs: true,
      #=>   warnings_as_errors: false, ignore_module_conflict: false}

  """
  @spec compiler_options(Enumerable.t()) :: %{optional(atom) => boolean}
  def compiler_options(opts) do
    available = available_compiler_options()

    Enum.each(opts, fn {key, value} ->
      cond do
        key not in available ->
          raise "unknown compiler option: #{inspect(key)}"

        not is_boolean(value) ->
          raise "compiler option #{inspect(key)} should be a boolean, got: #{inspect(value)}"

        true ->
          :ok
      end
    end)

    :elixir_config.update(:compiler_options, &Enum.into(opts, &1))
  end

  @doc """
  Compiles the given string.

  Returns a list of tuples where the first element is the module name
  and the second one is its bytecode (as a binary). A `file` can be
  given as second argument which will be used for reporting warnings
  and errors.
  """
  @spec compile_string(List.Chars.t(), binary) :: [{module, binary}]
  def compile_string(string, file \\ "nofile") when is_binary(file) do
    :elixir_compiler.string(to_charlist(string), file)
  end

  @doc """
  Compiles the quoted expression.

  Returns a list of tuples where the first element is the module name and
  the second one is its bytecode (as a binary). A `file` can be
  given as second argument which will be used for reporting warnings
  and errors.
  """
  @spec compile_quoted(Macro.t(), binary) :: [{module, binary}]
  def compile_quoted(quoted, file \\ "nofile") when is_binary(file) do
    :elixir_compiler.quoted(quoted, file)
  end

  @doc """
  Compiles the given file.

  Accepts `relative_to` as an argument to tell where the file is located.

  Returns a list of tuples where the first element is the module name and
  the second one is its bytecode (as a binary). Opposite to `require_file/2`,
  it does not track the filename of the compiled file.

  If you would like to get the result of evaluating file rather than the
  modules defined in it, see `eval_file/2`.

  For compiling many files concurrently, see `Kernel.ParallelCompiler.compile/2`.
  """
  @spec compile_file(binary, nil | binary) :: [{module, binary}]
  def compile_file(file, relative_to \\ nil) when is_binary(file) do
    :elixir_compiler.file(find_file(file, relative_to))
  end

  @doc """
  Ensures the given module is loaded.

  If the module is already loaded, this works as no-op. If the module
  was not yet loaded, it tries to load it.

  If it succeeds in loading the module, it returns `{:module, module}`.
  If not, returns `{:error, reason}` with the error reason.

  ## Code loading on the Erlang VM

  Erlang has two modes to load code: interactive and embedded.

  By default, the Erlang VM runs in interactive mode, where modules
  are loaded as needed. In embedded mode the opposite happens, as all
  modules need to be loaded upfront or explicitly.

  Therefore, this function is used to check if a module is loaded
  before using it and allows one to react accordingly. For example, the `URI`
  module uses this function to check if a specific parser exists for a given
  URI scheme.

  ## `ensure_compiled/1`

  Elixir also contains an `ensure_compiled/1` function that is a
  superset of `ensure_loaded/1`.

  Since Elixir's compilation happens in parallel, in some situations
  you may need to use a module that was not yet compiled, therefore
  it can't even be loaded.

  When invoked, `ensure_compiled/1` halts the compilation of the caller
  until the module given to `ensure_compiled/1` becomes available or
  all files for the current project have been compiled. If compilation
  finishes and the module is not available, an error tuple is returned.

  `ensure_compiled/1` does not apply to dependencies, as dependencies
  must be compiled upfront.

  In most cases, `ensure_loaded/1` is enough. `ensure_compiled/1`
  must be used in rare cases, usually involving macros that need to
  invoke a module for callback information.

  ## Examples

      iex> Code.ensure_loaded(Atom)
      {:module, Atom}

      iex> Code.ensure_loaded(DoesNotExist)
      {:error, :nofile}

  """
  @spec ensure_loaded(module) ::
          {:module, module} | {:error, :embedded | :badfile | :nofile | :on_load_failure}
  def ensure_loaded(module) when is_atom(module) do
    :code.ensure_loaded(module)
  end

  @doc """
  Ensures the given module is loaded.

  Similar to `ensure_loaded/1`, but returns `true` if the module
  is already loaded or was successfully loaded. Returns `false`
  otherwise.

  ## Examples

      iex> Code.ensure_loaded?(Atom)
      true

  """
  @spec ensure_loaded?(module) :: boolean
  def ensure_loaded?(module) when is_atom(module) do
    match?({:module, ^module}, ensure_loaded(module))
  end

  @doc """
  Ensures the given module is compiled and loaded.

  If the module is already loaded, it works as no-op. If the module was
  not loaded yet, it checks if it needs to be compiled first and then
  tries to load it.

  If it succeeds in loading the module, it returns `{:module, module}`.
  If not, returns `{:error, reason}` with the error reason.

  Check `ensure_loaded/1` for more information on module loading
  and when to use `ensure_loaded/1` or `ensure_compiled/1`.
  """
  @spec ensure_compiled(module) ::
          {:module, module} | {:error, :embedded | :badfile | :nofile | :on_load_failure}
  def ensure_compiled(module) when is_atom(module) do
    case :code.ensure_loaded(module) do
      {:error, :nofile} = error ->
        if is_pid(:erlang.get(:elixir_compiler_pid)) and
             Kernel.ErrorHandler.ensure_compiled(module, :module) do
          {:module, module}
        else
          error
        end

      other ->
        other
    end
  end

  @doc """
  Ensures the given module is compiled and loaded.

  Similar to `ensure_compiled/1`, but returns `true` if the module
  is already loaded or was successfully loaded and compiled.
  Returns `false` otherwise.
  """
  @spec ensure_compiled?(module) :: boolean
  def ensure_compiled?(module) when is_atom(module) do
    match?({:module, ^module}, ensure_compiled(module))
  end

  @doc ~S"""
  Returns the docs for the given module.

  When given a module name, it finds its BEAM code and reads the docs from it.

  When given a path to a `.beam` file, it will load the docs directly from that
  file.

  The return value depends on the `kind` value:

    * `:moduledoc` - tuple `{line, doc}` where `line` is the line on
      which the module definition starts and `doc` is the string
      attached to the module using the `@moduledoc` attribute,
      `false` if `@moduledoc false` was used, or `nil` if no `@moduledoc`
      was used.

    * `:docs` - list of all docstrings attached to functions and macros
      using the `@doc` attribute. Each tuple has the form
      `{{name, arity}, line, kind, arguments, doc}`. `doc` can be either a
      string, `false` if `@doc false` was used, or `nil` if no doc was used.

    * `:callback_docs` - list of all docstrings attached to
      `@callbacks` using the `@doc` attribute. Each tuple has the form
      `{{name, arity}, line, kind, doc}`. `doc` can be either a string or
      `nil` if no `@doc` was set.

    * `:type_docs` - list of all docstrings attached to `@type` callbacks
      using the `@typedoc` attribute. Each tuple has the form
      `{{name, arity}, line, kind, doc}`. `doc` can be either a string or
      `nil` if no `@typedoc` was used.

    * `:all` - a keyword list with `:docs`, `:moduledoc`, `:callback_docs`,
      and `:type_docs`.

  If the module cannot be found, it returns `nil`.

  ## Examples

      # Module documentation of an existing module
      iex> {_line, text} = Code.get_docs(Atom, :moduledoc)
      iex> text |> String.split("\n") |> Enum.at(0)
      "Convenience functions for working with atoms."

      # A module that doesn't exist
      iex> Code.get_docs(ModuleNotGood, :all)
      nil

  """
  @doc_kinds [:docs, :moduledoc, :callback_docs, :type_docs, :all]

  @spec get_docs(module, :moduledoc) :: {line :: pos_integer, doc :: false | binary} | nil
  @spec get_docs(module, :docs) :: [{function, line, kind, list, doc}] | nil
        when function: {atom, arity}, line: pos_integer, kind: atom, doc: nil | false | binary
  @spec get_docs(module, :callback_docs) :: [{callback, line, kind, doc}] | nil
        when callback: {atom, arity}, line: pos_integer, kind: atom, doc: nil | false | binary
  @spec get_docs(module, :type_docs) :: [{type, line, kind, doc}] | nil
        when type: {atom, arity}, line: pos_integer, kind: atom, doc: nil | false | binary
  @spec get_docs(module, :all) :: keyword | nil
  def get_docs(module, kind)

  def get_docs(module, kind) when is_atom(module) and kind in @doc_kinds do
    case :code.get_object_code(module) do
      {_module, bin, _beam_path} -> do_get_docs(bin, kind)
      :error -> nil
    end
  end

  def get_docs(binpath, kind) when is_binary(binpath) and kind in @doc_kinds do
    do_get_docs(String.to_charlist(binpath), kind)
  end

  @docs_chunk 'ExDc'

  defp do_get_docs(bin_or_path, kind) do
    case :beam_lib.chunks(bin_or_path, [@docs_chunk]) do
      {:ok, {_module, [{@docs_chunk, bin}]}} ->
        lookup_docs(:erlang.binary_to_term(bin), kind)

      {:error, :beam_lib, {:missing_chunk, _, @docs_chunk}} ->
        nil
    end
  end

  defp lookup_docs({:elixir_docs_v1, docs}, kind), do: do_lookup_docs(docs, kind)

  # unsupported chunk version
  defp lookup_docs(_, _), do: nil

  defp do_lookup_docs(docs, :all), do: docs
  defp do_lookup_docs(docs, kind), do: Keyword.get(docs, kind)

  ## Helpers

  # Finds the file given the relative_to path.
  #
  # If the file is found, returns its path in binary, fails otherwise.
  defp find_file(file, relative_to) do
    file =
      if relative_to do
        Path.expand(file, relative_to)
      else
        Path.expand(file)
      end

    if File.regular?(file) do
      file
    else
      raise Code.LoadError, file: file
    end
  end
end

defmodule Code do
  @moduledoc """
  Utilities for managing code compilation, code evaluation, and code loading.

  This module complements Erlang's [`:code` module](http://www.erlang.org/doc/man/code.html)
  to add behaviour which is specific to Elixir. Almost all of the functions in this module
  have global side effects on the behaviour of Elixir.

  ## Working with files

  This module contains three functions for compiling and evaluating files.
  Here is a summary of them and their behaviour:

    * `require_file/2` - compiles a file and tracks its name. It does not
      compile the file again if it has been previously required.

    * `compile_file/2` - compiles a file without tracking its name. Compiles the
      file multiple times when invoked multiple times.

    * `eval_file/2` - evaluates the file contents without tracking its name. It
      returns the result of the last expression in the file, instead of the modules
      defined in it.

  In a nutshell, the first must be used when you want to keep track of the files
  handled by the system, to avoid the same file from being compiled multiple
  times. This is common in scripts.

  `compile_file/2` must be used when you are interested in the modules defined in a
  file, without tracking. `eval_file/2` should be used when you are intested on
  the result of evaluating the file rather than the modules it defines.
  """

  @doc """
  Lists all required files.

  ## Examples

      Code.require_file("../eex/test/eex_test.exs")
      List.first(Code.required_files()) =~ "eex_test.exs"
      #=> true

  """
  @since "1.7.0"
  @spec required_files() :: [binary]
  def required_files do
    :elixir_code_server.call(:required)
  end

  # TODO: Deprecate me on 1.9
  @doc false
  def loaded_files do
    required_files()
  end

  @doc """
  Removes files from the required files list.

  The modules defined in the file are not removed;
  calling this function only removes them from the list,
  allowing them to be required again.

  ## Examples

      # Require EEx test code
      Code.require_file("../eex/test/eex_test.exs")

      # Now unrequire all files
      Code.unrequire_files(Code.required_files())

      # Notice modules are still available
      function_exported?(EExTest.Compiled, :before_compile, 0)
      #=> true

  """
  @spec unrequire_files([binary]) :: :ok
  @since "1.7.0"
  def unrequire_files(files) do
    :elixir_code_server.cast({:unrequire_files, files})
  end

  # TODO: Deprecate me on 1.9
  @doc false
  def unload_files(files) do
    unrequire_files(files)
  end

  @doc """
  Appends a path to the end of the Erlang VM code path list.

  This is the list of directories the Erlang VM uses for
  finding module code.

  The path is expanded with `Path.expand/1` before being appended.
  If this path does not exist, an error is returned.

  ## Examples

      Code.append_path(".")
      #=> true

      Code.append_path("/does_not_exist")
      #=> {:error, :bad_directory}

  """
  @spec append_path(Path.t()) :: true | {:error, :bad_directory}
  def append_path(path) do
    :code.add_pathz(to_charlist(Path.expand(path)))
  end

  @doc """
  Prepends a path to the beginning of the Erlang VM code path list.

  This is the list of directories the Erlang VM uses for finding
  module code.

  The path is expanded with `Path.expand/1` before being prepended.
  If this path does not exist, an error is returned.

  ## Examples

      Code.prepend_path(".")
      #=> true

      Code.prepend_path("/does_not_exist")
      #=> {:error, :bad_directory}

  """
  @spec prepend_path(Path.t()) :: true | {:error, :bad_directory}
  def prepend_path(path) do
    :code.add_patha(to_charlist(Path.expand(path)))
  end

  @doc """
  Deletes a path from the Erlang VM code path list. This is the list of
  directories the Erlang VM uses for finding module code.

  The path is expanded with `Path.expand/1` before being deleted. If the
  path does not exist, this function returns `false`.

  ## Examples

      Code.prepend_path(".")
      Code.delete_path(".")
      #=> true

      Code.delete_path("/does_not_exist")
      #=> false

  """
  @spec delete_path(Path.t()) :: boolean
  def delete_path(path) do
    :code.del_path(to_charlist(Path.expand(path)))
  end

  @doc """
  Evaluates the contents given by `string`.

  The `binding` argument is a keyword list of variable bindings.
  The `opts` argument is a keyword list of environment options.

  **Warning**: `string` can be any Elixir code and will be executed with
  the same privileges as the Erlang VM: this means that such code could
  compromise the machine (for example by executing system commands).
  Don't use `eval_string/3` with untrusted input (such as strings coming
  from the network).

  ## Options

  Options can be:

    * `:file` - the file to be considered in the evaluation

    * `:line` - the line on which the script starts

  Additionally, the following scope values can be configured:

    * `:aliases` - a list of tuples with the alias and its target

    * `:requires` - a list of modules required

    * `:functions` - a list of tuples where the first element is a module
      and the second a list of imported function names and arity; the list
      of function names and arity must be sorted

    * `:macros` - a list of tuples where the first element is a module
      and the second a list of imported macro names and arity; the list
      of function names and arity must be sorted

  Notice that setting any of the values above overrides Elixir's default
  values. For example, setting `:requires` to `[]` will no longer
  automatically require the `Kernel` module. In the same way setting
  `:macros` will no longer auto-import `Kernel` macros like `Kernel.if/2`,
  `Kernel.SpecialForms.case/2`, and so on.

  Returns a tuple of the form `{value, binding}`,
  where `value` is the value returned from evaluating `string`.
  If an error occurs while evaluating `string` an exception will be raised.

  `binding` is a keyword list with the value of all variable bindings
  after evaluating `string`. The binding key is usually an atom, but it
  may be a tuple for variables defined in a different context.

  ## Examples

      iex> Code.eval_string("a + b", [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
      {3, [a: 1, b: 2]}

      iex> Code.eval_string("c = a + b", [a: 1, b: 2], __ENV__)
      {3, [a: 1, b: 2, c: 3]}

      iex> Code.eval_string("a = a + b", [a: 1, b: 2])
      {3, [a: 3, b: 2]}

  For convenience, you can pass `__ENV__/0` as the `opts` argument and
  all imports, requires and aliases defined in the current environment
  will be automatically carried over:

      iex> Code.eval_string("a + b", [a: 1, b: 2], __ENV__)
      {3, [a: 1, b: 2]}

  """
  @spec eval_string(List.Chars.t(), list, Macro.Env.t() | keyword) :: {term, binding :: list}
  def eval_string(string, binding \\ [], opts \\ [])

  def eval_string(string, binding, %Macro.Env{} = env) do
    {value, binding, _env, _scope} = :elixir.eval(to_charlist(string), binding, Map.to_list(env))
    {value, binding}
  end

  def eval_string(string, binding, opts) when is_list(opts) do
    validate_eval_opts(opts)
    {value, binding, _env, _scope} = :elixir.eval(to_charlist(string), binding, opts)
    {value, binding}
  end

  @doc ~S"""
  Formats the given code `string`.

  The formatter receives a string representing Elixir code and
  returns iodata representing the formatted code according to
  pre-defined rules.

  ## Options

    * `:file` - the file which contains the string, used for error
      reporting

    * `:line` - the line the string starts, used for error reporting

    * `:line_length` - the line length to aim for when formatting
      the document. Defaults to 98.

    * `:locals_without_parens` - a keyword list of name and arity
      pairs that should be kept without parens whenever possible.
      The arity may be the atom `:*`, which implies all arities of
      that name. The formatter already includes a list of functions
      and this option augments this list.

    * `:rename_deprecated_at` - rename all known deprecated functions
      at the given version to their non-deprecated equivalent. It
      expects a valid `Version` which is usually the minimum Elixir
      version supported by the project.

  ## Design principles

  The formatter was designed under three principles.

  First, the formatter never changes the semantics of the code by
  default. This means the input AST and the output AST are equivalent.
  Optional behaviour, such as `:rename_deprecated_at`, is allowed to
  break this guarantee.

  The second principle is to provide as little configuration as possible.
  This eases the formatter adoption by removing contention points while
  making sure a single style is followed consistently by the community as
  a whole.

  The formatter does not hard code names. The formatter will not behave
  specially because a function is named `defmodule`, `def`, etc. This
  principle mirrors Elixir's goal of being an extensible language where
  developers can extend the language with new constructs as if they were
  part of the language. When it is absolutely necessary to change behaviour
  based on the name, this behaviour should be configurable, such as the
  `:locals_without_parens` option.

  ## Keeping user's formatting

  The formatter respects the input format in some cases. Those are
  listed below:

    * Insignificant digits in numbers are kept as is. The formatter
      however always inserts underscores for decimal numbers with more
      than 5 digits and converts hexadecimal digits to uppercase

    * Strings, charlists, atoms and sigils are kept as is. No character
      is automatically escaped or unescaped. The choice of delimiter is
      also respected from the input

    * Newlines inside blocks are kept as in the input except for:
      1) expressions that take multiple lines will always have an empty
      line before and after and 2) empty lines are always squeezed
      together into a single empty line

    * The choice between `:do` keyword and `do/end` blocks is left
      to the user

    * Lists, tuples, bitstrings, maps, structs and function calls will be
      broken into multiple lines if they are followed by a newline in the
      opening bracket and preceded by a new line in the closing bracket

    * Pipeline operators, like `|>` and others with the same precedence,
      will span multiple lines if they spanned multiple lines in the input

  The behaviours above are not guaranteed. We may remove or add new
  rules in the future. The goal of documenting them is to provide better
  understanding on what to expect from the formatter.

  ## Adjusting formatted output

  The formatter attempts to the fit the most it can on a single line.
  When the code does not fit a single line, the formatter introduces
  line breaks in the code.

  In some rare situations, this may lead to undesired formatting.
  For example, the code below:

      "this is a very long string ... #{inspect(some_value)}"

  may be formatted as:

      "this is a very long string ... #{
        inspect(some_value)
      }"

  This happens because the only place the formatter can introduce a
  new line without changing the code semantics is in the interpolation.
  In those scenarios, we recommend developers to directly adjust the
  code. Here we can use the binary concatenation operator `<>/2`:

      "this is a very long string " <>
        "... #{inspect(some_value)}"

  The string concatenation makes the code fit on a single line and also
  gives more options to the formatter.

  A similar example is when the formatter breaks a function definition
  over multiple clauses:

      def my_function(
        %User{name: name, age: age, ...},
        arg1,
        arg2
      ) do

  While the code above is completely valid, you may prefer to match on
  the struct variables inside the function body in order to keep the
  definition on a single line:

      def my_function(%User{} = user, arg1, arg2) do
        %{name: name, age: age, ...} = user

  Since the formatter cannot change the semantics of your code,
  sometimes it is necessary to tweak the code to get optimal formatting.

  ### Multi-line lists, maps, tuples, etc

  You can force lists, tuples, bitstrings, maps, structs and function
  calls to have one entry per line by adding a newline after the opening
  bracket and a new line before the closing bracket lines. For example:

      [
        foo,
        bar
      ]

  If there are no newlines around the brackets, then the formatter will
  try to fit everything on a single line, such that the snippet below

      [foo,
       bar]

  will be formatted as

      [foo, bar]

  You can also force function calls and keywords to be rendered on multiple
  lines by having each entry on its own line:

      defstruct name: nil,
                age: 0

  The code above will be kept with one keyword entry per line by the
  formatter. To avoid that, just squash everything into a single line.

  ### Parens and no parens in function calls

  Elixir has two syntaxes for function calls. With parens and no parens.
  By default, Elixir will add parens to all calls except for:

    1. calls that have do/end blocks
    2. local calls without parens where the name and arity of the local
       call is also listed under `:locals_without_parens`

  The choice of parens and no parens also affects indentation. When a
  function call with parens doesn't fit on the same line, the formatter
  introduces a newline around parens and indents the arguments with two
  spaces:

      some_call(
        arg1,
        arg2,
        arg3
      )

  On the other hand, function calls without parens are always indented
  by the function call length itself, like this:

      some_call arg1,
                arg2,
                arg3

  If the last argument is a data structure, such as maps and lists, and
  the beginning of the data structure fits on the same line as the function
  call, then no indentation happens, this allows code like this:

      Enum.reduce(some_collection, initial_value, fn element, acc ->
        # code
      end)

      some_funtion_without_parens %{
        foo: :bar,
        baz: :bat
      }

  ## Code comments

  The formatter also handles code comments in a way to guarantee a space
  is always added between the beginning of the comment (#) and the next
  character.

  The formatter also extracts all trailing comments to their previous line.
  For example, the code below

      hello # world

  will be rewritten to

      # world
      hello

  Because code comments are handled apart from the code representation (AST),
  there are some situations where code comments are seen as ambiguous by the
  code formatter. For example, the comment in the anonymous function below

      fn
        arg1 ->
          body1
          # comment

        arg2 ->
          body2
      end

  and in this one

      fn
        arg1 ->
          body1

        # comment
        arg2 ->
          body2
      end

  are considered equivalent (the nesting is discarded alongside most of
  user formatting). In such cases, the code formatter will always format to
  the latter.
  """
  @since "1.6.0"
  @spec format_string!(binary, keyword) :: iodata
  def format_string!(string, opts \\ []) when is_binary(string) and is_list(opts) do
    line_length = Keyword.get(opts, :line_length, 98)
    algebra = Code.Formatter.to_algebra!(string, opts)
    Inspect.Algebra.format(algebra, line_length)
  end

  @doc """
  Formats a file.

  See `format_string!/2` for more information on code formatting and
  available options.
  """
  @since "1.6.0"
  @spec format_file!(binary, keyword) :: iodata
  def format_file!(file, opts \\ []) when is_binary(file) and is_list(opts) do
    string = File.read!(file)
    formatted = format_string!(string, [file: file, line: 1] ++ opts)
    [formatted, ?\n]
  end

  @doc """
  Evaluates the quoted contents.

  **Warning**: Calling this function inside a macro is considered bad
  practice as it will attempt to evaluate runtime values at compile time.
  Macro arguments are typically transformed by unquoting them into the
  returned quoted expressions (instead of evaluated).

  See `eval_string/3` for a description of bindings and options.

  ## Examples

      iex> contents = quote(do: var!(a) + var!(b))
      iex> Code.eval_quoted(contents, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
      {3, [a: 1, b: 2]}

  For convenience, you can pass `__ENV__/0` as the `opts` argument and
  all options will be automatically extracted from the current environment:

      iex> contents = quote(do: var!(a) + var!(b))
      iex> Code.eval_quoted(contents, [a: 1, b: 2], __ENV__)
      {3, [a: 1, b: 2]}

  """
  @spec eval_quoted(Macro.t(), list, Macro.Env.t() | keyword) :: {term, binding :: list}
  def eval_quoted(quoted, binding \\ [], opts \\ [])

  def eval_quoted(quoted, binding, %Macro.Env{} = env) do
    {value, binding, _env, _scope} = :elixir.eval_quoted(quoted, binding, Map.to_list(env))
    {value, binding}
  end

  def eval_quoted(quoted, binding, opts) when is_list(opts) do
    validate_eval_opts(opts)
    {value, binding, _env, _scope} = :elixir.eval_quoted(quoted, binding, opts)
    {value, binding}
  end

  defp validate_eval_opts(opts) do
    if f = opts[:functions], do: validate_imports(:functions, f)
    if m = opts[:macros], do: validate_imports(:macros, m)
    if a = opts[:aliases], do: validate_aliases(:aliases, a)
    if r = opts[:requires], do: validate_requires(:requires, r)
  end

  defp validate_requires(kind, requires) do
    valid = is_list(requires) and Enum.all?(requires, &is_atom(&1))

    unless valid do
      raise ArgumentError, "expected :#{kind} option given to eval in the format: [module]"
    end
  end

  defp validate_aliases(kind, aliases) do
    valid = is_list(aliases) and Enum.all?(aliases, fn {k, v} -> is_atom(k) and is_atom(v) end)

    unless valid do
      raise ArgumentError,
            "expected :#{kind} option given to eval in the format: [{module, module}]"
    end
  end

  defp validate_imports(kind, imports) do
    valid =
      is_list(imports) and
        Enum.all?(imports, fn {k, v} ->
          is_atom(k) and is_list(v) and
            Enum.all?(v, fn {name, arity} -> is_atom(name) and is_integer(arity) end)
        end)

    unless valid do
      raise ArgumentError,
            "expected :#{kind} option given to eval in the format: [{module, [{name, arity}]}]"
    end
  end

  @doc """
  Converts the given string to its quoted form.

  Returns `{:ok, quoted_form}` if it succeeds,
  `{:error, {line, error, token}}` otherwise.

  ## Options

    * `:file` - the filename to be reported in case of parsing errors.
      Defaults to "nofile".

    * `:line` - the starting line of the string being parsed.
      Defaults to 1.

    * `:columns` - when `true`, attach a `:column` key to the quoted
      metadata. Defaults to `false`.

    * `:existing_atoms_only` - when `true`, raises an error
      when non-existing atoms are found by the tokenizer.
      Defaults to `false`.

  ## `Macro.to_string/2`

  The opposite of converting a string to its quoted form is
  `Macro.to_string/2`, which converts a quoted form to a string/binary
  representation.
  """
  @spec string_to_quoted(List.Chars.t(), keyword) ::
          {:ok, Macro.t()} | {:error, {line :: pos_integer, term, term}}
  def string_to_quoted(string, opts \\ []) when is_list(opts) do
    file = Keyword.get(opts, :file, "nofile")
    line = Keyword.get(opts, :line, 1)

    with {:ok, tokens} <- :elixir.string_to_tokens(to_charlist(string), line, file, opts) do
      :elixir.tokens_to_quoted(tokens, file, opts)
    end
  end

  @doc """
  Converts the given string to its quoted form.

  It returns the ast if it succeeds,
  raises an exception otherwise. The exception is a `TokenMissingError`
  in case a token is missing (usually because the expression is incomplete),
  `SyntaxError` otherwise.

  Check `string_to_quoted/2` for options information.
  """
  @spec string_to_quoted!(List.Chars.t(), keyword) :: Macro.t()
  def string_to_quoted!(string, opts \\ []) when is_list(opts) do
    file = Keyword.get(opts, :file, "nofile")
    line = Keyword.get(opts, :line, 1)
    :elixir.string_to_quoted!(to_charlist(string), line, file, opts)
  end

  @doc """
  Evals the given file.

  Accepts `relative_to` as an argument to tell where the file is located.

  While `require_file/2` and `compile_file/2` returns the loaded modules and their
  bytecode, `eval_file/2` simply evaluates the file contents and returns the
  evaluation result and its bindings (exactly the same return value as `eval_string/3`).
  """
  @spec eval_file(binary, nil | binary) :: {term, binding :: list}
  def eval_file(file, relative_to \\ nil) when is_binary(file) do
    file = find_file(file, relative_to)
    eval_string(File.read!(file), [], file: file, line: 1)
  end

  # TODO: Deprecate me on 1.9
  @doc false
  def load_file(file, relative_to \\ nil) when is_binary(file) do
    file = find_file(file, relative_to)
    :elixir_code_server.call({:acquire, file})
    loaded = :elixir_compiler.file(file)
    :elixir_code_server.cast({:required, file})
    loaded
  end

  @doc """
  Requires the given `file`.

  Accepts `relative_to` as an argument to tell where the file is located.
  If the file was already required, `require_file/2` doesn't do anything and
  returns `nil`.

  Notice that if `require_file/2` is invoked by different processes concurrently,
  the first process to invoke `require_file/2` acquires a lock and the remaining
  ones will block until the file is available. This means that if `require_file/2`
  is called more than once with a given file, that file will be compiled only once.
  The first process to call `require_file/2` will get the list of loaded modules,
  others will get `nil`.

  See `compile_file/2` if you would like to compile a file without tracking its
  filenames. Finally, if you would like to get the result of evaluating file rather
  than the modules defined in it, see `eval_file/2`.

  ## Examples

  If the file has not been required, it returns the list of modules:

      modules = Code.require_file("eex_test.exs", "../eex/test")
      List.first(modules)
      #=> {EExTest.Compiled, <<70, 79, 82, 49, ...>>}

  If the code has been required, it returns `nil`:

      Code.require_file("eex_test.exs", "../eex/test")
      #=> nil

  """
  @spec require_file(binary, nil | binary) :: [{module, binary}] | nil
  def require_file(file, relative_to \\ nil) when is_binary(file) do
    file = find_file(file, relative_to)

    # TODO: Simply block until :required or :proceed once load_file is removed in 2.0
    case :elixir_code_server.call({:acquire, file}) do
      :required ->
        nil

      {:queued, ref} ->
        receive do
          {:elixir_code_server, ^ref, :required} -> nil
        end

      :proceed ->
        loaded = :elixir_compiler.file(file)
        :elixir_code_server.cast({:required, file})
        loaded
    end
  end

  @doc """
  Gets the compilation options from the code server.

  Check `compiler_options/1` for more information.

  ## Examples

      Code.compiler_options()
      #=> %{debug_info: true, docs: true,
      #=>   warnings_as_errors: false, ignore_module_conflict: false}

  """
  @spec compiler_options() :: %{optional(atom) => boolean}
  def compiler_options do
    :elixir_config.get(:compiler_options)
  end

  @doc """
  Returns a list with the available compiler options.

  See `compiler_options/1` for more info.

  ## Examples

      iex> Code.available_compiler_options()
      [:docs, :debug_info, :ignore_module_conflict, :relative_paths, :warnings_as_errors]

  """
  @spec available_compiler_options() :: [atom]
  def available_compiler_options do
    [:docs, :debug_info, :ignore_module_conflict, :relative_paths, :warnings_as_errors]
  end

  @doc """
  Sets compilation options.

  These options are global since they are stored by Elixir's Code Server.

  Available options are:

    * `:docs` - when `true`, retain documentation in the compiled module.
      Defaults to `true`.

    * `:debug_info` - when `true`, retain debug information in the compiled
      module. This allows a developer to reconstruct the original source
      code. Defaults to `false`.

    * `:ignore_module_conflict` - when `true`, override modules that were
      already defined without raising errors. Defaults to `false`.

    * `:relative_paths` - when `true`, use relative paths in quoted nodes,
      warnings and errors generated by the compiler. Note disabling this option
      won't affect runtime warnings and errors. Defaults to `true`.

    * `:warnings_as_errors` - causes compilation to fail when warnings are
      generated. Defaults to `false`.

  It returns the new map of compiler options.

  ## Examples

      Code.compiler_options(debug_info: true)
      #=> %{debug_info: true, docs: true,
      #=>   warnings_as_errors: false, ignore_module_conflict: false}

  """
  @spec compiler_options(Enumerable.t()) :: %{optional(atom) => boolean}
  def compiler_options(opts) do
    available = available_compiler_options()

    Enum.each(opts, fn {key, value} ->
      cond do
        key not in available ->
          raise "unknown compiler option: #{inspect(key)}"

        not is_boolean(value) ->
          raise "compiler option #{inspect(key)} should be a boolean, got: #{inspect(value)}"

        true ->
          :ok
      end
    end)

    :elixir_config.update(:compiler_options, &Enum.into(opts, &1))
  end

  @doc """
  Compiles the given string.

  Returns a list of tuples where the first element is the module name
  and the second one is its bytecode (as a binary). A `file` can be
  given as second argument which will be used for reporting warnings
  and errors.
  """
  @spec compile_string(List.Chars.t(), binary) :: [{module, binary}]
  def compile_string(string, file \\ "nofile") when is_binary(file) do
    :elixir_compiler.string(to_charlist(string), file)
  end

  @doc """
  Compiles the quoted expression.

  Returns a list of tuples where the first element is the module name and
  the second one is its bytecode (as a binary). A `file` can be
  given as second argument which will be used for reporting warnings
  and errors.
  """
  @spec compile_quoted(Macro.t(), binary) :: [{module, binary}]
  def compile_quoted(quoted, file \\ "nofile") when is_binary(file) do
    :elixir_compiler.quoted(quoted, file)
  end

  @doc """
  Compiles the given file.

  Accepts `relative_to` as an argument to tell where the file is located.

  Returns a list of tuples where the first element is the module name and
  the second one is its bytecode (as a binary). Opposite to `require_file/2`,
  it does not track the filename of the compiled file.

  If you would like to get the result of evaluating file rather than the
  modules defined in it, see `eval_file/2`.

  For compiling many files concurrently, see `Kernel.ParallelCompiler.compile/2`.
  """
  @spec compile_file(binary, nil | binary) :: [{module, binary}]
  def compile_file(file, relative_to \\ nil) when is_binary(file) do
    :elixir_compiler.file(find_file(file, relative_to))
  end

  @doc """
  Ensures the given module is loaded.

  If the module is already loaded, this works as no-op. If the module
  was not yet loaded, it tries to load it.

  If it succeeds in loading the module, it returns `{:module, module}`.
  If not, returns `{:error, reason}` with the error reason.

  ## Code loading on the Erlang VM

  Erlang has two modes to load code: interactive and embedded.

  By default, the Erlang VM runs in interactive mode, where modules
  are loaded as needed. In embedded mode the opposite happens, as all
  modules need to be loaded upfront or explicitly.

  Therefore, this function is used to check if a module is loaded
  before using it and allows one to react accordingly. For example, the `URI`
  module uses this function to check if a specific parser exists for a given
  URI scheme.

  ## `ensure_compiled/1`

  Elixir also contains an `ensure_compiled/1` function that is a
  superset of `ensure_loaded/1`.

  Since Elixir's compilation happens in parallel, in some situations
  you may need to use a module that was not yet compiled, therefore
  it can't even be loaded.

  When invoked, `ensure_compiled/1` halts the compilation of the caller
  until the module given to `ensure_compiled/1` becomes available or
  all files for the current project have been compiled. If compilation
  finishes and the module is not available, an error tuple is returned.

  `ensure_compiled/1` does not apply to dependencies, as dependencies
  must be compiled upfront.

  In most cases, `ensure_loaded/1` is enough. `ensure_compiled/1`
  must be used in rare cases, usually involving macros that need to
  invoke a module for callback information.

  ## Examples

      iex> Code.ensure_loaded(Atom)
      {:module, Atom}

      iex> Code.ensure_loaded(DoesNotExist)
      {:error, :nofile}

  """
  @spec ensure_loaded(module) ::
          {:module, module} | {:error, :embedded | :badfile | :nofile | :on_load_failure}
  def ensure_loaded(module) when is_atom(module) do
    :code.ensure_loaded(module)
  end

  @doc """
  Ensures the given module is loaded.

  Similar to `ensure_loaded/1`, but returns `true` if the module
  is already loaded or was successfully loaded. Returns `false`
  otherwise.

  ## Examples

      iex> Code.ensure_loaded?(Atom)
      true

  """
  @spec ensure_loaded?(module) :: boolean
  def ensure_loaded?(module) when is_atom(module) do
    match?({:module, ^module}, ensure_loaded(module))
  end

  @doc """
  Ensures the given module is compiled and loaded.

  If the module is already loaded, it works as no-op. If the module was
  not loaded yet, it checks if it needs to be compiled first and then
  tries to load it.

  If it succeeds in loading the module, it returns `{:module, module}`.
  If not, returns `{:error, reason}` with the error reason.

  Check `ensure_loaded/1` for more information on module loading
  and when to use `ensure_loaded/1` or `ensure_compiled/1`.
  """
  @spec ensure_compiled(module) ::
          {:module, module} | {:error, :embedded | :badfile | :nofile | :on_load_failure}
  def ensure_compiled(module) when is_atom(module) do
    case :code.ensure_loaded(module) do
      {:error, :nofile} = error ->
        if is_pid(:erlang.get(:elixir_compiler_pid)) and
             Kernel.ErrorHandler.ensure_compiled(module, :module) do
          {:module, module}
        else
          error
        end

      other ->
        other
    end
  end

  @doc """
  Ensures the given module is compiled and loaded.

  Similar to `ensure_compiled/1`, but returns `true` if the module
  is already loaded or was successfully loaded and compiled.
  Returns `false` otherwise.
  """
  @spec ensure_compiled?(module) :: boolean
  def ensure_compiled?(module) when is_atom(module) do
    match?({:module, ^module}, ensure_compiled(module))
  end

  @doc ~S"""
  Returns the docs for the given module.

  When given a module name, it finds its BEAM code and reads the docs from it.

  When given a path to a `.beam` file, it will load the docs directly from that
  file.

  The return value depends on the `kind` value:

    * `:moduledoc` - tuple `{line, doc}` where `line` is the line on
      which the module definition starts and `doc` is the string
      attached to the module using the `@moduledoc` attribute,
      `false` if `@moduledoc false` was used, or `nil` if no `@moduledoc`
      was used.

    * `:docs` - list of all docstrings attached to functions and macros
      using the `@doc` attribute. Each tuple has the form
      `{{name, arity}, line, kind, arguments, doc}`. `doc` can be either a
      string, `false` if `@doc false` was used, or `nil` if no doc was used.

    * `:callback_docs` - list of all docstrings attached to
      `@callbacks` using the `@doc` attribute. Each tuple has the form
      `{{name, arity}, line, kind, doc}`. `doc` can be either a string or
      `nil` if no `@doc` was set.

    * `:type_docs` - list of all docstrings attached to `@type` callbacks
      using the `@typedoc` attribute. Each tuple has the form
      `{{name, arity}, line, kind, doc}`. `doc` can be either a string or
      `nil` if no `@typedoc` was used.

    * `:all` - a keyword list with `:docs`, `:moduledoc`, `:callback_docs`,
      and `:type_docs`.

  If the module cannot be found, it returns `nil`.

  ## Examples

      # Module documentation of an existing module
      iex> {_line, text} = Code.get_docs(Atom, :moduledoc)
      iex> text |> String.split("\n") |> Enum.at(0)
      "Convenience functions for working with atoms."

      # A module that doesn't exist
      iex> Code.get_docs(ModuleNotGood, :all)
      nil

  """
  @doc_kinds [:docs, :moduledoc, :callback_docs, :type_docs, :all]

  @spec get_docs(module, :moduledoc) :: {line :: pos_integer, doc :: false | binary} | nil
  @spec get_docs(module, :docs) :: [{function, line, kind, list, doc}] | nil
        when function: {atom, arity}, line: pos_integer, kind: atom, doc: nil | false | binary
  @spec get_docs(module, :callback_docs) :: [{callback, line, kind, doc}] | nil
        when callback: {atom, arity}, line: pos_integer, kind: atom, doc: nil | false | binary
  @spec get_docs(module, :type_docs) :: [{type, line, kind, doc}] | nil
        when type: {atom, arity}, line: pos_integer, kind: atom, doc: nil | false | binary
  @spec get_docs(module, :all) :: keyword | nil
  def get_docs(module, kind)

  def get_docs(module, kind) when is_atom(module) and kind in @doc_kinds do
    case :code.get_object_code(module) do
      {_module, bin, _beam_path} -> do_get_docs(bin, kind)
      :error -> nil
    end
  end

  def get_docs(binpath, kind) when is_binary(binpath) and kind in @doc_kinds do
    do_get_docs(String.to_charlist(binpath), kind)
  end

  @docs_chunk 'ExDc'

  defp do_get_docs(bin_or_path, kind) do
    case :beam_lib.chunks(bin_or_path, [@docs_chunk]) do
      {:ok, {_module, [{@docs_chunk, bin}]}} ->
        lookup_docs(:erlang.binary_to_term(bin), kind)

      {:error, :beam_lib, {:missing_chunk, _, @docs_chunk}} ->
        nil
    end
  end

  defp lookup_docs({:elixir_docs_v1, docs}, kind), do: do_lookup_docs(docs, kind)

  # unsupported chunk version
  defp lookup_docs(_, _), do: nil

  defp do_lookup_docs(docs, :all), do: docs
  defp do_lookup_docs(docs, kind), do: Keyword.get(docs, kind)

  ## Helpers

  # Finds the file given the relative_to path.
  #
  # If the file is found, returns its path in binary, fails otherwise.
  defp find_file(file, relative_to) do
    file =
      if relative_to do
        Path.expand(file, relative_to)
      else
        Path.expand(file)
      end

    if File.regular?(file) do
      file
    else
      raise Code.LoadError, file: file
    end
  end
end