funct 0.1.0

A small, functional, embeddable scripting language with a fully reified bytecode VM you can pause, snapshot, and resume.
Documentation
// glow.ft — a tiny animated style effect, the kind of script the jim-editor
// style system loads and hot-reloads. The host owns the drawing surface
// (uniform_set / mask_paint) and a persistent `state` atom; the script is
// pure logic that calls into that surface once per frame.
//
// This is the "what would it look like in our app" demo. Note mask_paint
// takes FIVE arguments — the host registers it with register5.

// The drawing surface (uniform_set, mask_paint, oklch, emit, …) and the
// canvas size come from the shared host interface. mask_paint takes FIVE
// arguments — the host registers it with register5.
import "host"

// `state` is a host-owned atom, so it survives a hot reload of this file.
// It's specific to this widget, so it stays a local extern.
extern let state

fn on_init() {
    host_log("glow init on ${canvas_w}x${canvas_h} canvas")
    set_animating(true)
    reset!(state, { t: 0.0, frames: 0 })
    emit("ready", { effect: "glow" })
}

// Called once per frame with the delta time in seconds.
fn tick(dt) {
    let s = @state
    let t = s.t + dt

    // pulse a shader uniform between 0 and 1
    let pulse = 0.5 + 0.5 * sin(t * 3.0)
    uniform_set("u_glow", pulse)
    uniform_set("u_tint", oklch(0.7, 0.15, t * 40.0))

    // sweep a soft brush across the canvas, painting into a mask texture
    let x = (t * 120.0) % canvas_w
    let y = canvas_h * 0.5
    mask_paint("ripple", x, y, 48.0, pulse)

    reset!(state, assoc(assoc(s, "t", t), "frames", s.frames + 1))
}

// The host reads persisted state back through plain script functions.
fn frame_count() = (@state).frames