// SPDX-License-Identifier: CC-BY-SA-4.0
= affine-res
:toc:
:icons: font

ReScript bindings for AffineScript WASM modules.

Wraps `@hyperpolymath/affine-js` with idiomatic ReScript types, exhaustive
pattern matching on `AffineScriptValue.t`, and typed call shortcuts that
extract native ReScript values without manual type hints.

== Installation

[source,json]
----
// rescript.json — add to bs-dependencies
{
  "bs-dependencies": ["affine-res"]
}
----

== Quick start

[source,rescript]
----
open AffineRes

let main = async () => {
  // Load a compiled AffineScript program:
  let mod = await AffineScript.fromFile("./calculator.wasm")

  // Typed call — returns a ReScript int directly:
  let sum = mod->AffineScript.callInt("add", [Value.Int(3), Value.Int(4)])
  Console.log(sum)  // 7

  // Generic call with pattern matching:
  let result = mod->AffineScript.call("safe_divide", ~returnType="result",
    [Value.Int(10), Value.Int(0)])
  switch result {
  | Ok(Int(n)) => Console.log(`Result: ${Int.toString(n)}`)
  | Err(String(msg)) => Console.error(`Error: ${msg}`)
  | _ => Console.error("Unexpected shape")
  }
}
----

== AffineScriptValue.t

All values crossing the WASM boundary use the `AffineScriptValue.t` variant:

[source,rescript]
----
type t =
  | Int(int)
  | Float(float)
  | Bool(bool)
  | Unit
  | String(string)
  | Some(t)
  | None
  | Ok(t)
  | Err(t)
  | Array(array<t>)
  | Record(Js.Dict.t<t>)
----

Exhaustive pattern matching is enforced by the ReScript compiler — you can
never forget to handle an `Err` case.

== Typed shortcuts

[cols="2,2"]
|===
| Function | Returns

| `callInt(mod, name, args)`
| `int`

| `callFloat(mod, name, args)`
| `float`

| `callBool(mod, name, args)`
| `bool`

| `callString(mod, name, args)`
| `string`

| `callOption(mod, name, args)`
| `option<AffineScriptValue.t>`

| `callOk(mod, name, args)`
| `AffineScriptValue.t` (raises on Err)
|===

== License

PMPL-1.0-or-later.
See link:../../LICENSE[LICENSE] at the repository root.
