|
4 | 4 | Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
5 | 5 | :toc: left |
6 | 6 | :icons: font |
| 7 | +:source-highlighter: rouge |
7 | 8 |
|
8 | | -== What Is This? |
| 9 | +== What Is Affinescriptiser? |
9 | 10 |
|
10 | | -AffineScriptiser wraps existing code in **affine types, dependent types, and |
11 | | -algebraic effects** — compiling to WebAssembly with no garbage collector. |
| 11 | +Affinescriptiser takes existing code written in Rust, C, or Zig and wraps it with |
| 12 | +https://github.com/hyperpolymath/affinescript[AffineScript]'s type system -- combining |
| 13 | +**affine types** (resources used at most once) with **dependent types** (compile-time |
| 14 | +value constraints) -- then compiles the result to **WebAssembly**. |
12 | 15 |
|
13 | | -AffineScript combines Rust's ownership model with Idris-level dependent types |
14 | | -and Koka-style effects. AffineScriptiser makes this accessible to existing codebases. |
| 16 | +The outcome: resources such as file descriptors, sockets, GPU buffers, and heap |
| 17 | +allocations become *provably* safe. They cannot be leaked, double-freed, or used |
| 18 | +after release. The wrapped code ships as a `.wasm` binary with zero garbage collector |
| 19 | +and zero runtime overhead from the type proofs. |
| 20 | + |
| 21 | +Affinescriptiser is part of the https://github.com/hyperpolymath/iseriser[-iser family], |
| 22 | +a collection of tools that wrap existing code in a target language's capabilities |
| 23 | +without requiring users to learn that language. |
15 | 24 |
|
16 | 25 | == How It Works |
17 | 26 |
|
18 | | -Describe your interface contracts in `affinescriptiser.toml`. AffineScriptiser: |
| 27 | +You describe your code in an `affinescriptiser.toml` manifest, point at your source |
| 28 | +files, and declare which resources need affine tracking. |
19 | 29 |
|
20 | | -1. Analyses your function signatures and resource patterns |
21 | | -2. Generates AffineScript wrappers with ownership + dependent type contracts |
22 | | -3. Compiles to WebAssembly (no GC, no runtime, minimal binary) |
23 | | -4. Creates FFI bridges for calling from JavaScript, Rust, or C |
| 30 | +[source,toml] |
| 31 | +---- |
| 32 | +# affinescriptiser.toml — example manifest |
| 33 | +[workload] |
| 34 | +name = "secure-file-processor" |
| 35 | +entry = "src/lib.rs::process_file" |
| 36 | +strategy = "affine-wrap" |
24 | 37 |
|
25 | | -== Key Value |
| 38 | +[data] |
| 39 | +input-type = "FileHandle" |
| 40 | +output-type = "ProcessedResult" |
| 41 | +
|
| 42 | +[options] |
| 43 | +flags = ["track-file-descriptors", "track-allocations", "wasm-size-opt"] |
| 44 | +---- |
| 45 | + |
| 46 | +Affinescriptiser then: |
26 | 47 |
|
27 | | -* **Rust-level safety + Idris-level verification** → WASM |
28 | | -* **Dependent type contracts** verified at compile time |
29 | | -* **Algebraic effects** for clean error handling and IO |
30 | | -* **Zero-GC WebAssembly** — tiny, fast, portable binaries |
| 48 | +1. **Analyses** your function signatures and identifies resource handles |
| 49 | + (file descriptors, heap allocations, locks, GPU buffers) |
| 50 | +2. **Generates** AffineScript type annotations that enforce at-most-once usage |
| 51 | + for each tracked resource |
| 52 | +3. **Proves** via Idris2 that affine invariants hold across the FFI boundary |
| 53 | +4. **Compiles** the wrapped code to WebAssembly with size and performance |
| 54 | + optimisation |
31 | 55 |
|
32 | 56 | == Architecture |
33 | 57 |
|
34 | | -Follows the hyperpolymath -iser pattern: |
35 | | -manifest -> Idris2 ABI proof -> Zig FFI bridge -> target language codegen. |
36 | | -Part of the https://github.com/hyperpolymath/iseriser[-iser family]. |
| 58 | +.... |
| 59 | + affinescriptiser pipeline |
| 60 | + ┌──────────────────────────────────────────────────────────────────────────┐ |
| 61 | + │ │ |
| 62 | + │ ┌─────────────────┐ ┌───────────────────┐ ┌────────────────┐ │ |
| 63 | + │ │ affinescriptiser │ │ Source Analysis │ │ Idris2 ABI │ │ |
| 64 | + │ │ .toml │────▶│ (Rust CLI) │────▶│ Proofs │ │ |
| 65 | + │ │ │ │ │ │ │ │ |
| 66 | + │ │ - entry point │ │ - parse signatures│ │ - ResourceKind│ │ |
| 67 | + │ │ - resource list │ │ - find handles │ │ - Linearity │ │ |
| 68 | + │ │ - WASM flags │ │ - map ownership │ │ - Ownership │ │ |
| 69 | + │ └─────────────────┘ └───────────────────┘ └───────┬────────┘ │ |
| 70 | + │ │ │ |
| 71 | + │ ▼ │ |
| 72 | + │ ┌─────────────────┐ ┌───────────────────┐ ┌────────────────┐ │ |
| 73 | + │ │ .wasm output │◀────│ AffineScript │◀────│ Zig FFI │ │ |
| 74 | + │ │ │ │ Codegen │ │ Bridge │ │ |
| 75 | + │ │ - zero GC │ │ │ │ │ │ |
| 76 | + │ │ - size-optimised│ │ - affine wrappers │ │ - C headers │ │ |
| 77 | + │ │ - portable │ │ - effect handlers │ │ - zero-cost │ │ |
| 78 | + │ └─────────────────┘ └───────────────────┘ └────────────────┘ │ |
| 79 | + │ │ |
| 80 | + └──────────────────────────────────────────────────────────────────────────┘ |
| 81 | +.... |
| 82 | + |
| 83 | +=== Layer Responsibilities |
| 84 | + |
| 85 | +[cols="1,3"] |
| 86 | +|=== |
| 87 | +| Layer | Role |
| 88 | + |
| 89 | +| **Manifest** (`affinescriptiser.toml`) |
| 90 | +| User declares what code to wrap and which resources to track. |
| 91 | + |
| 92 | +| **Source Analysis** (Rust, `src/manifest/`, `src/codegen/`) |
| 93 | +| Parses input source files, identifies resource handles and ownership patterns. |
| 94 | + |
| 95 | +| **Idris2 ABI** (`src/interface/abi/`) |
| 96 | +| Formal proofs that affine invariants (at-most-once usage, no leaks) hold. |
| 97 | + Defines `ResourceKind`, `Linearity`, `Ownership`, and WASM memory layout. |
| 98 | + |
| 99 | +| **Zig FFI** (`src/interface/ffi/`) |
| 100 | +| C-ABI compatible bridge between the proven ABI and the generated code. |
| 101 | + Zero runtime overhead, cross-compilation built in. |
| 102 | + |
| 103 | +| **AffineScript Codegen** (`src/codegen/`) |
| 104 | +| Generates AffineScript wrapper code with ownership annotations and |
| 105 | + algebraic effect handlers. Compiles to WASM. |
| 106 | + |
| 107 | +| **WASM Output** |
| 108 | +| Final `.wasm` binary. No garbage collector, no runtime, minimal size. |
| 109 | +|=== |
| 110 | + |
| 111 | +== Key Value |
| 112 | + |
| 113 | +**Automatic resource safety** -- files, sockets, GPU buffers, and heap allocations |
| 114 | +cannot be leaked or double-freed. The type system proves this at compile time, not |
| 115 | +at runtime. |
| 116 | + |
| 117 | +**WASM deployment** -- the output is a portable WebAssembly binary that runs in |
| 118 | +browsers, edge workers, IoT devices, or any WASM runtime. No GC means predictable |
| 119 | +latency and tiny binary size. |
| 120 | + |
| 121 | +**Zero target-language exposure** -- users never write AffineScript directly. They |
| 122 | +describe their intent in TOML and let affinescriptiser handle the wrapping, proving, |
| 123 | +and compilation. |
| 124 | + |
| 125 | +== Use Cases |
| 126 | + |
| 127 | +* **Browser sandboxed computation** -- run resource-safe code in the browser via WASM |
| 128 | + without worrying about memory leaks in long-running tabs |
| 129 | +* **Edge computing** -- deploy provably-safe WASM modules to Cloudflare Workers, |
| 130 | + Fastly Compute, or Deno Deploy with guaranteed resource bounds |
| 131 | +* **IoT firmware** -- compile to WASM for microcontrollers with formal proof that |
| 132 | + bounded memory is respected |
| 133 | +* **GPU buffer management** -- wrap CUDA/Vulkan buffer allocations with affine types |
| 134 | + to prevent double-free and use-after-free in compute shaders |
| 135 | +* **Secure file processing** -- process sensitive files with compile-time proof that |
| 136 | + file handles are closed exactly once |
| 137 | + |
| 138 | +== CLI Commands |
| 139 | + |
| 140 | +[source,bash] |
| 141 | +---- |
| 142 | +# Initialise a new manifest in the current directory |
| 143 | +affinescriptiser init |
| 144 | +
|
| 145 | +# Validate your manifest |
| 146 | +affinescriptiser validate -m affinescriptiser.toml |
| 147 | +
|
| 148 | +# Generate AffineScript wrappers, Zig FFI bridge, and C headers |
| 149 | +affinescriptiser generate -m affinescriptiser.toml -o generated/affinescriptiser |
| 150 | +
|
| 151 | +# Build the generated artifacts |
| 152 | +affinescriptiser build -m affinescriptiser.toml --release |
| 153 | +
|
| 154 | +# Run the workload |
| 155 | +affinescriptiser run -m affinescriptiser.toml -- --input data.bin |
| 156 | +
|
| 157 | +# Show manifest information |
| 158 | +affinescriptiser info -m affinescriptiser.toml |
| 159 | +---- |
| 160 | + |
| 161 | +== Building from Source |
| 162 | + |
| 163 | +[source,bash] |
| 164 | +---- |
| 165 | +# Prerequisites: Rust (nightly), Idris2, Zig |
| 166 | +cargo build --release |
| 167 | +
|
| 168 | +# Run tests |
| 169 | +cargo test |
| 170 | +
|
| 171 | +# Full quality check (format, lint, test) |
| 172 | +just quality |
| 173 | +---- |
37 | 174 |
|
38 | 175 | == Status |
39 | 176 |
|
40 | | -**Pre-alpha.** Architecture defined, scaffolding in place, codegen pending. |
| 177 | +**Pre-alpha / Scaffold.** The architecture is defined, the CLI is functional (init, |
| 178 | +validate, info), and the RSR template with full CI/CD is in place. Code generation |
| 179 | +is stubbed -- the `generate` command creates output directories but does not yet emit |
| 180 | +AffineScript wrappers. The Idris2 ABI proofs and Zig FFI bridge contain template |
| 181 | +placeholders awaiting domain-specific implementation. |
| 182 | + |
| 183 | +See link:ROADMAP.adoc[ROADMAP.adoc] for the phased development plan. |
41 | 184 |
|
42 | 185 | == License |
43 | 186 |
|
|
0 commit comments