# `Feel.Analysis.External`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/analysis/external.ex#L1)

An external function (`function(a, b) external {java: {...}}`, DMN 1.6 10.3.2.13), lowered to a call of the function that an
extension adds for its kind (D-211).

FEEL does not say how an external function is run: the body names a kind (`java`, `pmml`) and describes the function in that
kind's terms. DMN 1.6 has no way for the library to run one, so the analyzer refuses it, and `Feel.Extension` is where a host adds
one. For the kind `java` an extension adds a function named `external java`, which takes the description and the list of the
arguments:

    function(n1, n2) external {java: {class: "java.lang.Math", method signature: "max(double,double)"}}

is read as

    function(n1, n2) external java({class: "java.lang.Math", method signature: "max(double,double)"}, [n1, n2])

and is analyzed as that, so the function is an ordinary function of FEEL (it has the declared parameters, its closure, its type),
the call is an ordinary call of a function of an extension (it is not folded when the function is not pure, and its result is
typed by its signature), and nothing in the library knows what `java` means.

The body has to be a context of one entry, whose key (a name or a string) is the kind, and an extension has to add the function of
that kind. Otherwise there is nothing to lower to, and the function stays external, which the analyzer reports as
`:not_implemented` as it does without extensions. This module only builds the node; `lower/2` is the whole of it.

    iex> {:ok, ast} = Feel.parse(~S|function(a) external {demo: {x: 1}}|)
    iex> Feel.Analysis.External.lower(ast, Feel.Extensions.none())
    :error

# `function_name`

```elixir
@spec function_name(String.t()) :: Feel.Name.t()
```

The name of the function that an extension adds for an external function of this kind: `external java` for `java`.

    iex> Feel.Analysis.External.function_name("java")
    "external java"

# `lower`

```elixir
@spec lower(Feel.AST.expression(), Feel.Extensions.t()) ::
  {:ok, Feel.AST.expression()} | :error
```

The function without `external`, with a call of the function of its kind for the body, or `:error` if the body is not a context of
one entry or no extension adds the function.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
