# `A2UIAgent.Express.Decompiler`
[🔗](https://github.com/a2ui-elixir/a2ui/blob/v0.1.1/umbrella/apps/a2ui_agent/lib/a2ui_agent/express/decompiler.ex#L1)

Writes A2UI messages back as Express.

    {:ok, catalogs} = A2UIAgent.Express.Catalogs.new([catalog])

    A2UIAgent.Express.Decompiler.decompile(catalogs, [
      %{"version" => "v1.0", "deleteSurface" => %{"surfaceId" => "s1"}}
    ])
    #=> {:ok, ~s|deleteSurface("s1")|}

Messages are first coalesced: an `updateComponents`, and a root
`updateDataModel` with an object value, that follow a `createSurface`
for the same surface merge into it while that does not change what the
messages mean. Each surface becomes a `surface(...)` block (left out
for the default surface at the start), an update stays an update
(`update=true` when it carries a `root`), and deletes and renderer
function calls become statements of their own.

Components are written positionally in the order
`A2UIAgent.Express.SchemaHelper` gives, with `_` for a skipped
property; an id that is not an Express identifier gets a derived
variable name and an `id=` argument. A check whose `value` argument is
the component's own binding leaves it implicit, and a message other
than the default is written after the parameters. Data model values
are written one assignment per leaf, in path order. The result
compiles back to the same messages.

Map keys and event context keys are written in the order the message
has them: a message read with `objects: :ordered_objects` keeps its
order.

# `decompile`
*since 0.1.0* 

```elixir
@spec decompile(A2UIAgent.Express.Catalogs.t(), [map()] | map(), keyword()) ::
  {:ok, String.t()} | {:error, A2UICore.Error.t()}
```

Decompiles `messages` (a list, or one message). A component or
function the catalogs do not define is a `:validation` error.

With several catalogs, a component that names no `catalogId` belongs to
its surface's catalog, which the surface's `createSurface` names. For
messages that update surfaces created earlier, pass those surfaces'
catalogs as the `:surface_catalogs` option, a map of catalog ids by
surface id.

# `number`
*since 0.1.0* 

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

Writes a number as Python's `str` does: integers as they are, floats
with a decimal point (`1500.0`), or in exponent form outside
`1e-4 <= |x| < 1e16`.

    iex> A2UIAgent.Express.Decompiler.number(1500.0)
    "1500.0"
    iex> A2UIAgent.Express.Decompiler.number(0.1)
    "0.1"

# `string`
*since 0.1.0* 

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

Writes a string as the most readable Express literal: a triple-quoted
string for several lines, a raw string for backslashes, otherwise a
quoted string with escapes.

    iex> A2UIAgent.Express.Decompiler.string(~S(C:\temp))
    ~S(r"C:\temp")
    iex> A2UIAgent.Express.Decompiler.string(~s(say "hi"))
    ~S("say \"hi\"")

# `wrap_decompiled_blocks`
*since 0.1.0* 

```elixir
@spec wrap_decompiled_blocks([String.t()]) :: String.t()
```

Encloses decompiled blocks in one pair of `<a2ui>` tags.

    iex> A2UIAgent.Express.Decompiler.wrap_decompiled_blocks([~s|root = Text("a")|])
    ~s|<a2ui>\nroot = Text("a")\n</a2ui>|

---

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