# `Expression`

Documentation for `Expression`, a library to parse and evaluate
[Floip](https://floip.gitbook.io/flow-specification/expressions) compatible expressions

Expression is an expression language which consists of the functions provided
by Excel with a few additions.

Function and variable names are not case-sensitive so UPPER is equivalent to upper:

```
contact.name -> Marshawn Lynch
FIRST_WORD(contact.name) -> Marshawn
first_word(CONTACT.NAME) -> Marshawn
```

For templating, RapidPro uses the @ character to denote either a single variable substitution
or the beginning of an Expression block. `@` was chosen as it is known how to type by a broad
number of users regardless of keyboard. It does have the disadvantage of being used in
email addresses and Twitter handles, but these are rarely ambiguous and escaping can be
done easily via doubling of the character (`@@`).

Functions are called by using the block syntax:
```
10 plus 4 is @(SUM(10, 4))
```

Within a block, `@` is not required to refer to variable in the context:
```
Hello @(contact.name)
```

A template can contain more than one substitution or block:
```
Hello @contact.name, you were born in @(YEAR(contact.birthday))
```

# `expression_type`

```elixir
@type expression_type() ::
  String.t() | number() | map() | DateTime.t() | Date.t() | Time.t()
```

# `error`

> This function is deprecated. Use %Expression.Error{type: :function, message: message} instead.

```elixir
@spec error(message :: term()) :: %{required(String.t()) =&gt; term()}
```

Generate an error map.

Deprecated: use `Expression.Error` exception struct instead.
This function will be removed in a future major version.

# `escape`

```elixir
@spec escape(String.t()) :: String.t()
```

# `evaluate`

# `evaluate!`

# `evaluate_as_boolean!`

# `evaluate_as_string!`

```elixir
@spec evaluate_as_string!(
  String.t() | Number.t() | nil,
  map(),
  module()
) :: String.t()
```

# `evaluate_block`

# `evaluate_block!`

# `evaluate_template!`

```elixir
@spec evaluate_template!(String.t(), map(), module()) :: String.t()
```

Evaluate a string as an expression template, resolving any `@variable`
references and `@(expression)` blocks within it.

This is the explicit version of the behavior that occurs implicitly when
a string literal appears inside an expression (e.g., `"hello @name"`
as an argument to a function). Use this when you need template resolution
and want to be explicit about it.

Raises `Expression.Error` on parse or evaluation failures.

## Examples

    iex> Expression.evaluate_template!("hello @name", %{"name" => "world"})
    "hello world"

    iex> Expression.evaluate_template!("1 + 1 = @(1 + 1)", %{})
    "1 + 1 = 2"

# `parse!`

```elixir
@spec parse!(String.t() | Number.t() | Time.t() | boolean()) :: Keyword.t()
```

# `parse_expression`

```elixir
@spec parse_expression(String.t()) :: {:ok, Keyword.t()} | {:error, String.t()}
```

# `parse_expression!`

```elixir
@spec parse_expression!(String.t()) :: Keyword.t()
```

# `prewalk`

# `stringify`

```elixir
@spec stringify([expression_type()] | expression_type()) :: String.t()
```

Convert an Expression type into a string.

This function is applied to all values when `Expression.evaluate_as_string!/3` is called.

# `time_struct?`

```elixir
@spec time_struct?(String.t() | Time.t()) :: boolean()
```

# `traverse`

---

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