# `Noizu.Tessera.Component.Expr`
[🔗](https://github.com/the-robot-lives/tessera/blob/v0.2.0/lib/noizu/tessera/component/expr.ex#L1)

SPIKE (`spike/elixir-to-lit`): translator for the restricted Elixir subset
accepted inside tessera element `action/2` bodies and `~TSR` template
expressions (see docs/notes/spike-elixir-to-lit.md §subset).

Everything in the subset compiles to a plain JavaScript expression string;
anything outside it raises `CompileError` NAMING the rejected construct
(that is the contract: no silent mistranslation).

## In the subset

  * literals — integers, floats, strings (with `` interpolation),
    booleans, `nil`, lists, keyword lists, atom-keyed/string-keyed maps,
    map update `%{state | key: value}`
  * reads — `state.<key>` (declared keys only), `params.<key>`, bound
    pattern variables, `map.key` / `map[:key]` access
  * arithmetic `+ - * /` (+ `div/2`, `rem/2`, `trunc/1`), comparison
    `== != < <= > >=`, boolean `and or not`
  * `if cond do .. else .. end` (expression form)
  * `emit(event, detail)` for declared events (detail atom keys are
    camelCased at this boundary — the JS wire convention, CONTRACT.md §1)
  * the high-value Lit directives (lit-parity 1d): `class_map(map)`,
    `style_map(map)`, `if_defined(expr)` and the bare `nothing` sentinel —
    lowered to `classMap`/`styleMap`/`ifDefined`/`nothing` (the element
    codegen adds the matching `lit` / `lit/directives/*` imports)
  * allowlisted `Kernel` / `String` / `Enum` calls (see the maps below)
    plus `|>` into any of them
  * single-clause single-argument anonymous `fn` — only as the callback of
    `Enum.map` / `Enum.filter`

## Not in the subset (each rejected by name at compile time)

  `case`, `cond`, `with`, comprehensions in actions, multi-clause `fn`s,
  captures `&f/1`, module calls outside the allowlist, structs, tuples,
  charlists, `++`, blocks, `try`, `receive`.

# `t`

```elixir
@type t() :: %Noizu.Tessera.Component.Expr{
  actions: term(),
  attrs: term(),
  callback?: term(),
  camel_map_keys?: term(),
  derived?: term(),
  events: term(),
  file: term(),
  inherited_actions: term(),
  line: term(),
  module: term(),
  props: term(),
  state_keys: term(),
  vars: term()
}
```

# `translate`

```elixir
@spec translate(Macro.t(), t()) :: String.t()
```

Translate a restricted-subset Elixir AST into a JavaScript expression.
Raises `CompileError` naming any construct outside the subset.

# `translate_action`

```elixir
@spec translate_action(Macro.t(), t()) :: String.t()
```

Validate + translate an action body: `fn state, params -> expr end`.
Returns the JavaScript expression for the NEXT state. Emits compile errors
for wrong arity, multiple clauses or non-subset bodies.

---

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