|
1 | 1 | // SPDX-License-Identifier: MPL-2.0 |
2 | 2 | // SPDX-FileCopyrightText: 2024-2026 Jonathan D.A. Jewell (hyperpolymath) |
3 | 3 | = AffineScript Faces — Design & Implementation Reference |
| 4 | +Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
4 | 5 | :toc: macro |
5 | 6 | :toclevels: 2 |
6 | 7 | :source-highlighter: rouge |
@@ -71,15 +72,64 @@ The compiler is face-agnostic throughout. The two face-aware layers are: |
71 | 72 | | `--face pseudocode` or `--face pseudo` |
72 | 73 | | `.pseudoaff` |
73 | 74 | | Beta (2026-04-11) |
| 75 | + |
| 76 | +| Lucid (PureScript / Haskell) |
| 77 | +| `--face lucid` |
| 78 | +| `.lucidaff` |
| 79 | +| Beta (2026-06) |
| 80 | + |
| 81 | +| Cafe (CoffeeScript) |
| 82 | +| `--face cafe` or `--face coffee` |
| 83 | +| `.cafeaff` |
| 84 | +| Beta (2026-06) |
| 85 | +|=== |
| 86 | + |
| 87 | +=== Brand-surface repos |
| 88 | + |
| 89 | +Each non-canonical face has a brand-surface repo — examples, community docs, |
| 90 | +migration guides, and a `bin/<face>` shim that injects `--face`. The compiler, |
| 91 | +type checker, borrow checker, and codegen live only here in affinescript; the |
| 92 | +brand repos carry no compiler. |
| 93 | + |
| 94 | +[cols="1,2,2", options="header"] |
74 | 95 | |=== |
| 96 | +| Face | Brand repo | Transformer |
| 97 | + |
| 98 | +| RattleScript (Python) | `hyperpolymath/rattlescript` | `lib/python_face.ml` |
| 99 | +| JaffaScript (JS / TS) | `hyperpolymath/jaffascript` | `lib/js_face.ml` |
| 100 | +| PseudoScript (pseudocode) | `hyperpolymath/pseudoscript` | `lib/pseudocode_face.ml` |
| 101 | +| LucidScript (PureScript) | `hyperpolymath/lucidscript` | `lib/lucid_face.ml` |
| 102 | +| CafeScripto (CoffeeScript) | `hyperpolymath/cafescripto` | `lib/cafe_face.ml` |
| 103 | +|=== |
| 104 | + |
| 105 | +=== Same-cube grounding |
| 106 | + |
| 107 | +The "different faces, same cube" claim is grounded by |
| 108 | +`hyperpolymath/invariant-path` (the `faces` profile + `scripts/verify-same-cube.sh`), |
| 109 | +which compiles one program written in every face to typed-wasm and compares the |
| 110 | +modules. Per-face snapshot stability is covered separately by |
| 111 | +`tools/run_face_transformer_tests.sh` (currently 6/6 green). |
| 112 | + |
| 113 | +*Known transformer-consistency item (grounded 2026-06-18):* on the `greet` |
| 114 | +corpus the six faces compile to *two* wasm modules — `{canonical, jaffa, cafe}` |
| 115 | +vs `{rattle, pseudo, lucid}` — because the transformers disagree on |
| 116 | +trailing-statement lowering (statement `{ println(x); }` vs tail-expression |
| 117 | +`{ println(x) }`). The programs are observationally identical (same output, |
| 118 | +same unit return) but the wasm is not byte-identical. Making the transformers |
| 119 | +agree on trailing-statement lowering would yield byte-level same-cube. |
75 | 120 |
|
76 | 121 | == Roadmap Faces |
77 | 122 |
|
78 | | -These faces are on the roadmap but have not been designed in detail. The |
79 | | -face architecture makes implementation cheap once the surface mapping is |
80 | | -settled; the bottleneck is design, not code. |
| 123 | +ActionScript-face remains on the roadmap (CoffeeScript has since shipped as |
| 124 | +CafeScripto — see Active Faces above). The face architecture makes |
| 125 | +implementation cheap once the surface mapping is settled; the bottleneck is |
| 126 | +design, not code. |
| 127 | + |
| 128 | +=== CoffeeScript-face — SHIPPED as CafeScripto |
81 | 129 |
|
82 | | -=== CoffeeScript-face (strategic priority) |
| 130 | +NOTE: This face is now *established* (`lib/cafe_face.ml`, `--face cafe`; see the |
| 131 | +Active Faces table and `hyperpolymath/cafescripto`). The design notes below are |
| 132 | +retained as historical reference; only ActionScript-face remains on the roadmap. |
83 | 133 |
|
84 | 134 | *Rationale:* CoffeeScript has a loyal displaced community that never loved |
85 | 135 | JavaScript and were forced away when the ecosystem moved on. Their syntax |
|
0 commit comments