@live-codes/browser-haskell 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +199 -0
- package/dist/browser-haskell.iife.js +34 -0
- package/dist/browser-haskell.iife.js.map +7 -0
- package/dist/browser-haskell.mjs +34 -0
- package/dist/browser-haskell.mjs.map +7 -0
- package/dist/index.d.ts +77 -0
- package/dist/mhs/VERSION.md +36 -0
- package/dist/mhs/mhs-embed.js +1 -0
- package/dist/mhs/mhs-embed.wasm +0 -0
- package/dist/pkgs/index.json +739 -0
- package/dist/pkgs/packages/Diff-1.0.2.pkg +0 -0
- package/dist/pkgs/packages/HUnit-1.6.2.0.pkg +0 -0
- package/dist/pkgs/packages/QuickCheck-2.18.0.0.pkg +0 -0
- package/dist/pkgs/packages/ansi-terminal-1.1.5.pkg +0 -0
- package/dist/pkgs/packages/ansi-terminal-types-1.1.3.pkg +0 -0
- package/dist/pkgs/packages/array-mhs-0.5.8.0.pkg +0 -0
- package/dist/pkgs/packages/async-2.2.6.pkg +0 -0
- package/dist/pkgs/packages/call-stack-0.4.0.pkg +0 -0
- package/dist/pkgs/packages/colour-2.3.7.pkg +0 -0
- package/dist/pkgs/packages/containers-0.8.pkg +0 -0
- package/dist/pkgs/packages/data-ordlist-0.4.7.0.pkg +0 -0
- package/dist/pkgs/packages/dlist-1.0.pkg +0 -0
- package/dist/pkgs/packages/edit-distance-0.2.2.1.pkg +0 -0
- package/dist/pkgs/packages/exceptions-0.10.11.pkg +0 -0
- package/dist/pkgs/packages/fgl-5.8.3.1.pkg +0 -0
- package/dist/pkgs/packages/filepath-1.5.5.0.pkg +0 -0
- package/dist/pkgs/packages/fingertree-0.1.6.3.pkg +0 -0
- package/dist/pkgs/packages/ghc-compat-0.5.11.0.pkg +0 -0
- package/dist/pkgs/packages/haskell-lexer-1.2.1.pkg +0 -0
- package/dist/pkgs/packages/heaps-0.4.1.pkg +0 -0
- package/dist/pkgs/packages/hspec-2.11.17.pkg +0 -0
- package/dist/pkgs/packages/hspec-core-2.11.17.pkg +0 -0
- package/dist/pkgs/packages/hspec-discover-2.11.17.pkg +0 -0
- package/dist/pkgs/packages/hspec-expectations-0.8.4.pkg +0 -0
- package/dist/pkgs/packages/monad-loops-0.4.3.pkg +0 -0
- package/dist/pkgs/packages/mtl-2.3.2.pkg +0 -0
- package/dist/pkgs/packages/numbers-3000.2.0.2.pkg +0 -0
- package/dist/pkgs/packages/os-string-2.0.10.pkg +0 -0
- package/dist/pkgs/packages/parallel-3.3.0.0.pkg +0 -0
- package/dist/pkgs/packages/parsec-3.1.18.0.pkg +0 -0
- package/dist/pkgs/packages/pretty-1.1.3.6.pkg +0 -0
- package/dist/pkgs/packages/prettyprinter-1.7.2.pkg +0 -0
- package/dist/pkgs/packages/psqueues-0.2.8.3.pkg +0 -0
- package/dist/pkgs/packages/quickcheck-io-0.2.0.pkg +0 -0
- package/dist/pkgs/packages/random-mhs-1.3.2.2.pkg +0 -0
- package/dist/pkgs/packages/semigroups-0.20.1.pkg +0 -0
- package/dist/pkgs/packages/split-0.2.5.1.pkg +0 -0
- package/dist/pkgs/packages/splitmix-0.1.3.2.pkg +0 -0
- package/dist/pkgs/packages/tagsoup-0.14.8.pkg +0 -0
- package/dist/pkgs/packages/time-1.15.pkg +0 -0
- package/dist/pkgs/packages/transformers-0.6.2.0.pkg +0 -0
- package/dist/pkgs/packages/unordered-containers-0.2.21.pkg +0 -0
- package/dist/pkgs/packages/xhtml-3000.2.2.1.pkg +0 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# @live-codes/browser-haskell
|
|
2
|
+
|
|
3
|
+
Run Haskell entirely in the browser. Powered by [MicroHs](https://github.com/augustss/MicroHs)
|
|
4
|
+
compiled to WebAssembly — no server, no install, ~1.8 MB of wasm plus the packages a program
|
|
5
|
+
actually imports.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import { createHaskell } from '@live-codes/browser-haskell';
|
|
9
|
+
|
|
10
|
+
const haskell = await createHaskell();
|
|
11
|
+
const result = await haskell.run({
|
|
12
|
+
code: 'main :: IO ()\nmain = interact (unlines . map reverse . lines)',
|
|
13
|
+
stdin: 'hello\nworld\n',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
result.stdout; // "olleh\ndlrow\n"
|
|
17
|
+
result.stderr; // ""
|
|
18
|
+
result.error; // null
|
|
19
|
+
result.exitCode; // 0
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm install @live-codes/browser-haskell
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or load it from a CDN — no bundler required:
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<script src="https://cdn.jsdelivr.net/npm/@live-codes/browser-haskell/dist/browser-haskell.iife.js"></script>
|
|
32
|
+
<script>
|
|
33
|
+
const haskell = await BrowserHaskell.createHaskell();
|
|
34
|
+
const { stdout, error, exitCode } = await haskell.run({ code: 'main = putStrLn "hi"' });
|
|
35
|
+
</script>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The IIFE build exposes `BrowserHaskell` and works out of the box: with no `baseUrl` it loads its
|
|
39
|
+
assets from the directory it was served from.
|
|
40
|
+
|
|
41
|
+
## API
|
|
42
|
+
|
|
43
|
+
### `createHaskell(options?) → Promise<Haskell>`
|
|
44
|
+
|
|
45
|
+
Boots MicroHs (~0.5–2 s; the wasm is instantiated and the REPL reaches its prompt) and returns an
|
|
46
|
+
instance. Do this once per page or worker.
|
|
47
|
+
|
|
48
|
+
| option | default | meaning |
|
|
49
|
+
| --- | --- | --- |
|
|
50
|
+
| `baseUrl` | this module's directory | Where the assets are: `mhs/mhs-embed.js` (+ `.wasm`) and `pkgs/index.json` (+ `pkgs/packages/`). |
|
|
51
|
+
| `wasmUrl` | `baseUrl + 'mhs/mhs-embed.js'` | Full URL of the compiler's JS glue. |
|
|
52
|
+
| `packagesUrl` | `baseUrl + 'pkgs/'` | Directory holding `index.json` and `packages/`. |
|
|
53
|
+
| `importmap` | `{}` | Packages by module name, for ones that are not bundled: `{ 'My.Module': 'https://…/my-pkg.pkg' }`. See below. |
|
|
54
|
+
| `timeout` | `60000` | Per-run timeout in ms. |
|
|
55
|
+
| `onLog` | – | `(message) => void` for diagnostics. |
|
|
56
|
+
|
|
57
|
+
### `haskell.run({ code, stdin?, timeout? }) → Promise<RunResult>`
|
|
58
|
+
|
|
59
|
+
Compiles and runs `code` as a `Main` module.
|
|
60
|
+
|
|
61
|
+
| field | meaning |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `stdout` | what the program wrote to stdout |
|
|
64
|
+
| `stderr` | what the program wrote to stderr |
|
|
65
|
+
| `error` | compile errors and runtime exceptions, or `null` |
|
|
66
|
+
| `output` | stdout, stderr and diagnostics together, in the order produced |
|
|
67
|
+
| `exitCode` | `0` on success, `1` on error, `124` on timeout |
|
|
68
|
+
| `packages` | MicroHs package files that had to be fetched for this run |
|
|
69
|
+
| `durationMs` | wall-clock time for the run |
|
|
70
|
+
|
|
71
|
+
`import`ed modules that cannot be satisfied are reported *before* anything is compiled, with a
|
|
72
|
+
reason rather than a bare `Module not found`:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
const r = await haskell.run({ code: 'import Data.Aeson\nmain = pure ()' });
|
|
76
|
+
r.error; // "Not available in this playground:\n Data.Aeson — not bundled with this playground\n…"
|
|
77
|
+
r.exitCode; // 1
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `haskell.dispose()`
|
|
81
|
+
|
|
82
|
+
Releases the instance. Browsers cannot unload a wasm module, so this drops the library's
|
|
83
|
+
references rather than freeing memory — use one instance per page or worker, and reuse it.
|
|
84
|
+
|
|
85
|
+
## stdin
|
|
86
|
+
|
|
87
|
+
The web build of MicroHs has no usable file descriptor 0: `getLine` throws
|
|
88
|
+
`Handle(stdin): end of file`, and characters pushed at the REPL are read by the *REPL*, not by the
|
|
89
|
+
running program. So `stdin` is injected as source instead, in two ways:
|
|
90
|
+
|
|
91
|
+
1. `lcInput :: String`, `lcInputLines :: [String]`, `lcInputWords :: [String]` — always available
|
|
92
|
+
when `stdin` is passed, no imports needed.
|
|
93
|
+
2. Prelude's `getLine`, `readLn`, `getContents` and `interact` are **shadowed** by equivalents
|
|
94
|
+
that consume the same input, so ordinary programs work unchanged:
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
await haskell.run({
|
|
98
|
+
code: `
|
|
99
|
+
main :: IO ()
|
|
100
|
+
main = do
|
|
101
|
+
[n, k] <- fmap (map read . words) getLine
|
|
102
|
+
print (n + k :: Int)`,
|
|
103
|
+
stdin: '2 40\n',
|
|
104
|
+
}); // stdout: "42"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Imports of `Data.IORef` and `System.IO.Unsafe` are hoisted to the top of your module to make that
|
|
108
|
+
work; if your program defines `getLine`, `readLn`, `getContents`, `interact` or `lcInput` itself,
|
|
109
|
+
yours is kept and ours is not injected.
|
|
110
|
+
|
|
111
|
+
## What is available
|
|
112
|
+
|
|
113
|
+
The wasm embeds MicroHs's `base` (which is larger than GHC's — it includes `bytestring`, `text`,
|
|
114
|
+
`deepseq`, `directory`, `stm`, `process`, `hashable`) plus `canvhs`. On top of that, 43 packages
|
|
115
|
+
are fetched **on demand** — only what a program imports:
|
|
116
|
+
|
|
117
|
+
`containers`, `array`, `transformers`, `mtl`, `exceptions`, `filepath`, `os-string`, `time`,
|
|
118
|
+
`random`, `splitmix`, `unordered-containers`, `async`, `parsec`, `pretty`, `xhtml`, `semigroups`,
|
|
119
|
+
`fgl`, `fingertree`, `heaps`, `psqueues`, `tagsoup`, `edit-distance`, `Diff`, `data-ordlist`,
|
|
120
|
+
`dlist`, `split`, `monad-loops`, `prettyprinter`, `numbers`, `parallel`, `HUnit`, `QuickCheck`,
|
|
121
|
+
`hspec` (+ `hspec-core`, `hspec-expectations`, `hspec-discover`, `quickcheck-io`, `call-stack`,
|
|
122
|
+
`ansi-terminal`, `ansi-terminal-types`, `colour`, `haskell-lexer`, `ghc-compat`).
|
|
123
|
+
|
|
124
|
+
Modules that can never work here (`Language.Haskell.TH`, `GHC.*`, `System.Posix.*`, `Network.*`,
|
|
125
|
+
`Data.Vector`, `Data.Aeson`, `Control.Lens`, …) are reported with a reason. `Data.Binary` compiles
|
|
126
|
+
but its reader loops forever, so it is deliberately withheld rather than shipped as a landmine.
|
|
127
|
+
|
|
128
|
+
### Custom packages (`importmap`)
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
const haskell = await createHaskell({
|
|
132
|
+
importmap: { 'My.Module': 'https://example.com/my-module.pkg' },
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The `.pkg` is a MicroHs package, and it must be built by the same MicroHs version as the bundled
|
|
137
|
+
compiler or it will not deserialize. The manifest cannot know anything about packages it does not
|
|
138
|
+
ship, so list their MicroHs dependencies in the `importmap` too.
|
|
139
|
+
|
|
140
|
+
## Assets
|
|
141
|
+
|
|
142
|
+
`dist/` contains the bundles, the type definitions, and the runtime assets:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
dist/browser-haskell.mjs ESM bundle (minified)
|
|
146
|
+
dist/browser-haskell.iife.js IIFE bundle, global `BrowserHaskell` (minified)
|
|
147
|
+
dist/index.d.ts types
|
|
148
|
+
dist/mhs/mhs-embed.js|.wasm MicroHs compiler (pinned 0.16.6.0)
|
|
149
|
+
dist/pkgs/index.json package manifest
|
|
150
|
+
dist/pkgs/packages/*.pkg 43 packages, ~11 MB, fetched lazily
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Point `baseUrl` at a copy of `dist/` on your own origin, or straight at a CDN:
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
const haskell = await createHaskell({
|
|
157
|
+
baseUrl: 'https://cdn.jsdelivr.net/npm/@live-codes/browser-haskell/dist/',
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
If your page is cross-origin isolated (`COEP: require-corp`), make sure the host serving the
|
|
162
|
+
assets sends the matching CORS/CORP headers — jsDelivr does.
|
|
163
|
+
|
|
164
|
+
## Limits
|
|
165
|
+
|
|
166
|
+
- **Browser only** (window or worker). There is no Node build: the compiler glue needs a DOM or a
|
|
167
|
+
worker scope.
|
|
168
|
+
- **One instance per page/worker.** The Emscripten glue is a classic script that installs globals,
|
|
169
|
+
so loading it twice in the same context is not supported. Everything else is reusable — run as
|
|
170
|
+
many programs as you like through one instance.
|
|
171
|
+
- **No interrupt.** A program that loops forever blocks the main thread and freezes the page; that
|
|
172
|
+
is a MicroHs/JavaScript limitation, not something this library can work around. A run that
|
|
173
|
+
merely takes too long rejects with `exitCode: 124` and poisons the instance (create a new one).
|
|
174
|
+
- **Execution is REPL-based.** MicroHs's web bundle cannot compile-and-run in batch mode, so each
|
|
175
|
+
run is `import Main` → `:reload` → `:main` behind a sentinel prompt. This is why runs take about
|
|
176
|
+
a second even for tiny programs.
|
|
177
|
+
- Template Haskell, type families, GHC internals and anything platform-specific are absent.
|
|
178
|
+
|
|
179
|
+
## Development
|
|
180
|
+
|
|
181
|
+
```sh
|
|
182
|
+
cd packages/browser-haskell
|
|
183
|
+
npm install
|
|
184
|
+
npm run build # dist/ — bundles, types and assets
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Open `test/index.html` (ESM) or `test/iife.html` (IIFE) to smoke-test the built output against the
|
|
188
|
+
real wasm and packages — serving from the repository root:
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
node serve.js 8124 .
|
|
192
|
+
# → http://localhost:8124/packages/browser-haskell/test/index.html
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
MIT. MicroHs itself is Apache-2.0; its wasm bundle is redistributed here unmodified, and the
|
|
198
|
+
package set in `dist/pkgs` is built from upstream Haskell packages (see the repository's
|
|
199
|
+
`PACKAGES.md`).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*! @live-codes/browser-haskell v0.1.0 | MIT
|
|
2
|
+
* Runs Haskell in the browser with MicroHs (Apache-2.0). */
|
|
3
|
+
var BrowserHaskell=(()=>{var L=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var B=(s,t)=>{for(var e in t)L(s,e,{get:t[e],enumerable:!0})},G=(s,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of q(t))!$.call(s,o)&&o!==e&&L(s,o,{get:()=>t[o],enumerable:!(n=H(t,o))||n.enumerable});return s};var J=s=>G(L({},"__esModule",{value:!0}),s);var ut={};B(ut,{MicroHs:()=>b,createHaskell:()=>Z,default:()=>lt});var K=s=>s.endsWith("/")?s:s+"/";function Q(s){let t=String(s).replace(/\{-[\s\S]*?-\}/g," ").split(`
|
|
4
|
+
`).map(a=>a.replace(/--.*$/,"")).join(`
|
|
5
|
+
`),e=[],n=/^[ \t]*import[ \t]+(?:safe[ \t]+)?(?:qualified[ \t]+)?(?:"[^"]*"[ \t]+)?([A-Z][A-Za-z0-9_.']*)/gm,o;for(;(o=n.exec(t))!==null;)e.indexOf(o[1])===-1&&e.push(o[1]);return e}function P(s){let t=String(s).split("?")[0].split("#")[0];return t.slice(t.lastIndexOf("/")+1)||"custom.pkg"}function C(s){let t=s||{},e=K(t.packagesUrl),n=t.importmap||{},o=t.log||(()=>{}),a=t.fetch||((...i)=>fetch(...i)),l=new Map;for(let i of Object.keys(n)){let r=n[i];if(typeof r!="string"||!r)continue;let p=P(r),f=l.get(p)||{name:p,url:r,modules:new Set};f.modules.add(i),l.set(p,f)}let d=null,c=null;function E(){if(!d){let i=e+"index.json";d=a(i,{cache:"no-store"}).then(r=>r.ok?r.json():null).then(r=>!r||Array.isArray(r)?(o("no package manifest at "+i+"; only the embedded modules are available"),null):(c=r,r)).catch(r=>(o("failed to load "+i+": "+(r&&r.message)),null))}return d}function y(i){if(l.has(i)){let r=l.get(i);return{kind:"package",pkg:r.name,url:r.url}}if(c&&c.modules&&c.modules[i])return{kind:"package",pkg:c.modules[i]};if(!c)return{kind:"unknown"};if(c.embedded&&c.embedded.indexOf(i)!==-1)return{kind:"embedded"};for(let r of c.unavailable||[])if(i===r.prefix||i.indexOf(r.prefix+".")===0)return{kind:"unavailable",reason:r.reason};return{kind:"unknown"}}function x(i){let r=new Set,p={},f=[];for(let h of Q(i)){if(n[h]){let S=P(n[h]);r.add(S),p[S]=n[h];continue}let w=y(h);w.kind==="package"?r.add(w.pkg):w.kind==="unavailable"?f.push({module:h,reason:w.reason}):w.kind==="unknown"&&f.push({module:h,reason:"not bundled with this playground"})}let m=new Set,u=Array.from(r);for(;u.length;){let h=u.shift();if(m.has(h))continue;m.add(h);let w=c&&c.packages&&c.packages[h]||[];for(let S of w)!m.has(S)&&u.indexOf(S)===-1&&u.push(S)}return{packages:Array.from(m).sort(),missing:f,urls:p}}function k(i){return l.has(i)?l.get(i).name:c&&c.modules&&c.modules[i]||null}function O(i){let r=[],p=new Set(i);if(c&&c.modules)for(let f of Object.keys(c.modules))p.has(c.modules[f])&&r.push(f);for(let f of l.values())p.has(f.name)&&r.push(...f.modules);return r}function g(i,r){let p={};return Promise.all(i.map(f=>{let m=r&&r[f]||e+"packages/"+f;return a(m,{cache:"force-cache"}).then(u=>{if(!u.ok)throw new Error("HTTP "+u.status+" for "+m);return u.arrayBuffer()}).then(u=>{p[f]=new Uint8Array(u)}).catch(u=>{o("could not fetch "+m+": "+(u&&u.message))})})).then(()=>p)}function D(i){if(!i||!i.length)return null;let r=["Not available in this playground:"];for(let p of i)r.push(" "+p.module+" \u2014 "+p.reason);if(c&&c.modules&&c.packages){let p=Object.keys(c.modules).length,f=(c.embedded||[]).length,m=Object.keys(c.packages).length,u=["Data.Map","Control.Monad.State","System.Random","Data.Time","Test.Hspec"].filter(h=>c.modules[h]!==void 0);r.push(""),r.push("This playground provides base ("+f+" modules) plus "+m+" packages ("+p+" modules), including "+(u.length?u.join(", ")+", \u2026":"see the manifest")+".")}return r.join(`
|
|
6
|
+
`)}function z(i){if(!i)return i;let r=[],p=/Module not found:\s*([A-Z][A-Za-z0-9_.']*)/g,f;for(;(f=p.exec(i))!==null;){let u=f[1];if(r.some(w=>w.module===u))continue;let h=y(u);h.kind==="unavailable"?r.push({module:u,reason:h.reason}):h.kind==="unknown"?r.push({module:u,reason:"not bundled with this playground"}):h.kind==="package"&&r.push({module:u,reason:"its package ("+h.pkg+") is not loaded"})}let m=D(r);return m?i+`
|
|
7
|
+
|
|
8
|
+
`+m:i}return{loadManifest:E,classifyModule:y,analyzeImports:x,packageOfModule:k,modulesOf:O,fetchPackages:g,explainMissing:D,explainNotFound:z,get manifest(){return c}}}var V=["import Data.IORef","import System.IO.Unsafe (unsafePerformIO)"];var v={"\\":"\\\\",'"':'\\"',"\n":"\\n","\r":"\\r"," ":"\\t"};function X(s){let t="";for(let e of String(s)){if(v[e]){t+=v[e];continue}let n=e.codePointAt(0);if(n<32||n===127){t+="\\"+n+"\\&";continue}t+=e}return t}function T(s,t){return new RegExp("^"+t+"\\s*(::|=)","m").test(s)}function Y(s){let t=s.findIndex(n=>/^module\s+[A-Z][A-Za-z0-9_.']*\s*(\(.*)?\bwhere\b/.test(n));if(t!==-1)return t+1;let e=0;for(;e<s.length;){let n=s[e].trim();if(!(n===""||n.startsWith("--")||n.startsWith("{-#")||n.startsWith("{-")||n.startsWith("#")))break;if(n.startsWith("{-")&&!n.includes("-}")){for(;e<s.length&&!s[e].includes("-}");)e++;e++;continue}e++}return e}function tt(s,t){let e=[],n=(o,a)=>{T(t,o)||e.push(a)};return n("lcInput",["-- stdin, injected by @live-codes/browser-haskell (this build has no fd 0)","lcInput :: String",'lcInput = "'+X(s)+'"'].join(`
|
|
9
|
+
`)),n("lcInputLines",`lcInputLines :: [String]
|
|
10
|
+
lcInputLines = lines lcInput`),n("lcInputWords",`lcInputWords :: [String]
|
|
11
|
+
lcInputWords = words lcInput`),T(t,"lcInput")||(e.push(["{-# NOINLINE lcStdinRef #-}","lcStdinRef :: IORef String","lcStdinRef = unsafePerformIO (newIORef lcInput)","","lcReadAll :: IO String","lcReadAll = do"," s <- readIORef lcStdinRef",' writeIORef lcStdinRef ""'," return s"].join(`
|
|
12
|
+
`)),n("getLine",["getLine :: IO String","getLine = do"," s <- readIORef lcStdinRef"," case s of",' [] -> return ""'," _ -> do"," let (l, rest) = break (== '\\n') s"," writeIORef lcStdinRef (drop 1 rest)"," return l"].join(`
|
|
13
|
+
`)),n("readLn",`readLn :: Read a => IO a
|
|
14
|
+
readLn = getLine >>= return . read`),n("getContents",`getContents :: IO String
|
|
15
|
+
getContents = lcReadAll`),n("interact",`interact :: (String -> String) -> IO ()
|
|
16
|
+
interact f = getContents >>= putStr . f`)),e.join(`
|
|
17
|
+
|
|
18
|
+
`)}function U(s,t){let e=String(s??""),n=String(t??"");if(!n)return e;let o=e.replace(/\s*$/,"").split(`
|
|
19
|
+
`),a=Y(o),l=V.filter(c=>!new RegExp("^"+c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"\\s*$","m").test(e));return(l.length?o.slice(0,a).concat([""]).concat(l).concat("").concat(o.slice(a)):o).join(`
|
|
20
|
+
`)+`
|
|
21
|
+
|
|
22
|
+
`+tt(n,e)+`
|
|
23
|
+
`}var F="/home/web_user",_="Main.hs",M="<<<LC_PROMPT>>>",I="/pkgs",et=3e4,nt=6e4,W=s=>new Promise(t=>setTimeout(t,s));async function ot(s){if(typeof document<"u"&&document.createElement){await new Promise((t,e)=>{let n=document.createElement("script");n.src=s,n.onload=()=>t(),n.onerror=()=>e(new Error("failed to load "+s)),(document.head||document.body||document.documentElement).appendChild(n)});return}if(typeof importScripts=="function"){importScripts(s);return}await import(s)}function st(s){let t="";for(let e of s)e==="\b"?t=t.slice(0,-1):t+=e;return t}function rt(s){return s.split(`
|
|
24
|
+
`).map(t=>{let e=t.lastIndexOf("\r");return e>=0?t.slice(e+1):t}).join(`
|
|
25
|
+
`)}function R(s,t){let e=s.split(M).join(""),n=rt(st(e.replace(/\u001b\[[0-9;?]*[A-Za-z]|\u001b[@-Z\\-_]|\u001b\([A-Za-z0-9]/g,"").replace(/\u0007/g,""))),o=[/^Welcome to interactive MicroHs/,/^Integer implemented with imath/,/^Loading embedded package /,/^Loading package /,/^loaded /,/^Type ':quit' to quit/];return n.split(`
|
|
26
|
+
`).filter(a=>{let l=a.trim();return!(o.some(d=>d.test(l))||(t||[]).some(d=>l===d))}).join(`
|
|
27
|
+
`)}function it(s){let t=s.trim();return/^(\*\*\* )?(Exception|error:|Error:)/.test(t)||/^Unrecognized command/.test(t)||/^fully qualified:/.test(t)||/: line \d+, col \d+:/.test(t)}function N(s){let t=[],e=[];for(let n of s.split(`
|
|
28
|
+
`))(it(n)?e:t).push(n);return{out:t,errors:e}}var j=s=>s.join(`
|
|
29
|
+
`).trim(),b=class{constructor(t){let e=t||{};this.options={wasmUrl:e.wasmUrl,packagesUrl:e.packagesUrl,importmap:e.importmap||{},timeout:e.timeout||nt,charDelay:e.charDelay==null?0:e.charDelay,onLog:typeof e.onLog=="function"?e.onLog:null,fetch:e.fetch},this.raw="",this.out="",this.err="",this.outDecoder=new TextDecoder("utf-8",{fatal:!1}),this.errDecoder=new TextDecoder("utf-8",{fatal:!1}),this.loaded=new Set,this.exitCode=null,this.fatal=null,this.ready=!1,this.running=!1,this.disposed=!1,this.poisoned=null,this.Module=null,this.resolver=null}log(t){this.options.onLog&&this.options.onLog(t)}promptCount(){let t=0,e=0;for(;(e=this.raw.indexOf(M,e))!==-1;)t++,e+=M.length;return t}async waitFor(t,e,n){for(;;){if(t())return;if(this.fatal)throw new Error(this.fatal);if(Date.now()>n){let o=new Error("timed out waiting for "+e);throw o.timeout=!0,o}await W(1)}}async typeLine(t,e){let n=new TextEncoder().encode(t+`
|
|
30
|
+
`);for(let o of n){if(Date.now()>e){let a=new Error("timed out while sending input");throw a.timeout=!0,a}this.Module._set_input_char(o),await W(this.options.charDelay)}}async step(t,e){let n=this.promptCount();await this.typeLine(t,e),await this.waitFor(()=>this.promptCount()>n,JSON.stringify(t),e)}async boot(){this.resolver=C({packagesUrl:this.options.packagesUrl,importmap:this.options.importmap,log:o=>this.log(o),fetch:this.options.fetch}),await this.resolver.loadManifest();let t=String(this.options.wasmUrl),e=t.slice(0,t.lastIndexOf("/")+1),n={arguments:["-a"+I],locateFile:o=>e+o,preRun:[function(){let o=n.FS;o.mkdirTree(F),o.chdir(F),o.writeFile(".mhsi_rc",":set prompt="+M+`
|
|
31
|
+
`),o.writeFile(_,"")}],stdin:()=>null,stdout:o=>o!==null&&this.appendOut(o),stderr:o=>o!==null&&this.appendErr(o),print:o=>this.appendOut(o+`
|
|
32
|
+
`),printErr:o=>this.appendErr(o+`
|
|
33
|
+
`),onExit:o=>{this.exitCode=o,this.log("compiler exited with "+o)},onAbort:o=>{this.fatal=String(o)}};return this.Module=n,globalThis.Module=n,this.log("loading "+t),await ot(t),await this.waitFor(()=>this.promptCount()>0,"the REPL to start",Date.now()+et),this.ready=!0,this.log("ready"),this}appendOut(t){let e=typeof t=="number"?this.outDecoder.decode(new Uint8Array([t]),{stream:!0}):String(t);this.out+=e,this.raw+=e}appendErr(t){let e=typeof t=="number"?this.errDecoder.decode(new Uint8Array([t]),{stream:!0}):String(t);this.err+=e,this.raw+=e}async loadPackages(t,e){let n=(t||[]).filter(d=>!this.loaded.has(d));if(!n.length)return[];let o=await this.resolver.fetchPackages(n,e),a=Object.keys(o);if(!a.length)return[];let l=this.Module.FS;l.mkdirTree(I+"/packages");for(let d of a)l.writeFile(I+"/packages/"+d,o[d]);this.writeModuleMaps(a);for(let d of a)this.loaded.add(d);return this.log("loaded "+a.length+" package(s): "+a.join(", ")),a}writeModuleMaps(t){let e=this.Module.FS;for(let n of this.resolver.modulesOf(t)){let o=this.resolver.packageOfModule(n);if(!o)continue;let a=I+"/"+n.replace(/\./g,"/")+".txt";e.mkdirTree(a.slice(0,a.lastIndexOf("/"))),e.writeFile(a,o)}}async run(t){let e=t||{};if(this.disposed)throw new Error("this instance has been disposed");if(this.poisoned)throw new Error(this.poisoned);if(!this.ready)throw new Error("the REPL is not ready");if(this.running)throw new Error("a run is already in progress");let n=e.timeout||this.options.timeout,o=Date.now()+n,a=U(e.code,e.stdin),l=this.resolver.analyzeImports(a);if(l.missing.length)return this.result({error:this.resolver.explainMissing(l.missing)});let d=await this.loadPackages(l.packages,l.urls),c=l.packages.filter(g=>!this.loaded.has(g));if(c.length)return this.result({error:"package file(s) missing from this build: "+c.join(", "),packages:d});let E={raw:this.raw.length,out:this.out.length,err:this.err.length},y=[],x=Date.now(),k=!1;this.running=!0;try{this.Module.FS.writeFile(_,a);for(let g of["import Main",":reload",":main"])y.push(g),await this.step(g,o)}catch(g){k=!!g.timeout,k||(this.fatal=String(g&&g.message||g))}finally{this.running=!1}let O=this.collect(E,y);return k&&(this.poisoned="the previous run timed out and left the REPL busy; create a new instance"),this.result({...O,error:O.error||(k?"timed out after "+n+"ms":null)||(this.fatal?this.fatal:null),exitCode:k?124:void 0,packages:d,durationMs:Date.now()-x})}collect(t,e){let n=N(R(this.out.slice(t.out),e)),o=N(R(this.err.slice(t.err),e)),a=[];for(let d of n.errors.concat(o.errors))a.includes(d)||a.push(d);let l=j(a);return{stdout:j(n.out),stderr:j(o.out),error:l?this.resolver.explainNotFound(l):null,output:R(this.raw.slice(t.raw),e).trim()}}result(t){let e=t.error||null,n=t.exitCode!=null?t.exitCode:e?1:this.exitCode==null?0:this.exitCode;return{stdout:t.stdout||"",stderr:t.stderr||"",error:e,output:t.output||"",exitCode:n,packages:t.packages||[],durationMs:t.durationMs==null?0:t.durationMs}}dispose(){this.disposed=!0,this.Module=null,this.resolver=null,this.loaded.clear()}};var dt={},at=(()=>{if(typeof document<"u"&&document.currentScript&&document.currentScript.src)return A(document.currentScript.src);try{return A(dt.url)}catch{}return typeof location<"u"&&location.href?A(location.href):""})();function A(s){return String(s).slice(0,String(s).lastIndexOf("/")+1)}var ct=s=>String(s).endsWith("/")?String(s):String(s)+"/";async function Z(s){let t=s||{},e=ct(t.baseUrl||at),n=new b({...t,wasmUrl:t.wasmUrl||e+"mhs/mhs-embed.js",packagesUrl:t.packagesUrl||e+"pkgs/"});return await n.boot(),n}var lt={createHaskell:Z,MicroHs:b};return J(ut);})();
|
|
34
|
+
//# sourceMappingURL=browser-haskell.iife.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.js", "../src/manifest.js", "../src/shim.js", "../src/repl.js"],
|
|
4
|
+
"sourcesContent": ["import { MicroHs } from './repl.js';\n\n/**\n * @live-codes/browser-haskell \u2014 run Haskell in the browser.\n *\n * import { createHaskell } from '@live-codes/browser-haskell';\n *\n * const haskell = await createHaskell(); // boots MicroHs (~1-2s)\n * const result = await haskell.run({ code: 'main = putStrLn \"hi\"', stdin: '' });\n * result.stdout; // \"hi\\n\"\n * result.error; // compile errors / exceptions, or null\n * result.exitCode; // 0, 1, or 124 on timeout\n *\n * Everything is client-side: a wasm build of MicroHs plus lazily fetched MicroHs\n * packages. Assets (the wasm bundle and the package set) are looked up next to this\n * module by default; point `baseUrl` at wherever you host them.\n */\n\n/**\n * Where this file lives, so a default asset URL can be derived. Captured at load time\n * because `document.currentScript` is only meaningful then (IIFE build); the ESM build\n * uses `import.meta.url`.\n */\nconst SELF_DIR = (() => {\n if (typeof document !== 'undefined' && document.currentScript && document.currentScript.src) {\n return dirOf(document.currentScript.src);\n }\n try {\n return dirOf(import.meta.url);\n } catch (err) {\n // Not a module (IIFE build without a script tag): fall back to the page URL.\n }\n if (typeof location !== 'undefined' && location.href) return dirOf(location.href);\n return '';\n})();\n\nfunction dirOf(url) {\n return String(url).slice(0, String(url).lastIndexOf('/') + 1);\n}\n\nconst withSlash = (url) => (String(url).endsWith('/') ? String(url) : String(url) + '/');\n\n/**\n * Create a MicroHs instance.\n *\n * @param {object} [options]\n * @param {string} [options.baseUrl] Where the assets live: `mhs/mhs-embed.js` (+ .wasm)\n * and `pkgs/index.json` (+ `pkgs/packages/*.pkg`). Defaults to this module's directory.\n * @param {string} [options.wasmUrl] Full URL of `mhs-embed.js` (overrides baseUrl).\n * @param {string} [options.packagesUrl] Directory containing `index.json` and\n * `packages/` (overrides baseUrl).\n * @param {Object<string,string>} [options.importmap] Extra packages by module name,\n * e.g. `{ 'My.Module': 'https://example.com/my-pkg.pkg' }`. The `.pkg` must be built by\n * the same MicroHs version, and any MicroHs dependencies it has must be mapped too.\n * @param {number} [options.timeout] Per-run timeout in ms (default 60000).\n * @param {(message: string) => void} [options.onLog] Diagnostic logging.\n * @returns {Promise<MicroHs>}\n */\nexport async function createHaskell(options) {\n const opts = options || {};\n const baseUrl = withSlash(opts.baseUrl || SELF_DIR);\n const repl = new MicroHs({\n ...opts,\n wasmUrl: opts.wasmUrl || baseUrl + 'mhs/mhs-embed.js',\n packagesUrl: opts.packagesUrl || baseUrl + 'pkgs/',\n });\n await repl.boot();\n return repl;\n}\n\nexport { MicroHs };\nexport default { createHaskell, MicroHs };\n", "/**\n * Which packages does a program need, and where do they come from?\n *\n * The wasm bundle embeds MicroHs's `base` (+ canvhs). Everything else ships as MicroHs\n * packages, described by a manifest that is fetched lazily and used to pull in only the\n * `.pkg` files a program actually imports:\n *\n * {\n * \"modules\": { \"Data.Map\": \"containers-0.8.pkg\", ... },\n * \"packages\": { \"containers-0.8.pkg\": [\"array-mhs-0.5.8.0.pkg\"], ... },\n * \"embedded\": [\"Data.List\", ...],\n * \"unavailable\": [{ \"prefix\": \"Data.Aeson\", \"reason\": \"not bundled here\" }]\n * }\n *\n * `embedded` and `unavailable` are what let an import we cannot satisfy come back with\n * \"not available, because X\" instead of a bare `Module not found`.\n *\n * Inside the compiler's virtual FS the layout is:\n * /pkgs/packages/<name>.pkg the serialized package\n * /pkgs/<Module/Path>.txt contains the package file name\n */\n\nconst withSlash = (url) => (url.endsWith('/') ? url : url + '/');\n\n/** Imported module names in a source file, in source order. Comments are ignored. */\nexport function importedModules(source) {\n const code = String(source)\n .replace(/\\{-[\\s\\S]*?-\\}/g, ' ')\n .split('\\n')\n .map((line) => line.replace(/--.*$/, ''))\n .join('\\n');\n const out = [];\n const re = /^[ \\t]*import[ \\t]+(?:safe[ \\t]+)?(?:qualified[ \\t]+)?(?:\"[^\"]*\"[ \\t]+)?([A-Z][A-Za-z0-9_.']*)/gm;\n let m;\n while ((m = re.exec(code)) !== null) {\n if (out.indexOf(m[1]) === -1) out.push(m[1]);\n }\n return out;\n}\n\n/** The package file name implied by a custom package URL. */\nfunction customName(url) {\n const clean = String(url).split('?')[0].split('#')[0];\n const last = clean.slice(clean.lastIndexOf('/') + 1);\n return last || 'custom.pkg';\n}\n\n/**\n * @param {object} options\n * @param {string} options.packagesUrl directory holding index.json and packages/\n * @param {Object<string,string>} [options.importmap] module -> .pkg URL, for packages\n * that are not in the manifest. They must be built by the same MicroHs version, and\n * any MicroHs dependencies they have must be mapped here too (the manifest cannot\n * know about them).\n * @param {(msg: string) => void} [options.log]\n * @param {typeof fetch} [options.fetch]\n */\nexport function createPackageResolver(options) {\n const opts = options || {};\n const base = withSlash(opts.packagesUrl);\n const importmap = opts.importmap || {};\n const log = opts.log || (() => {});\n const doFetch = opts.fetch || ((...args) => fetch(...args));\n\n /** module file name -> { name, url, modules } for importmap entries */\n const custom = new Map();\n for (const moduleName of Object.keys(importmap)) {\n const url = importmap[moduleName];\n if (typeof url !== 'string' || !url) continue;\n const name = customName(url);\n const entry = custom.get(name) || { name, url, modules: new Set() };\n entry.modules.add(moduleName);\n custom.set(name, entry);\n }\n\n let manifestPromise = null;\n let manifest = null;\n\n function loadManifest() {\n if (!manifestPromise) {\n const url = base + 'index.json';\n manifestPromise = doFetch(url, { cache: 'no-store' })\n .then((res) => (res.ok ? res.json() : null))\n .then((m) => {\n if (!m || Array.isArray(m)) {\n log('no package manifest at ' + url + '; only the embedded modules are available');\n return null;\n }\n manifest = m;\n return m;\n })\n .catch((err) => {\n log('failed to load ' + url + ': ' + (err && err.message));\n return null;\n });\n }\n return manifestPromise;\n }\n\n /**\n * @returns {{kind:'package'|'custom'|'embedded'|'unavailable'|'unknown', pkg?:string, url?:string, reason?:string}}\n */\n function classifyModule(name) {\n if (custom.has(name)) {\n const entry = custom.get(name);\n return { kind: 'package', pkg: entry.name, url: entry.url };\n }\n if (manifest && manifest.modules && manifest.modules[name]) {\n return { kind: 'package', pkg: manifest.modules[name] };\n }\n if (!manifest) {\n // Without a manifest only the embedded modules are known for sure.\n return { kind: 'unknown' };\n }\n if (manifest.embedded && manifest.embedded.indexOf(name) !== -1) return { kind: 'embedded' };\n for (const rule of manifest.unavailable || []) {\n if (name === rule.prefix || name.indexOf(rule.prefix + '.') === 0) {\n return { kind: 'unavailable', reason: rule.reason };\n }\n }\n return { kind: 'unknown' };\n }\n\n /**\n * What a program needs before it can compile.\n * @returns {{packages:string[], missing:{module:string, reason:string}[], urls:Object<string,string>}}\n */\n function analyzeImports(source) {\n const needed = new Set();\n const urls = {};\n const missing = [];\n\n for (const mod of importedModules(source)) {\n if (importmap[mod]) {\n const name = customName(importmap[mod]);\n needed.add(name);\n urls[name] = importmap[mod];\n continue;\n }\n const found = classifyModule(mod);\n if (found.kind === 'package') needed.add(found.pkg);\n else if (found.kind === 'unavailable') missing.push({ module: mod, reason: found.reason });\n else if (found.kind === 'unknown') {\n missing.push({ module: mod, reason: 'not bundled with this playground' });\n }\n }\n\n // A package brings its MicroHs dependencies with it.\n const closure = new Set();\n const queue = Array.from(needed);\n while (queue.length) {\n const pkg = queue.shift();\n if (closure.has(pkg)) continue;\n closure.add(pkg);\n const deps = (manifest && manifest.packages && manifest.packages[pkg]) || [];\n for (const dep of deps) {\n if (!closure.has(dep) && queue.indexOf(dep) === -1) queue.push(dep);\n }\n }\n\n return { packages: Array.from(closure).sort(), missing, urls };\n }\n\n /** The package file that provides a module (from the manifest or the importmap). */\n function packageOfModule(mod) {\n if (custom.has(mod)) return custom.get(mod).name;\n if (manifest && manifest.modules) return manifest.modules[mod] || null;\n return null;\n }\n\n /** Modules provided by the given package files (used to write the lookup maps). */\n function modulesOf(pkgFiles) {\n const out = [];\n const wanted = new Set(pkgFiles);\n if (manifest && manifest.modules) {\n for (const mod of Object.keys(manifest.modules)) {\n if (wanted.has(manifest.modules[mod])) out.push(mod);\n }\n }\n for (const entry of custom.values()) {\n if (wanted.has(entry.name)) out.push(...entry.modules);\n }\n return out;\n }\n\n /** Fetch package files. @returns {Promise<Object<string, Uint8Array>>} */\n function fetchPackages(names, urls) {\n const out = {};\n return Promise.all(\n names.map((name) => {\n const url = (urls && urls[name]) || base + 'packages/' + name;\n return doFetch(url, { cache: 'force-cache' })\n .then((res) => {\n if (!res.ok) throw new Error('HTTP ' + res.status + ' for ' + url);\n return res.arrayBuffer();\n })\n .then((buf) => {\n out[name] = new Uint8Array(buf);\n })\n .catch((err) => {\n log('could not fetch ' + url + ': ' + (err && err.message));\n });\n }),\n ).then(() => out);\n }\n\n /** A human explanation for imports we cannot satisfy, or null if there are none. */\n function explainMissing(missing) {\n if (!missing || !missing.length) return null;\n const lines = ['Not available in this playground:'];\n for (const item of missing) lines.push(' ' + item.module + ' \u2014 ' + item.reason);\n if (manifest && manifest.modules && manifest.packages) {\n const count = Object.keys(manifest.modules).length;\n const base = (manifest.embedded || []).length;\n const pkgs = Object.keys(manifest.packages).length;\n const examples = ['Data.Map', 'Control.Monad.State', 'System.Random', 'Data.Time', 'Test.Hspec']\n .filter((mod) => manifest.modules[mod] !== undefined);\n lines.push('');\n lines.push(\n 'This playground provides base (' + base + ' modules) plus ' + pkgs + ' packages (' + count +\n ' modules), including ' + (examples.length ? examples.join(', ') + ', \u2026' : 'see the manifest') + '.',\n );\n }\n return lines.join('\\n');\n }\n\n /**\n * The backstop for a `Module not found: X` the pre-check could not see \u2014 the reason\n * is appended so the message does not look like a broken package.\n */\n function explainNotFound(text) {\n if (!text) return text;\n const seen = [];\n const re = /Module not found:\\s*([A-Z][A-Za-z0-9_.']*)/g;\n let m;\n while ((m = re.exec(text)) !== null) {\n const name = m[1];\n if (seen.some((s) => s.module === name)) continue;\n const found = classifyModule(name);\n if (found.kind === 'unavailable') seen.push({ module: name, reason: found.reason });\n else if (found.kind === 'unknown') seen.push({ module: name, reason: 'not bundled with this playground' });\n else if (found.kind === 'package') {\n seen.push({ module: name, reason: 'its package (' + found.pkg + ') is not loaded' });\n }\n }\n const why = explainMissing(seen);\n return why ? text + '\\n\\n' + why : text;\n }\n\n return {\n loadManifest,\n classifyModule,\n analyzeImports,\n packageOfModule,\n modulesOf,\n fetchPackages,\n explainMissing,\n explainNotFound,\n get manifest() {\n return manifest;\n },\n };\n}\n", "/**\n * stdin for Haskell programs.\n *\n * The MicroHs web build has no usable fd 0: `getLine` throws\n * `Handle(stdin): end of file`, and the REPL's own input queue (`_set_input_char`)\n * belongs to the REPL \u2014 characters sent while a program runs are read by the REPL\n * afterwards, not by the program. So stdin has to arrive as *source*:\n *\n * 1. `lcInput` / `lcInputLines` / `lcInputWords` \u2014 pure bindings, no imports needed.\n * 2. Prelude's `getLine`, `readLn`, `getContents` and `interact` are shadowed by\n * equivalents that consume the same input, so ordinary programs work unchanged.\n * A top-level definition in Main shadows the imported one, which is what makes\n * this possible without touching the compiler.\n *\n * The shadowing needs `Data.IORef` and `System.IO.Unsafe`, so the imports are hoisted\n * to the top of the module (they cannot appear after declarations).\n */\n\nconst IMPORTS = ['import Data.IORef', 'import System.IO.Unsafe (unsafePerformIO)'];\n\n/** Names we shadow; skipped if the program defines them itself. */\nconst SHADOWED = ['getLine', 'readLn', 'getContents', 'interact'];\n\nconst ESCAPES = { '\\\\': '\\\\\\\\', '\"': '\\\\\"', '\\n': '\\\\n', '\\r': '\\\\r', '\\t': '\\\\t' };\n\n/** Escape text as a Haskell string literal. */\nexport function toHaskellString(text) {\n let out = '';\n for (const ch of String(text)) {\n if (ESCAPES[ch]) {\n out += ESCAPES[ch];\n continue;\n }\n const code = ch.codePointAt(0);\n if (code < 0x20 || code === 0x7f) {\n // Numeric escape; `\\&` keeps a following digit from joining the number.\n out += '\\\\' + code + '\\\\&';\n continue;\n }\n out += ch;\n }\n return out;\n}\n\n/** Does the program define this name at the top level? */\nfunction definesName(source, name) {\n return new RegExp('^' + name + '\\\\s*(::|=)', 'm').test(source);\n}\n\n/**\n * Where new import lines can legally go: after the module header if there is one,\n * otherwise after any leading pragmas and comments (which must come first).\n */\nfunction importInsertAt(lines) {\n const header = lines.findIndex((l) => /^module\\s+[A-Z][A-Za-z0-9_.']*\\s*(\\(.*)?\\bwhere\\b/.test(l));\n if (header !== -1) return header + 1;\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i].trim();\n const isLeading =\n line === '' ||\n line.startsWith('--') ||\n line.startsWith('{-#') ||\n line.startsWith('{-') ||\n line.startsWith('#');\n if (!isLeading) break;\n if (line.startsWith('{-') && !line.includes('-}')) {\n // Block comment: skip to its end.\n while (i < lines.length && !lines[i].includes('-}')) i++;\n i++;\n continue;\n }\n i++;\n }\n return i;\n}\n\nfunction shimSource(input, source) {\n const parts = [];\n const add = (name, text) => {\n if (!definesName(source, name)) parts.push(text);\n };\n\n add(\n 'lcInput',\n [\n '-- stdin, injected by @live-codes/browser-haskell (this build has no fd 0)',\n 'lcInput :: String',\n 'lcInput = \"' + toHaskellString(input) + '\"',\n ].join('\\n'),\n );\n add('lcInputLines', 'lcInputLines :: [String]\\nlcInputLines = lines lcInput');\n add('lcInputWords', 'lcInputWords :: [String]\\nlcInputWords = words lcInput');\n\n if (definesName(source, 'lcInput')) {\n // The program provides its own input; nothing to shadow it with.\n return parts.join('\\n\\n');\n }\n\n parts.push(\n [\n '{-# NOINLINE lcStdinRef #-}',\n 'lcStdinRef :: IORef String',\n 'lcStdinRef = unsafePerformIO (newIORef lcInput)',\n '',\n 'lcReadAll :: IO String',\n 'lcReadAll = do',\n ' s <- readIORef lcStdinRef',\n ' writeIORef lcStdinRef \"\"',\n ' return s',\n ].join('\\n'),\n );\n\n add(\n 'getLine',\n [\n 'getLine :: IO String',\n 'getLine = do',\n ' s <- readIORef lcStdinRef',\n ' case s of',\n ' [] -> return \"\"',\n ' _ -> do',\n ' let (l, rest) = break (== \\'\\\\n\\') s',\n ' writeIORef lcStdinRef (drop 1 rest)',\n ' return l',\n ].join('\\n'),\n );\n add('readLn', 'readLn :: Read a => IO a\\nreadLn = getLine >>= return . read');\n add('getContents', 'getContents :: IO String\\ngetContents = lcReadAll');\n add('interact', 'interact :: (String -> String) -> IO ()\\ninteract f = getContents >>= putStr . f');\n\n return parts.join('\\n\\n');\n}\n\n/**\n * Append stdin support to a program. Imports are hoisted; definitions are appended\n * (order does not matter in Haskell). A program with no stdin is left untouched.\n * @param {string} source\n * @param {string} input\n * @returns {string}\n */\nexport function injectStdin(source, input) {\n const code = String(source == null ? '' : source);\n const text = String(input == null ? '' : input);\n if (!text) return code;\n\n // Drop a trailing newline the editor may have added, so line counting stays sane.\n const lines = code.replace(/\\s*$/, '').split('\\n');\n const at = importInsertAt(lines);\n const hoisted = IMPORTS.filter((line) => !new RegExp('^' + line.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '\\\\s*$', 'm').test(code));\n const withImports = hoisted.length\n ? lines.slice(0, at).concat(['']).concat(hoisted).concat('').concat(lines.slice(at))\n : lines;\n\n return withImports.join('\\n') + '\\n\\n' + shimSource(text, code) + '\\n';\n}\n", "import { createPackageResolver } from './manifest.js';\nimport { injectStdin } from './shim.js';\n\n/**\n * MicroHs REPL driver.\n *\n * The published `mhs-embed` bundle cannot compile and run in batch mode, so the only\n * execution path is the interactive REPL: write Main.hs, `import Main` (which compiles,\n * so diagnostics surface here), `:reload` (the REPL caches modules, so a changed file is\n * otherwise ignored), then `:main` (which runs it). Output is read between sentinel\n * prompts.\n *\n * Program stdin does not exist at the OS level in this build, so it is injected into the\n * source instead \u2014 see shim.js.\n */\n\nconst HOME = '/home/web_user';\nconst MAIN_FILE = 'Main.hs';\nconst PROMPT = '<<<LC_PROMPT>>>';\nconst PKG_DIR = '/pkgs';\nconst BOOT_TIMEOUT = 30000;\nconst DEFAULT_TIMEOUT = 60000;\n\nconst delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Load the Emscripten glue, wherever this is running. */\nasync function loadScript(url) {\n if (typeof document !== 'undefined' && document.createElement) {\n await new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('failed to load ' + url));\n (document.head || document.body || document.documentElement).appendChild(script);\n });\n return;\n }\n if (typeof importScripts === 'function') {\n importScripts(url);\n return;\n }\n // Module worker (or Node, if someone points wasmUrl at a file URL).\n await import(/* webpackIgnore: true */ /* @vite-ignore */ url);\n}\n\n/** Backspaces delete the previous character, as a terminal would. */\nfunction applyBackspaces(text) {\n let out = '';\n for (const ch of text) {\n if (ch === '\\b') out = out.slice(0, -1);\n else out += ch;\n }\n return out;\n}\n\n/** Progress lines (\"adds [ ]\\radds [x]\") keep only their final state. */\nfunction applyCarriageReturns(text) {\n return text\n .split('\\n')\n .map((line) => {\n const i = line.lastIndexOf('\\r');\n return i >= 0 ? line.slice(i + 1) : line;\n })\n .join('\\n');\n}\n\n/** Drop prompts, ANSI control sequences, echoed input and REPL banner lines. */\nfunction clean(text, sentLines) {\n const noPrompts = text.split(PROMPT).join('');\n const noAnsi = applyCarriageReturns(\n applyBackspaces(\n noPrompts\n // eslint-disable-next-line no-control-regex\n .replace(/\\u001b\\[[0-9;?]*[A-Za-z]|\\u001b[@-Z\\\\-_]|\\u001b\\([A-Za-z0-9]/g, '')\n .replace(/\\u0007/g, ''),\n ),\n );\n const banner = [\n /^Welcome to interactive MicroHs/,\n /^Integer implemented with imath/,\n /^Loading embedded package /,\n /^Loading package /,\n /^loaded /,\n /^Type ':quit' to quit/,\n ];\n return noAnsi\n .split('\\n')\n .filter((line) => {\n const t = line.trim();\n if (banner.some((re) => re.test(t))) return false;\n if ((sentLines || []).some((s) => t === s)) return false;\n return true;\n })\n .join('\\n');\n}\n\n/** Is this line an error/diagnostic rather than program output? */\nfunction isErrorLine(line) {\n const t = line.trim();\n return (\n /^(\\*\\*\\* )?(Exception|error:|Error:)/.test(t) ||\n /^Unrecognized command/.test(t) ||\n // The compiler explains failed constraint solving on its own lines, on stdout.\n /^fully qualified:/.test(t) ||\n /: line \\d+, col \\d+:/.test(t)\n );\n}\n\nfunction classify(text) {\n const out = [];\n const errors = [];\n for (const line of text.split('\\n')) (isErrorLine(line) ? errors : out).push(line);\n return { out, errors };\n}\n\nconst joinLines = (lines) => lines.join('\\n').trim();\n\n/**\n * One MicroHs instance. Booting is expensive (~1-2s: 1.9 MB wasm), so create one and\n * reuse it for every run in the page/worker.\n */\nexport class MicroHs {\n constructor(options) {\n const opts = options || {};\n this.options = {\n wasmUrl: opts.wasmUrl,\n packagesUrl: opts.packagesUrl,\n importmap: opts.importmap || {},\n timeout: opts.timeout || DEFAULT_TIMEOUT,\n charDelay: opts.charDelay == null ? 0 : opts.charDelay,\n onLog: typeof opts.onLog === 'function' ? opts.onLog : null,\n fetch: opts.fetch,\n };\n\n this.raw = '';\n this.out = '';\n this.err = '';\n this.outDecoder = new TextDecoder('utf-8', { fatal: false });\n this.errDecoder = new TextDecoder('utf-8', { fatal: false });\n this.loaded = new Set();\n this.exitCode = null;\n this.fatal = null;\n this.ready = false;\n this.running = false;\n this.disposed = false;\n /** Set once a run has timed out: the REPL is mid-execution and cannot be reused. */\n this.poisoned = null;\n this.Module = null;\n this.resolver = null;\n }\n\n log(message) {\n if (this.options.onLog) this.options.onLog(message);\n }\n\n promptCount() {\n let n = 0;\n let i = 0;\n while ((i = this.raw.indexOf(PROMPT, i)) !== -1) {\n n++;\n i += PROMPT.length;\n }\n return n;\n }\n\n async waitFor(predicate, label, deadline) {\n for (;;) {\n if (predicate()) return;\n if (this.fatal) throw new Error(this.fatal);\n if (Date.now() > deadline) {\n const err = new Error('timed out waiting for ' + label);\n err.timeout = true;\n throw err;\n }\n await delay(1);\n }\n }\n\n /** Type a line into the REPL one character at a time, yielding between them. */\n async typeLine(text, deadline) {\n const bytes = new TextEncoder().encode(text + '\\n');\n for (const byte of bytes) {\n if (Date.now() > deadline) {\n const err = new Error('timed out while sending input');\n err.timeout = true;\n throw err;\n }\n this.Module._set_input_char(byte);\n await delay(this.options.charDelay);\n }\n }\n\n /** Type a REPL command and wait for the output it produces. */\n async step(line, deadline) {\n const baseline = this.promptCount();\n await this.typeLine(line, deadline);\n await this.waitFor(() => this.promptCount() > baseline, JSON.stringify(line), deadline);\n }\n\n /** Boot the compiler. Resolves once the REPL shows its first prompt. */\n async boot() {\n this.resolver = createPackageResolver({\n packagesUrl: this.options.packagesUrl,\n importmap: this.options.importmap,\n log: (m) => this.log(m),\n fetch: this.options.fetch,\n });\n await this.resolver.loadManifest();\n\n const wasmUrl = String(this.options.wasmUrl);\n const wasmDir = wasmUrl.slice(0, wasmUrl.lastIndexOf('/') + 1);\n\n const Module = {\n // `-aPATH` appends to the package search path. Declaring it up front (even while\n // /pkgs is empty) is what lets packages be written into the virtual FS later and\n // imported without restarting the REPL.\n arguments: ['-a' + PKG_DIR],\n locateFile: (file) => wasmDir + file,\n preRun: [\n function () {\n const FS = Module.FS;\n FS.mkdirTree(HOME);\n FS.chdir(HOME);\n FS.writeFile('.mhsi_rc', ':set prompt=' + PROMPT + '\\n');\n FS.writeFile(MAIN_FILE, '');\n },\n ],\n // Program stdin is unusable here; it is injected as source instead (shim.js).\n stdin: () => null,\n stdout: (code) => code !== null && this.appendOut(code),\n stderr: (code) => code !== null && this.appendErr(code),\n print: (text) => this.appendOut(text + '\\n'),\n printErr: (text) => this.appendErr(text + '\\n'),\n onExit: (code) => {\n this.exitCode = code;\n this.log('compiler exited with ' + code);\n },\n onAbort: (what) => {\n this.fatal = String(what);\n },\n };\n\n this.Module = Module;\n // The glue is a classic script that reads a global `Module`.\n globalThis.Module = Module;\n\n this.log('loading ' + wasmUrl);\n await loadScript(wasmUrl);\n await this.waitFor(() => this.promptCount() > 0, 'the REPL to start', Date.now() + BOOT_TIMEOUT);\n this.ready = true;\n this.log('ready');\n return this;\n }\n\n appendOut(text) {\n const s = typeof text === 'number' ? this.outDecoder.decode(new Uint8Array([text]), { stream: true }) : String(text);\n this.out += s;\n this.raw += s;\n }\n\n appendErr(text) {\n const s = typeof text === 'number' ? this.errDecoder.decode(new Uint8Array([text]), { stream: true }) : String(text);\n this.err += s;\n this.raw += s;\n }\n\n /**\n * Write package files into the live virtual FS, plus the module lookup maps that point\n * at them. No restart, no page reload: the search path was declared at boot.\n * @returns {Promise<string[]>} package files actually written\n */\n async loadPackages(names, urls) {\n const want = (names || []).filter((name) => !this.loaded.has(name));\n if (!want.length) return [];\n\n const bytes = await this.resolver.fetchPackages(want, urls);\n const got = Object.keys(bytes);\n if (!got.length) return [];\n\n const FS = this.Module.FS;\n FS.mkdirTree(PKG_DIR + '/packages');\n for (const name of got) FS.writeFile(PKG_DIR + '/packages/' + name, bytes[name]);\n this.writeModuleMaps(got);\n for (const name of got) this.loaded.add(name);\n this.log('loaded ' + got.length + ' package(s): ' + got.join(', '));\n return got;\n }\n\n /** `<Module/Path>.txt` containing the package file name, for each provided module. */\n writeModuleMaps(pkgFiles) {\n const FS = this.Module.FS;\n for (const mod of this.resolver.modulesOf(pkgFiles)) {\n const pkg = this.resolver.packageOfModule(mod);\n if (!pkg) continue;\n const path = PKG_DIR + '/' + mod.replace(/\\./g, '/') + '.txt';\n FS.mkdirTree(path.slice(0, path.lastIndexOf('/')));\n FS.writeFile(path, pkg);\n }\n }\n\n /**\n * Compile and run a program.\n * @param {{code: string, stdin?: string, timeout?: number}} options\n * @returns {Promise<{stdout:string, stderr:string, error:string|null, output:string,\n * exitCode:number, packages:string[], durationMs:number}>}\n */\n async run(options) {\n const opts = options || {};\n if (this.disposed) throw new Error('this instance has been disposed');\n if (this.poisoned) throw new Error(this.poisoned);\n if (!this.ready) throw new Error('the REPL is not ready');\n if (this.running) throw new Error('a run is already in progress');\n\n const timeout = opts.timeout || this.options.timeout;\n const deadline = Date.now() + timeout;\n const source = injectStdin(opts.code, opts.stdin);\n\n // Imports that can never be satisfied are reported before anything is compiled.\n const analysis = this.resolver.analyzeImports(source);\n if (analysis.missing.length) {\n return this.result({ error: this.resolver.explainMissing(analysis.missing) });\n }\n\n const loaded = await this.loadPackages(analysis.packages, analysis.urls);\n const absent = analysis.packages.filter((name) => !this.loaded.has(name));\n if (absent.length) {\n return this.result({ error: 'package file(s) missing from this build: ' + absent.join(', '), packages: loaded });\n }\n\n const mark = { raw: this.raw.length, out: this.out.length, err: this.err.length };\n const sent = [];\n const started = Date.now();\n let timedOut = false;\n\n this.running = true;\n try {\n this.Module.FS.writeFile(MAIN_FILE, source);\n // `import Main` compiles, so diagnostics appear here; :reload is what actually\n // picks up a changed file; :main runs it.\n for (const line of ['import Main', ':reload', ':main']) {\n sent.push(line);\n await this.step(line, deadline);\n }\n } catch (err) {\n timedOut = !!err.timeout;\n if (!timedOut) this.fatal = String((err && err.message) || err);\n } finally {\n this.running = false;\n }\n\n const collected = this.collect(mark, sent);\n if (timedOut) {\n this.poisoned = 'the previous run timed out and left the REPL busy; create a new instance';\n }\n\n return this.result({\n ...collected,\n error:\n collected.error ||\n (timedOut ? 'timed out after ' + timeout + 'ms' : null) ||\n (this.fatal ? this.fatal : null),\n exitCode: timedOut ? 124 : undefined,\n packages: loaded,\n durationMs: Date.now() - started,\n });\n }\n\n /** Split the output captured since `mark` into stdout, stderr and diagnostics. */\n collect(mark, sent) {\n const outC = classify(clean(this.out.slice(mark.out), sent));\n const errC = classify(clean(this.err.slice(mark.err), sent));\n const errors = [];\n for (const line of outC.errors.concat(errC.errors)) {\n if (!errors.includes(line)) errors.push(line);\n }\n const error = joinLines(errors);\n return {\n stdout: joinLines(outC.out),\n stderr: joinLines(errC.out),\n error: error ? this.resolver.explainNotFound(error) : null,\n output: clean(this.raw.slice(mark.raw), sent).trim(),\n };\n }\n\n result(extra) {\n const error = extra.error || null;\n const exitCode =\n extra.exitCode != null ? extra.exitCode : error ? 1 : this.exitCode == null ? 0 : this.exitCode;\n return {\n stdout: extra.stdout || '',\n stderr: extra.stderr || '',\n error,\n output: extra.output || '',\n exitCode,\n packages: extra.packages || [],\n durationMs: extra.durationMs == null ? 0 : extra.durationMs,\n };\n }\n\n /**\n * Release this instance. Browsers cannot unload a wasm module, so this drops our\n * references rather than freeing memory; one instance per page/worker is the model.\n */\n dispose() {\n this.disposed = true;\n this.Module = null;\n this.resolver = null;\n this.loaded.clear();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;qbAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,aAAAE,EAAA,kBAAAC,EAAA,YAAAC,KCsBA,IAAMC,EAAaC,GAASA,EAAI,SAAS,GAAG,EAAIA,EAAMA,EAAM,IAGrD,SAASC,EAAgBC,EAAQ,CACtC,IAAMC,EAAO,OAAOD,CAAM,EACvB,QAAQ,kBAAmB,GAAG,EAC9B,MAAM;AAAA,CAAI,EACV,IAAKE,GAASA,EAAK,QAAQ,QAAS,EAAE,CAAC,EACvC,KAAK;AAAA,CAAI,EACNC,EAAM,CAAC,EACPC,EAAK,mGACPC,EACJ,MAAQA,EAAID,EAAG,KAAKH,CAAI,KAAO,MACzBE,EAAI,QAAQE,EAAE,CAAC,CAAC,IAAM,IAAIF,EAAI,KAAKE,EAAE,CAAC,CAAC,EAE7C,OAAOF,CACT,CAGA,SAASG,EAAWR,EAAK,CACvB,IAAMS,EAAQ,OAAOT,CAAG,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAEpD,OADaS,EAAM,MAAMA,EAAM,YAAY,GAAG,EAAI,CAAC,GACpC,YACjB,CAYO,SAASC,EAAsBC,EAAS,CAC7C,IAAMC,EAAOD,GAAW,CAAC,EACnBE,EAAOd,EAAUa,EAAK,WAAW,EACjCE,EAAYF,EAAK,WAAa,CAAC,EAC/BG,EAAMH,EAAK,MAAQ,IAAM,CAAC,GAC1BI,EAAUJ,EAAK,QAAU,IAAIK,IAAS,MAAM,GAAGA,CAAI,GAGnDC,EAAS,IAAI,IACnB,QAAWC,KAAc,OAAO,KAAKL,CAAS,EAAG,CAC/C,IAAMd,EAAMc,EAAUK,CAAU,EAChC,GAAI,OAAOnB,GAAQ,UAAY,CAACA,EAAK,SACrC,IAAMoB,EAAOZ,EAAWR,CAAG,EACrBqB,EAAQH,EAAO,IAAIE,CAAI,GAAK,CAAE,KAAAA,EAAM,IAAApB,EAAK,QAAS,IAAI,GAAM,EAClEqB,EAAM,QAAQ,IAAIF,CAAU,EAC5BD,EAAO,IAAIE,EAAMC,CAAK,CACxB,CAEA,IAAIC,EAAkB,KAClBC,EAAW,KAEf,SAASC,GAAe,CACtB,GAAI,CAACF,EAAiB,CACpB,IAAMtB,EAAMa,EAAO,aACnBS,EAAkBN,EAAQhB,EAAK,CAAE,MAAO,UAAW,CAAC,EACjD,KAAMyB,GAASA,EAAI,GAAKA,EAAI,KAAK,EAAI,IAAK,EAC1C,KAAMlB,GACD,CAACA,GAAK,MAAM,QAAQA,CAAC,GACvBQ,EAAI,0BAA4Bf,EAAM,2CAA2C,EAC1E,OAETuB,EAAWhB,EACJA,EACR,EACA,MAAOmB,IACNX,EAAI,kBAAoBf,EAAM,MAAQ0B,GAAOA,EAAI,QAAQ,EAClD,KACR,CACL,CACA,OAAOJ,CACT,CAKA,SAASK,EAAeP,EAAM,CAC5B,GAAIF,EAAO,IAAIE,CAAI,EAAG,CACpB,IAAMC,EAAQH,EAAO,IAAIE,CAAI,EAC7B,MAAO,CAAE,KAAM,UAAW,IAAKC,EAAM,KAAM,IAAKA,EAAM,GAAI,CAC5D,CACA,GAAIE,GAAYA,EAAS,SAAWA,EAAS,QAAQH,CAAI,EACvD,MAAO,CAAE,KAAM,UAAW,IAAKG,EAAS,QAAQH,CAAI,CAAE,EAExD,GAAI,CAACG,EAEH,MAAO,CAAE,KAAM,SAAU,EAE3B,GAAIA,EAAS,UAAYA,EAAS,SAAS,QAAQH,CAAI,IAAM,GAAI,MAAO,CAAE,KAAM,UAAW,EAC3F,QAAWQ,KAAQL,EAAS,aAAe,CAAC,EAC1C,GAAIH,IAASQ,EAAK,QAAUR,EAAK,QAAQQ,EAAK,OAAS,GAAG,IAAM,EAC9D,MAAO,CAAE,KAAM,cAAe,OAAQA,EAAK,MAAO,EAGtD,MAAO,CAAE,KAAM,SAAU,CAC3B,CAMA,SAASC,EAAe3B,EAAQ,CAC9B,IAAM4B,EAAS,IAAI,IACbC,EAAO,CAAC,EACRC,EAAU,CAAC,EAEjB,QAAWC,KAAOhC,EAAgBC,CAAM,EAAG,CACzC,GAAIY,EAAUmB,CAAG,EAAG,CAClB,IAAMb,EAAOZ,EAAWM,EAAUmB,CAAG,CAAC,EACtCH,EAAO,IAAIV,CAAI,EACfW,EAAKX,CAAI,EAAIN,EAAUmB,CAAG,EAC1B,QACF,CACA,IAAMC,EAAQP,EAAeM,CAAG,EAC5BC,EAAM,OAAS,UAAWJ,EAAO,IAAII,EAAM,GAAG,EACzCA,EAAM,OAAS,cAAeF,EAAQ,KAAK,CAAE,OAAQC,EAAK,OAAQC,EAAM,MAAO,CAAC,EAChFA,EAAM,OAAS,WACtBF,EAAQ,KAAK,CAAE,OAAQC,EAAK,OAAQ,kCAAmC,CAAC,CAE5E,CAGA,IAAME,EAAU,IAAI,IACdC,EAAQ,MAAM,KAAKN,CAAM,EAC/B,KAAOM,EAAM,QAAQ,CACnB,IAAMC,EAAMD,EAAM,MAAM,EACxB,GAAID,EAAQ,IAAIE,CAAG,EAAG,SACtBF,EAAQ,IAAIE,CAAG,EACf,IAAMC,EAAQf,GAAYA,EAAS,UAAYA,EAAS,SAASc,CAAG,GAAM,CAAC,EAC3E,QAAWE,KAAOD,EACZ,CAACH,EAAQ,IAAII,CAAG,GAAKH,EAAM,QAAQG,CAAG,IAAM,IAAIH,EAAM,KAAKG,CAAG,CAEtE,CAEA,MAAO,CAAE,SAAU,MAAM,KAAKJ,CAAO,EAAE,KAAK,EAAG,QAAAH,EAAS,KAAAD,CAAK,CAC/D,CAGA,SAASS,EAAgBP,EAAK,CAC5B,OAAIf,EAAO,IAAIe,CAAG,EAAUf,EAAO,IAAIe,CAAG,EAAE,KACxCV,GAAYA,EAAS,SAAgBA,EAAS,QAAQU,CAAG,GAAK,IAEpE,CAGA,SAASQ,EAAUC,EAAU,CAC3B,IAAMrC,EAAM,CAAC,EACPsC,EAAS,IAAI,IAAID,CAAQ,EAC/B,GAAInB,GAAYA,EAAS,QACvB,QAAWU,KAAO,OAAO,KAAKV,EAAS,OAAO,EACxCoB,EAAO,IAAIpB,EAAS,QAAQU,CAAG,CAAC,GAAG5B,EAAI,KAAK4B,CAAG,EAGvD,QAAWZ,KAASH,EAAO,OAAO,EAC5ByB,EAAO,IAAItB,EAAM,IAAI,GAAGhB,EAAI,KAAK,GAAGgB,EAAM,OAAO,EAEvD,OAAOhB,CACT,CAGA,SAASuC,EAAcC,EAAOd,EAAM,CAClC,IAAM1B,EAAM,CAAC,EACb,OAAO,QAAQ,IACbwC,EAAM,IAAKzB,GAAS,CAClB,IAAMpB,EAAO+B,GAAQA,EAAKX,CAAI,GAAMP,EAAO,YAAcO,EACzD,OAAOJ,EAAQhB,EAAK,CAAE,MAAO,aAAc,CAAC,EACzC,KAAMyB,GAAQ,CACb,GAAI,CAACA,EAAI,GAAI,MAAM,IAAI,MAAM,QAAUA,EAAI,OAAS,QAAUzB,CAAG,EACjE,OAAOyB,EAAI,YAAY,CACzB,CAAC,EACA,KAAMqB,GAAQ,CACbzC,EAAIe,CAAI,EAAI,IAAI,WAAW0B,CAAG,CAChC,CAAC,EACA,MAAOpB,GAAQ,CACdX,EAAI,mBAAqBf,EAAM,MAAQ0B,GAAOA,EAAI,QAAQ,CAC5D,CAAC,CACL,CAAC,CACH,EAAE,KAAK,IAAMrB,CAAG,CAClB,CAGA,SAAS0C,EAAef,EAAS,CAC/B,GAAI,CAACA,GAAW,CAACA,EAAQ,OAAQ,OAAO,KACxC,IAAMgB,EAAQ,CAAC,mCAAmC,EAClD,QAAWC,KAAQjB,EAASgB,EAAM,KAAK,KAAOC,EAAK,OAAS,WAAQA,EAAK,MAAM,EAC/E,GAAI1B,GAAYA,EAAS,SAAWA,EAAS,SAAU,CACrD,IAAM2B,EAAQ,OAAO,KAAK3B,EAAS,OAAO,EAAE,OACtCV,GAAQU,EAAS,UAAY,CAAC,GAAG,OACjC4B,EAAO,OAAO,KAAK5B,EAAS,QAAQ,EAAE,OACtC6B,EAAW,CAAC,WAAY,sBAAuB,gBAAiB,YAAa,YAAY,EAC5F,OAAQnB,GAAQV,EAAS,QAAQU,CAAG,IAAM,MAAS,EACtDe,EAAM,KAAK,EAAE,EACbA,EAAM,KACJ,kCAAoCnC,EAAO,kBAAoBsC,EAAO,cAAgBD,EACpF,yBAA2BE,EAAS,OAASA,EAAS,KAAK,IAAI,EAAI,WAAQ,oBAAsB,GACrG,CACF,CACA,OAAOJ,EAAM,KAAK;AAAA,CAAI,CACxB,CAMA,SAASK,EAAgBC,EAAM,CAC7B,GAAI,CAACA,EAAM,OAAOA,EAClB,IAAMC,EAAO,CAAC,EACRjD,EAAK,8CACPC,EACJ,MAAQA,EAAID,EAAG,KAAKgD,CAAI,KAAO,MAAM,CACnC,IAAMlC,EAAOb,EAAE,CAAC,EAChB,GAAIgD,EAAK,KAAMC,GAAMA,EAAE,SAAWpC,CAAI,EAAG,SACzC,IAAMc,EAAQP,EAAeP,CAAI,EAC7Bc,EAAM,OAAS,cAAeqB,EAAK,KAAK,CAAE,OAAQnC,EAAM,OAAQc,EAAM,MAAO,CAAC,EACzEA,EAAM,OAAS,UAAWqB,EAAK,KAAK,CAAE,OAAQnC,EAAM,OAAQ,kCAAmC,CAAC,EAChGc,EAAM,OAAS,WACtBqB,EAAK,KAAK,CAAE,OAAQnC,EAAM,OAAQ,gBAAkBc,EAAM,IAAM,iBAAkB,CAAC,CAEvF,CACA,IAAMuB,EAAMV,EAAeQ,CAAI,EAC/B,OAAOE,EAAMH,EAAO;AAAA;AAAA,EAASG,EAAMH,CACrC,CAEA,MAAO,CACL,aAAA9B,EACA,eAAAG,EACA,eAAAE,EACA,gBAAAW,EACA,UAAAC,EACA,cAAAG,EACA,eAAAG,EACA,gBAAAM,EACA,IAAI,UAAW,CACb,OAAO9B,CACT,CACF,CACF,CCpPA,IAAMmC,EAAU,CAAC,oBAAqB,2CAA2C,EAKjF,IAAMC,EAAU,CAAE,KAAM,OAAQ,IAAK,MAAO,KAAM,MAAO,KAAM,MAAO,IAAM,KAAM,EAG3E,SAASC,EAAgBC,EAAM,CACpC,IAAIC,EAAM,GACV,QAAWC,KAAM,OAAOF,CAAI,EAAG,CAC7B,GAAIF,EAAQI,CAAE,EAAG,CACfD,GAAOH,EAAQI,CAAE,EACjB,QACF,CACA,IAAMC,EAAOD,EAAG,YAAY,CAAC,EAC7B,GAAIC,EAAO,IAAQA,IAAS,IAAM,CAEhCF,GAAO,KAAOE,EAAO,MACrB,QACF,CACAF,GAAOC,CACT,CACA,OAAOD,CACT,CAGA,SAASG,EAAYC,EAAQC,EAAM,CACjC,OAAO,IAAI,OAAO,IAAMA,EAAO,aAAc,GAAG,EAAE,KAAKD,CAAM,CAC/D,CAMA,SAASE,EAAeC,EAAO,CAC7B,IAAMC,EAASD,EAAM,UAAWE,GAAM,oDAAoD,KAAKA,CAAC,CAAC,EACjG,GAAID,IAAW,GAAI,OAAOA,EAAS,EAEnC,IAAIE,EAAI,EACR,KAAOA,EAAIH,EAAM,QAAQ,CACvB,IAAMI,EAAOJ,EAAMG,CAAC,EAAE,KAAK,EAO3B,GAAI,EALFC,IAAS,IACTA,EAAK,WAAW,IAAI,GACpBA,EAAK,WAAW,KAAK,GACrBA,EAAK,WAAW,IAAI,GACpBA,EAAK,WAAW,GAAG,GACL,MAChB,GAAIA,EAAK,WAAW,IAAI,GAAK,CAACA,EAAK,SAAS,IAAI,EAAG,CAEjD,KAAOD,EAAIH,EAAM,QAAU,CAACA,EAAMG,CAAC,EAAE,SAAS,IAAI,GAAGA,IACrDA,IACA,QACF,CACAA,GACF,CACA,OAAOA,CACT,CAEA,SAASE,GAAWC,EAAOT,EAAQ,CACjC,IAAMU,EAAQ,CAAC,EACTC,EAAM,CAACV,EAAMN,IAAS,CACrBI,EAAYC,EAAQC,CAAI,GAAGS,EAAM,KAAKf,CAAI,CACjD,EAaA,OAXAgB,EACE,UACA,CACE,6EACA,oBACA,cAAgBjB,EAAgBe,CAAK,EAAI,GAC3C,EAAE,KAAK;AAAA,CAAI,CACb,EACAE,EAAI,eAAgB;AAAA,6BAAwD,EAC5EA,EAAI,eAAgB;AAAA,6BAAwD,EAExEZ,EAAYC,EAAQ,SAAS,IAKjCU,EAAM,KACJ,CACE,8BACA,6BACA,kDACA,GACA,yBACA,iBACA,8BACA,6BACA,YACF,EAAE,KAAK;AAAA,CAAI,CACb,EAEAC,EACE,UACA,CACE,uBACA,eACA,8BACA,cACA,sBACA,eACA,2CACA,4CACA,gBACF,EAAE,KAAK;AAAA,CAAI,CACb,EACAA,EAAI,SAAU;AAAA,mCAA8D,EAC5EA,EAAI,cAAe;AAAA,wBAAmD,EACtEA,EAAI,WAAY;AAAA,wCAAkF,GAE3FD,EAAM,KAAK;AAAA;AAAA,CAAM,CAC1B,CASO,SAASE,EAAYZ,EAAQS,EAAO,CACzC,IAAMX,EAAO,OAAOE,GAAiB,EAAW,EAC1CL,EAAO,OAAOc,GAAgB,EAAU,EAC9C,GAAI,CAACd,EAAM,OAAOG,EAGlB,IAAMK,EAAQL,EAAK,QAAQ,OAAQ,EAAE,EAAE,MAAM;AAAA,CAAI,EAC3Ce,EAAKX,EAAeC,CAAK,EACzBW,EAAUC,EAAQ,OAAQR,GAAS,CAAC,IAAI,OAAO,IAAMA,EAAK,QAAQ,sBAAuB,MAAM,EAAI,QAAS,GAAG,EAAE,KAAKT,CAAI,CAAC,EAKjI,OAJoBgB,EAAQ,OACxBX,EAAM,MAAM,EAAGU,CAAE,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,OAAOC,CAAO,EAAE,OAAO,EAAE,EAAE,OAAOX,EAAM,MAAMU,CAAE,CAAC,EACjFV,GAEe,KAAK;AAAA,CAAI,EAAI;AAAA;AAAA,EAASK,GAAWb,EAAMG,CAAI,EAAI;AAAA,CACpE,CC5IA,IAAMkB,EAAO,iBACPC,EAAY,UACZC,EAAS,kBACTC,EAAU,QACVC,GAAe,IACfC,GAAkB,IAElBC,EAASC,GAAO,IAAI,QAASC,GAAY,WAAWA,EAASD,CAAE,CAAC,EAGtE,eAAeE,GAAWC,EAAK,CAC7B,GAAI,OAAO,SAAa,KAAe,SAAS,cAAe,CAC7D,MAAM,IAAI,QAAQ,CAACF,EAASG,IAAW,CACrC,IAAMC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,IAAMF,EACbE,EAAO,OAAS,IAAMJ,EAAQ,EAC9BI,EAAO,QAAU,IAAMD,EAAO,IAAI,MAAM,kBAAoBD,CAAG,CAAC,GAC/D,SAAS,MAAQ,SAAS,MAAQ,SAAS,iBAAiB,YAAYE,CAAM,CACjF,CAAC,EACD,MACF,CACA,GAAI,OAAO,eAAkB,WAAY,CACvC,cAAcF,CAAG,EACjB,MACF,CAEA,MAAM,OAAoDA,EAC5D,CAGA,SAASG,GAAgBC,EAAM,CAC7B,IAAIC,EAAM,GACV,QAAWC,KAAMF,EACXE,IAAO,KAAMD,EAAMA,EAAI,MAAM,EAAG,EAAE,EACjCA,GAAOC,EAEd,OAAOD,CACT,CAGA,SAASE,GAAqBH,EAAM,CAClC,OAAOA,EACJ,MAAM;AAAA,CAAI,EACV,IAAKI,GAAS,CACb,IAAMC,EAAID,EAAK,YAAY,IAAI,EAC/B,OAAOC,GAAK,EAAID,EAAK,MAAMC,EAAI,CAAC,EAAID,CACtC,CAAC,EACA,KAAK;AAAA,CAAI,CACd,CAGA,SAASE,EAAMN,EAAMO,EAAW,CAC9B,IAAMC,EAAYR,EAAK,MAAMZ,CAAM,EAAE,KAAK,EAAE,EACtCqB,EAASN,GACbJ,GACES,EAEG,QAAQ,gEAAiE,EAAE,EAC3E,QAAQ,UAAW,EAAE,CAC1B,CACF,EACME,EAAS,CACb,kCACA,kCACA,6BACA,oBACA,WACA,uBACF,EACA,OAAOD,EACJ,MAAM;AAAA,CAAI,EACV,OAAQL,GAAS,CAChB,IAAMO,EAAIP,EAAK,KAAK,EAEpB,MADI,EAAAM,EAAO,KAAME,GAAOA,EAAG,KAAKD,CAAC,CAAC,IAC7BJ,GAAa,CAAC,GAAG,KAAMM,GAAMF,IAAME,CAAC,EAE3C,CAAC,EACA,KAAK;AAAA,CAAI,CACd,CAGA,SAASC,GAAYV,EAAM,CACzB,IAAM,EAAIA,EAAK,KAAK,EACpB,MACE,uCAAuC,KAAK,CAAC,GAC7C,wBAAwB,KAAK,CAAC,GAE9B,oBAAoB,KAAK,CAAC,GAC1B,uBAAuB,KAAK,CAAC,CAEjC,CAEA,SAASW,EAASf,EAAM,CACtB,IAAMC,EAAM,CAAC,EACPe,EAAS,CAAC,EAChB,QAAWZ,KAAQJ,EAAK,MAAM;AAAA,CAAI,GAAIc,GAAYV,CAAI,EAAIY,EAASf,GAAK,KAAKG,CAAI,EACjF,MAAO,CAAE,IAAAH,EAAK,OAAAe,CAAO,CACvB,CAEA,IAAMC,EAAaC,GAAUA,EAAM,KAAK;AAAA,CAAI,EAAE,KAAK,EAMtCC,EAAN,KAAc,CACnB,YAAYC,EAAS,CACnB,IAAMC,EAAOD,GAAW,CAAC,EACzB,KAAK,QAAU,CACb,QAASC,EAAK,QACd,YAAaA,EAAK,YAClB,UAAWA,EAAK,WAAa,CAAC,EAC9B,QAASA,EAAK,SAAW9B,GACzB,UAAW8B,EAAK,WAAa,KAAO,EAAIA,EAAK,UAC7C,MAAO,OAAOA,EAAK,OAAU,WAAaA,EAAK,MAAQ,KACvD,MAAOA,EAAK,KACd,EAEA,KAAK,IAAM,GACX,KAAK,IAAM,GACX,KAAK,IAAM,GACX,KAAK,WAAa,IAAI,YAAY,QAAS,CAAE,MAAO,EAAM,CAAC,EAC3D,KAAK,WAAa,IAAI,YAAY,QAAS,CAAE,MAAO,EAAM,CAAC,EAC3D,KAAK,OAAS,IAAI,IAClB,KAAK,SAAW,KAChB,KAAK,MAAQ,KACb,KAAK,MAAQ,GACb,KAAK,QAAU,GACf,KAAK,SAAW,GAEhB,KAAK,SAAW,KAChB,KAAK,OAAS,KACd,KAAK,SAAW,IAClB,CAEA,IAAIC,EAAS,CACP,KAAK,QAAQ,OAAO,KAAK,QAAQ,MAAMA,CAAO,CACpD,CAEA,aAAc,CACZ,IAAIC,EAAI,EACJlB,EAAI,EACR,MAAQA,EAAI,KAAK,IAAI,QAAQjB,EAAQiB,CAAC,KAAO,IAC3CkB,IACAlB,GAAKjB,EAAO,OAEd,OAAOmC,CACT,CAEA,MAAM,QAAQC,EAAWC,EAAOC,EAAU,CACxC,OAAS,CACP,GAAIF,EAAU,EAAG,OACjB,GAAI,KAAK,MAAO,MAAM,IAAI,MAAM,KAAK,KAAK,EAC1C,GAAI,KAAK,IAAI,EAAIE,EAAU,CACzB,IAAMC,EAAM,IAAI,MAAM,yBAA2BF,CAAK,EACtD,MAAAE,EAAI,QAAU,GACRA,CACR,CACA,MAAMnC,EAAM,CAAC,CACf,CACF,CAGA,MAAM,SAASQ,EAAM0B,EAAU,CAC7B,IAAME,EAAQ,IAAI,YAAY,EAAE,OAAO5B,EAAO;AAAA,CAAI,EAClD,QAAW6B,KAAQD,EAAO,CACxB,GAAI,KAAK,IAAI,EAAIF,EAAU,CACzB,IAAMC,EAAM,IAAI,MAAM,+BAA+B,EACrD,MAAAA,EAAI,QAAU,GACRA,CACR,CACA,KAAK,OAAO,gBAAgBE,CAAI,EAChC,MAAMrC,EAAM,KAAK,QAAQ,SAAS,CACpC,CACF,CAGA,MAAM,KAAKY,EAAMsB,EAAU,CACzB,IAAMI,EAAW,KAAK,YAAY,EAClC,MAAM,KAAK,SAAS1B,EAAMsB,CAAQ,EAClC,MAAM,KAAK,QAAQ,IAAM,KAAK,YAAY,EAAII,EAAU,KAAK,UAAU1B,CAAI,EAAGsB,CAAQ,CACxF,CAGA,MAAM,MAAO,CACX,KAAK,SAAWK,EAAsB,CACpC,YAAa,KAAK,QAAQ,YAC1B,UAAW,KAAK,QAAQ,UACxB,IAAMC,GAAM,KAAK,IAAIA,CAAC,EACtB,MAAO,KAAK,QAAQ,KACtB,CAAC,EACD,MAAM,KAAK,SAAS,aAAa,EAEjC,IAAMC,EAAU,OAAO,KAAK,QAAQ,OAAO,EACrCC,EAAUD,EAAQ,MAAM,EAAGA,EAAQ,YAAY,GAAG,EAAI,CAAC,EAEvDE,EAAS,CAIb,UAAW,CAAC,KAAO9C,CAAO,EAC1B,WAAa+C,GAASF,EAAUE,EAChC,OAAQ,CACN,UAAY,CACV,IAAMC,EAAKF,EAAO,GAClBE,EAAG,UAAUnD,CAAI,EACjBmD,EAAG,MAAMnD,CAAI,EACbmD,EAAG,UAAU,WAAY,eAAiBjD,EAAS;AAAA,CAAI,EACvDiD,EAAG,UAAUlD,EAAW,EAAE,CAC5B,CACF,EAEA,MAAO,IAAM,KACb,OAASmD,GAASA,IAAS,MAAQ,KAAK,UAAUA,CAAI,EACtD,OAASA,GAASA,IAAS,MAAQ,KAAK,UAAUA,CAAI,EACtD,MAAQtC,GAAS,KAAK,UAAUA,EAAO;AAAA,CAAI,EAC3C,SAAWA,GAAS,KAAK,UAAUA,EAAO;AAAA,CAAI,EAC9C,OAASsC,GAAS,CAChB,KAAK,SAAWA,EAChB,KAAK,IAAI,wBAA0BA,CAAI,CACzC,EACA,QAAUC,GAAS,CACjB,KAAK,MAAQ,OAAOA,CAAI,CAC1B,CACF,EAEA,YAAK,OAASJ,EAEd,WAAW,OAASA,EAEpB,KAAK,IAAI,WAAaF,CAAO,EAC7B,MAAMtC,GAAWsC,CAAO,EACxB,MAAM,KAAK,QAAQ,IAAM,KAAK,YAAY,EAAI,EAAG,oBAAqB,KAAK,IAAI,EAAI3C,EAAY,EAC/F,KAAK,MAAQ,GACb,KAAK,IAAI,OAAO,EACT,IACT,CAEA,UAAUU,EAAM,CACd,IAAMa,EAAI,OAAOb,GAAS,SAAW,KAAK,WAAW,OAAO,IAAI,WAAW,CAACA,CAAI,CAAC,EAAG,CAAE,OAAQ,EAAK,CAAC,EAAI,OAAOA,CAAI,EACnH,KAAK,KAAOa,EACZ,KAAK,KAAOA,CACd,CAEA,UAAUb,EAAM,CACd,IAAMa,EAAI,OAAOb,GAAS,SAAW,KAAK,WAAW,OAAO,IAAI,WAAW,CAACA,CAAI,CAAC,EAAG,CAAE,OAAQ,EAAK,CAAC,EAAI,OAAOA,CAAI,EACnH,KAAK,KAAOa,EACZ,KAAK,KAAOA,CACd,CAOA,MAAM,aAAa2B,EAAOC,EAAM,CAC9B,IAAMC,GAAQF,GAAS,CAAC,GAAG,OAAQG,GAAS,CAAC,KAAK,OAAO,IAAIA,CAAI,CAAC,EAClE,GAAI,CAACD,EAAK,OAAQ,MAAO,CAAC,EAE1B,IAAMd,EAAQ,MAAM,KAAK,SAAS,cAAcc,EAAMD,CAAI,EACpDG,EAAM,OAAO,KAAKhB,CAAK,EAC7B,GAAI,CAACgB,EAAI,OAAQ,MAAO,CAAC,EAEzB,IAAMP,EAAK,KAAK,OAAO,GACvBA,EAAG,UAAUhD,EAAU,WAAW,EAClC,QAAWsD,KAAQC,EAAKP,EAAG,UAAUhD,EAAU,aAAesD,EAAMf,EAAMe,CAAI,CAAC,EAC/E,KAAK,gBAAgBC,CAAG,EACxB,QAAWD,KAAQC,EAAK,KAAK,OAAO,IAAID,CAAI,EAC5C,YAAK,IAAI,UAAYC,EAAI,OAAS,gBAAkBA,EAAI,KAAK,IAAI,CAAC,EAC3DA,CACT,CAGA,gBAAgBC,EAAU,CACxB,IAAMR,EAAK,KAAK,OAAO,GACvB,QAAWS,KAAO,KAAK,SAAS,UAAUD,CAAQ,EAAG,CACnD,IAAME,EAAM,KAAK,SAAS,gBAAgBD,CAAG,EAC7C,GAAI,CAACC,EAAK,SACV,IAAMC,EAAO3D,EAAU,IAAMyD,EAAI,QAAQ,MAAO,GAAG,EAAI,OACvDT,EAAG,UAAUW,EAAK,MAAM,EAAGA,EAAK,YAAY,GAAG,CAAC,CAAC,EACjDX,EAAG,UAAUW,EAAMD,CAAG,CACxB,CACF,CAQA,MAAM,IAAI3B,EAAS,CACjB,IAAMC,EAAOD,GAAW,CAAC,EACzB,GAAI,KAAK,SAAU,MAAM,IAAI,MAAM,iCAAiC,EACpE,GAAI,KAAK,SAAU,MAAM,IAAI,MAAM,KAAK,QAAQ,EAChD,GAAI,CAAC,KAAK,MAAO,MAAM,IAAI,MAAM,uBAAuB,EACxD,GAAI,KAAK,QAAS,MAAM,IAAI,MAAM,8BAA8B,EAEhE,IAAM6B,EAAU5B,EAAK,SAAW,KAAK,QAAQ,QACvCK,EAAW,KAAK,IAAI,EAAIuB,EACxBC,EAASC,EAAY9B,EAAK,KAAMA,EAAK,KAAK,EAG1C+B,EAAW,KAAK,SAAS,eAAeF,CAAM,EACpD,GAAIE,EAAS,QAAQ,OACnB,OAAO,KAAK,OAAO,CAAE,MAAO,KAAK,SAAS,eAAeA,EAAS,OAAO,CAAE,CAAC,EAG9E,IAAMC,EAAS,MAAM,KAAK,aAAaD,EAAS,SAAUA,EAAS,IAAI,EACjEE,EAASF,EAAS,SAAS,OAAQT,GAAS,CAAC,KAAK,OAAO,IAAIA,CAAI,CAAC,EACxE,GAAIW,EAAO,OACT,OAAO,KAAK,OAAO,CAAE,MAAO,4CAA8CA,EAAO,KAAK,IAAI,EAAG,SAAUD,CAAO,CAAC,EAGjH,IAAME,EAAO,CAAE,IAAK,KAAK,IAAI,OAAQ,IAAK,KAAK,IAAI,OAAQ,IAAK,KAAK,IAAI,MAAO,EAC1EC,EAAO,CAAC,EACRC,EAAU,KAAK,IAAI,EACrBC,EAAW,GAEf,KAAK,QAAU,GACf,GAAI,CACF,KAAK,OAAO,GAAG,UAAUvE,EAAW+D,CAAM,EAG1C,QAAW9C,IAAQ,CAAC,cAAe,UAAW,OAAO,EACnDoD,EAAK,KAAKpD,CAAI,EACd,MAAM,KAAK,KAAKA,EAAMsB,CAAQ,CAElC,OAASC,EAAK,CACZ+B,EAAW,CAAC,CAAC/B,EAAI,QACZ+B,IAAU,KAAK,MAAQ,OAAQ/B,GAAOA,EAAI,SAAYA,CAAG,EAChE,QAAE,CACA,KAAK,QAAU,EACjB,CAEA,IAAMgC,EAAY,KAAK,QAAQJ,EAAMC,CAAI,EACzC,OAAIE,IACF,KAAK,SAAW,4EAGX,KAAK,OAAO,CACjB,GAAGC,EACH,MACEA,EAAU,QACTD,EAAW,mBAAqBT,EAAU,KAAO,QACjD,KAAK,MAAQ,KAAK,MAAQ,MAC7B,SAAUS,EAAW,IAAM,OAC3B,SAAUL,EACV,WAAY,KAAK,IAAI,EAAII,CAC3B,CAAC,CACH,CAGA,QAAQF,EAAMC,EAAM,CAClB,IAAMI,EAAO7C,EAAST,EAAM,KAAK,IAAI,MAAMiD,EAAK,GAAG,EAAGC,CAAI,CAAC,EACrDK,EAAO9C,EAAST,EAAM,KAAK,IAAI,MAAMiD,EAAK,GAAG,EAAGC,CAAI,CAAC,EACrDxC,EAAS,CAAC,EAChB,QAAWZ,KAAQwD,EAAK,OAAO,OAAOC,EAAK,MAAM,EAC1C7C,EAAO,SAASZ,CAAI,GAAGY,EAAO,KAAKZ,CAAI,EAE9C,IAAM0D,EAAQ7C,EAAUD,CAAM,EAC9B,MAAO,CACL,OAAQC,EAAU2C,EAAK,GAAG,EAC1B,OAAQ3C,EAAU4C,EAAK,GAAG,EAC1B,MAAOC,EAAQ,KAAK,SAAS,gBAAgBA,CAAK,EAAI,KACtD,OAAQxD,EAAM,KAAK,IAAI,MAAMiD,EAAK,GAAG,EAAGC,CAAI,EAAE,KAAK,CACrD,CACF,CAEA,OAAOO,EAAO,CACZ,IAAMD,EAAQC,EAAM,OAAS,KACvBC,EACJD,EAAM,UAAY,KAAOA,EAAM,SAAWD,EAAQ,EAAI,KAAK,UAAY,KAAO,EAAI,KAAK,SACzF,MAAO,CACL,OAAQC,EAAM,QAAU,GACxB,OAAQA,EAAM,QAAU,GACxB,MAAAD,EACA,OAAQC,EAAM,QAAU,GACxB,SAAAC,EACA,SAAUD,EAAM,UAAY,CAAC,EAC7B,WAAYA,EAAM,YAAc,KAAO,EAAIA,EAAM,UACnD,CACF,CAMA,SAAU,CACR,KAAK,SAAW,GAChB,KAAK,OAAS,KACd,KAAK,SAAW,KAChB,KAAK,OAAO,MAAM,CACpB,CACF,EHzZA,IAAAE,GAAA,GAuBMC,IAAY,IAAM,CACtB,GAAI,OAAO,SAAa,KAAe,SAAS,eAAiB,SAAS,cAAc,IACtF,OAAOC,EAAM,SAAS,cAAc,GAAG,EAEzC,GAAI,CACF,OAAOA,EAAMF,GAAY,GAAG,CAC9B,MAAc,CAEd,CACA,OAAI,OAAO,SAAa,KAAe,SAAS,KAAaE,EAAM,SAAS,IAAI,EACzE,EACT,GAAG,EAEH,SAASA,EAAMC,EAAK,CAClB,OAAO,OAAOA,CAAG,EAAE,MAAM,EAAG,OAAOA,CAAG,EAAE,YAAY,GAAG,EAAI,CAAC,CAC9D,CAEA,IAAMC,GAAaD,GAAS,OAAOA,CAAG,EAAE,SAAS,GAAG,EAAI,OAAOA,CAAG,EAAI,OAAOA,CAAG,EAAI,IAkBpF,eAAsBE,EAAcC,EAAS,CAC3C,IAAMC,EAAOD,GAAW,CAAC,EACnBE,EAAUJ,GAAUG,EAAK,SAAWN,EAAQ,EAC5CQ,EAAO,IAAIC,EAAQ,CACvB,GAAGH,EACH,QAASA,EAAK,SAAWC,EAAU,mBACnC,YAAaD,EAAK,aAAeC,EAAU,OAC7C,CAAC,EACD,aAAMC,EAAK,KAAK,EACTA,CACT,CAGA,IAAOE,GAAQ,CAAE,cAAAC,EAAe,QAAAC,CAAQ",
|
|
6
|
+
"names": ["index_exports", "__export", "MicroHs", "createHaskell", "index_default", "withSlash", "url", "importedModules", "source", "code", "line", "out", "re", "m", "customName", "clean", "createPackageResolver", "options", "opts", "base", "importmap", "log", "doFetch", "args", "custom", "moduleName", "name", "entry", "manifestPromise", "manifest", "loadManifest", "res", "err", "classifyModule", "rule", "analyzeImports", "needed", "urls", "missing", "mod", "found", "closure", "queue", "pkg", "deps", "dep", "packageOfModule", "modulesOf", "pkgFiles", "wanted", "fetchPackages", "names", "buf", "explainMissing", "lines", "item", "count", "pkgs", "examples", "explainNotFound", "text", "seen", "s", "why", "IMPORTS", "ESCAPES", "toHaskellString", "text", "out", "ch", "code", "definesName", "source", "name", "importInsertAt", "lines", "header", "l", "i", "line", "shimSource", "input", "parts", "add", "injectStdin", "at", "hoisted", "IMPORTS", "HOME", "MAIN_FILE", "PROMPT", "PKG_DIR", "BOOT_TIMEOUT", "DEFAULT_TIMEOUT", "delay", "ms", "resolve", "loadScript", "url", "reject", "script", "applyBackspaces", "text", "out", "ch", "applyCarriageReturns", "line", "i", "clean", "sentLines", "noPrompts", "noAnsi", "banner", "t", "re", "s", "isErrorLine", "classify", "errors", "joinLines", "lines", "MicroHs", "options", "opts", "message", "n", "predicate", "label", "deadline", "err", "bytes", "byte", "baseline", "createPackageResolver", "m", "wasmUrl", "wasmDir", "Module", "file", "FS", "code", "what", "names", "urls", "want", "name", "got", "pkgFiles", "mod", "pkg", "path", "timeout", "source", "injectStdin", "analysis", "loaded", "absent", "mark", "sent", "started", "timedOut", "collected", "outC", "errC", "error", "extra", "exitCode", "import_meta", "SELF_DIR", "dirOf", "url", "withSlash", "createHaskell", "options", "opts", "baseUrl", "repl", "MicroHs", "index_default", "createHaskell", "MicroHs"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*! @live-codes/browser-haskell v0.1.0 | MIT
|
|
2
|
+
* Runs Haskell in the browser with MicroHs (Apache-2.0). */
|
|
3
|
+
var Z=s=>s.endsWith("/")?s:s+"/";function z(s){let t=String(s).replace(/\{-[\s\S]*?-\}/g," ").split(`
|
|
4
|
+
`).map(a=>a.replace(/--.*$/,"")).join(`
|
|
5
|
+
`),e=[],n=/^[ \t]*import[ \t]+(?:safe[ \t]+)?(?:qualified[ \t]+)?(?:"[^"]*"[ \t]+)?([A-Z][A-Za-z0-9_.']*)/gm,o;for(;(o=n.exec(t))!==null;)e.indexOf(o[1])===-1&&e.push(o[1]);return e}function D(s){let t=String(s).split("?")[0].split("#")[0];return t.slice(t.lastIndexOf("/")+1)||"custom.pkg"}function P(s){let t=s||{},e=Z(t.packagesUrl),n=t.importmap||{},o=t.log||(()=>{}),a=t.fetch||((...i)=>fetch(...i)),l=new Map;for(let i of Object.keys(n)){let r=n[i];if(typeof r!="string"||!r)continue;let p=D(r),f=l.get(p)||{name:p,url:r,modules:new Set};f.modules.add(i),l.set(p,f)}let d=null,c=null;function E(){if(!d){let i=e+"index.json";d=a(i,{cache:"no-store"}).then(r=>r.ok?r.json():null).then(r=>!r||Array.isArray(r)?(o("no package manifest at "+i+"; only the embedded modules are available"),null):(c=r,r)).catch(r=>(o("failed to load "+i+": "+(r&&r.message)),null))}return d}function y(i){if(l.has(i)){let r=l.get(i);return{kind:"package",pkg:r.name,url:r.url}}if(c&&c.modules&&c.modules[i])return{kind:"package",pkg:c.modules[i]};if(!c)return{kind:"unknown"};if(c.embedded&&c.embedded.indexOf(i)!==-1)return{kind:"embedded"};for(let r of c.unavailable||[])if(i===r.prefix||i.indexOf(r.prefix+".")===0)return{kind:"unavailable",reason:r.reason};return{kind:"unknown"}}function x(i){let r=new Set,p={},f=[];for(let h of z(i)){if(n[h]){let S=D(n[h]);r.add(S),p[S]=n[h];continue}let w=y(h);w.kind==="package"?r.add(w.pkg):w.kind==="unavailable"?f.push({module:h,reason:w.reason}):w.kind==="unknown"&&f.push({module:h,reason:"not bundled with this playground"})}let m=new Set,u=Array.from(r);for(;u.length;){let h=u.shift();if(m.has(h))continue;m.add(h);let w=c&&c.packages&&c.packages[h]||[];for(let S of w)!m.has(S)&&u.indexOf(S)===-1&&u.push(S)}return{packages:Array.from(m).sort(),missing:f,urls:p}}function k(i){return l.has(i)?l.get(i).name:c&&c.modules&&c.modules[i]||null}function O(i){let r=[],p=new Set(i);if(c&&c.modules)for(let f of Object.keys(c.modules))p.has(c.modules[f])&&r.push(f);for(let f of l.values())p.has(f.name)&&r.push(...f.modules);return r}function g(i,r){let p={};return Promise.all(i.map(f=>{let m=r&&r[f]||e+"packages/"+f;return a(m,{cache:"force-cache"}).then(u=>{if(!u.ok)throw new Error("HTTP "+u.status+" for "+m);return u.arrayBuffer()}).then(u=>{p[f]=new Uint8Array(u)}).catch(u=>{o("could not fetch "+m+": "+(u&&u.message))})})).then(()=>p)}function A(i){if(!i||!i.length)return null;let r=["Not available in this playground:"];for(let p of i)r.push(" "+p.module+" \u2014 "+p.reason);if(c&&c.modules&&c.packages){let p=Object.keys(c.modules).length,f=(c.embedded||[]).length,m=Object.keys(c.packages).length,u=["Data.Map","Control.Monad.State","System.Random","Data.Time","Test.Hspec"].filter(h=>c.modules[h]!==void 0);r.push(""),r.push("This playground provides base ("+f+" modules) plus "+m+" packages ("+p+" modules), including "+(u.length?u.join(", ")+", \u2026":"see the manifest")+".")}return r.join(`
|
|
6
|
+
`)}function N(i){if(!i)return i;let r=[],p=/Module not found:\s*([A-Z][A-Za-z0-9_.']*)/g,f;for(;(f=p.exec(i))!==null;){let u=f[1];if(r.some(w=>w.module===u))continue;let h=y(u);h.kind==="unavailable"?r.push({module:u,reason:h.reason}):h.kind==="unknown"?r.push({module:u,reason:"not bundled with this playground"}):h.kind==="package"&&r.push({module:u,reason:"its package ("+h.pkg+") is not loaded"})}let m=A(r);return m?i+`
|
|
7
|
+
|
|
8
|
+
`+m:i}return{loadManifest:E,classifyModule:y,analyzeImports:x,packageOfModule:k,modulesOf:O,fetchPackages:g,explainMissing:A,explainNotFound:N,get manifest(){return c}}}var H=["import Data.IORef","import System.IO.Unsafe (unsafePerformIO)"];var C={"\\":"\\\\",'"':'\\"',"\n":"\\n","\r":"\\r"," ":"\\t"};function q(s){let t="";for(let e of String(s)){if(C[e]){t+=C[e];continue}let n=e.codePointAt(0);if(n<32||n===127){t+="\\"+n+"\\&";continue}t+=e}return t}function v(s,t){return new RegExp("^"+t+"\\s*(::|=)","m").test(s)}function $(s){let t=s.findIndex(n=>/^module\s+[A-Z][A-Za-z0-9_.']*\s*(\(.*)?\bwhere\b/.test(n));if(t!==-1)return t+1;let e=0;for(;e<s.length;){let n=s[e].trim();if(!(n===""||n.startsWith("--")||n.startsWith("{-#")||n.startsWith("{-")||n.startsWith("#")))break;if(n.startsWith("{-")&&!n.includes("-}")){for(;e<s.length&&!s[e].includes("-}");)e++;e++;continue}e++}return e}function B(s,t){let e=[],n=(o,a)=>{v(t,o)||e.push(a)};return n("lcInput",["-- stdin, injected by @live-codes/browser-haskell (this build has no fd 0)","lcInput :: String",'lcInput = "'+q(s)+'"'].join(`
|
|
9
|
+
`)),n("lcInputLines",`lcInputLines :: [String]
|
|
10
|
+
lcInputLines = lines lcInput`),n("lcInputWords",`lcInputWords :: [String]
|
|
11
|
+
lcInputWords = words lcInput`),v(t,"lcInput")||(e.push(["{-# NOINLINE lcStdinRef #-}","lcStdinRef :: IORef String","lcStdinRef = unsafePerformIO (newIORef lcInput)","","lcReadAll :: IO String","lcReadAll = do"," s <- readIORef lcStdinRef",' writeIORef lcStdinRef ""'," return s"].join(`
|
|
12
|
+
`)),n("getLine",["getLine :: IO String","getLine = do"," s <- readIORef lcStdinRef"," case s of",' [] -> return ""'," _ -> do"," let (l, rest) = break (== '\\n') s"," writeIORef lcStdinRef (drop 1 rest)"," return l"].join(`
|
|
13
|
+
`)),n("readLn",`readLn :: Read a => IO a
|
|
14
|
+
readLn = getLine >>= return . read`),n("getContents",`getContents :: IO String
|
|
15
|
+
getContents = lcReadAll`),n("interact",`interact :: (String -> String) -> IO ()
|
|
16
|
+
interact f = getContents >>= putStr . f`)),e.join(`
|
|
17
|
+
|
|
18
|
+
`)}function T(s,t){let e=String(s??""),n=String(t??"");if(!n)return e;let o=e.replace(/\s*$/,"").split(`
|
|
19
|
+
`),a=$(o),l=H.filter(c=>!new RegExp("^"+c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"\\s*$","m").test(e));return(l.length?o.slice(0,a).concat([""]).concat(l).concat("").concat(o.slice(a)):o).join(`
|
|
20
|
+
`)+`
|
|
21
|
+
|
|
22
|
+
`+B(n,e)+`
|
|
23
|
+
`}var U="/home/web_user",F="Main.hs",M="<<<LC_PROMPT>>>",I="/pkgs",G=3e4,J=6e4,_=s=>new Promise(t=>setTimeout(t,s));async function K(s){if(typeof document<"u"&&document.createElement){await new Promise((t,e)=>{let n=document.createElement("script");n.src=s,n.onload=()=>t(),n.onerror=()=>e(new Error("failed to load "+s)),(document.head||document.body||document.documentElement).appendChild(n)});return}if(typeof importScripts=="function"){importScripts(s);return}await import(s)}function Q(s){let t="";for(let e of s)e==="\b"?t=t.slice(0,-1):t+=e;return t}function V(s){return s.split(`
|
|
24
|
+
`).map(t=>{let e=t.lastIndexOf("\r");return e>=0?t.slice(e+1):t}).join(`
|
|
25
|
+
`)}function L(s,t){let e=s.split(M).join(""),n=V(Q(e.replace(/\u001b\[[0-9;?]*[A-Za-z]|\u001b[@-Z\\-_]|\u001b\([A-Za-z0-9]/g,"").replace(/\u0007/g,""))),o=[/^Welcome to interactive MicroHs/,/^Integer implemented with imath/,/^Loading embedded package /,/^Loading package /,/^loaded /,/^Type ':quit' to quit/];return n.split(`
|
|
26
|
+
`).filter(a=>{let l=a.trim();return!(o.some(d=>d.test(l))||(t||[]).some(d=>l===d))}).join(`
|
|
27
|
+
`)}function X(s){let t=s.trim();return/^(\*\*\* )?(Exception|error:|Error:)/.test(t)||/^Unrecognized command/.test(t)||/^fully qualified:/.test(t)||/: line \d+, col \d+:/.test(t)}function W(s){let t=[],e=[];for(let n of s.split(`
|
|
28
|
+
`))(X(n)?e:t).push(n);return{out:t,errors:e}}var R=s=>s.join(`
|
|
29
|
+
`).trim(),b=class{constructor(t){let e=t||{};this.options={wasmUrl:e.wasmUrl,packagesUrl:e.packagesUrl,importmap:e.importmap||{},timeout:e.timeout||J,charDelay:e.charDelay==null?0:e.charDelay,onLog:typeof e.onLog=="function"?e.onLog:null,fetch:e.fetch},this.raw="",this.out="",this.err="",this.outDecoder=new TextDecoder("utf-8",{fatal:!1}),this.errDecoder=new TextDecoder("utf-8",{fatal:!1}),this.loaded=new Set,this.exitCode=null,this.fatal=null,this.ready=!1,this.running=!1,this.disposed=!1,this.poisoned=null,this.Module=null,this.resolver=null}log(t){this.options.onLog&&this.options.onLog(t)}promptCount(){let t=0,e=0;for(;(e=this.raw.indexOf(M,e))!==-1;)t++,e+=M.length;return t}async waitFor(t,e,n){for(;;){if(t())return;if(this.fatal)throw new Error(this.fatal);if(Date.now()>n){let o=new Error("timed out waiting for "+e);throw o.timeout=!0,o}await _(1)}}async typeLine(t,e){let n=new TextEncoder().encode(t+`
|
|
30
|
+
`);for(let o of n){if(Date.now()>e){let a=new Error("timed out while sending input");throw a.timeout=!0,a}this.Module._set_input_char(o),await _(this.options.charDelay)}}async step(t,e){let n=this.promptCount();await this.typeLine(t,e),await this.waitFor(()=>this.promptCount()>n,JSON.stringify(t),e)}async boot(){this.resolver=P({packagesUrl:this.options.packagesUrl,importmap:this.options.importmap,log:o=>this.log(o),fetch:this.options.fetch}),await this.resolver.loadManifest();let t=String(this.options.wasmUrl),e=t.slice(0,t.lastIndexOf("/")+1),n={arguments:["-a"+I],locateFile:o=>e+o,preRun:[function(){let o=n.FS;o.mkdirTree(U),o.chdir(U),o.writeFile(".mhsi_rc",":set prompt="+M+`
|
|
31
|
+
`),o.writeFile(F,"")}],stdin:()=>null,stdout:o=>o!==null&&this.appendOut(o),stderr:o=>o!==null&&this.appendErr(o),print:o=>this.appendOut(o+`
|
|
32
|
+
`),printErr:o=>this.appendErr(o+`
|
|
33
|
+
`),onExit:o=>{this.exitCode=o,this.log("compiler exited with "+o)},onAbort:o=>{this.fatal=String(o)}};return this.Module=n,globalThis.Module=n,this.log("loading "+t),await K(t),await this.waitFor(()=>this.promptCount()>0,"the REPL to start",Date.now()+G),this.ready=!0,this.log("ready"),this}appendOut(t){let e=typeof t=="number"?this.outDecoder.decode(new Uint8Array([t]),{stream:!0}):String(t);this.out+=e,this.raw+=e}appendErr(t){let e=typeof t=="number"?this.errDecoder.decode(new Uint8Array([t]),{stream:!0}):String(t);this.err+=e,this.raw+=e}async loadPackages(t,e){let n=(t||[]).filter(d=>!this.loaded.has(d));if(!n.length)return[];let o=await this.resolver.fetchPackages(n,e),a=Object.keys(o);if(!a.length)return[];let l=this.Module.FS;l.mkdirTree(I+"/packages");for(let d of a)l.writeFile(I+"/packages/"+d,o[d]);this.writeModuleMaps(a);for(let d of a)this.loaded.add(d);return this.log("loaded "+a.length+" package(s): "+a.join(", ")),a}writeModuleMaps(t){let e=this.Module.FS;for(let n of this.resolver.modulesOf(t)){let o=this.resolver.packageOfModule(n);if(!o)continue;let a=I+"/"+n.replace(/\./g,"/")+".txt";e.mkdirTree(a.slice(0,a.lastIndexOf("/"))),e.writeFile(a,o)}}async run(t){let e=t||{};if(this.disposed)throw new Error("this instance has been disposed");if(this.poisoned)throw new Error(this.poisoned);if(!this.ready)throw new Error("the REPL is not ready");if(this.running)throw new Error("a run is already in progress");let n=e.timeout||this.options.timeout,o=Date.now()+n,a=T(e.code,e.stdin),l=this.resolver.analyzeImports(a);if(l.missing.length)return this.result({error:this.resolver.explainMissing(l.missing)});let d=await this.loadPackages(l.packages,l.urls),c=l.packages.filter(g=>!this.loaded.has(g));if(c.length)return this.result({error:"package file(s) missing from this build: "+c.join(", "),packages:d});let E={raw:this.raw.length,out:this.out.length,err:this.err.length},y=[],x=Date.now(),k=!1;this.running=!0;try{this.Module.FS.writeFile(F,a);for(let g of["import Main",":reload",":main"])y.push(g),await this.step(g,o)}catch(g){k=!!g.timeout,k||(this.fatal=String(g&&g.message||g))}finally{this.running=!1}let O=this.collect(E,y);return k&&(this.poisoned="the previous run timed out and left the REPL busy; create a new instance"),this.result({...O,error:O.error||(k?"timed out after "+n+"ms":null)||(this.fatal?this.fatal:null),exitCode:k?124:void 0,packages:d,durationMs:Date.now()-x})}collect(t,e){let n=W(L(this.out.slice(t.out),e)),o=W(L(this.err.slice(t.err),e)),a=[];for(let d of n.errors.concat(o.errors))a.includes(d)||a.push(d);let l=R(a);return{stdout:R(n.out),stderr:R(o.out),error:l?this.resolver.explainNotFound(l):null,output:L(this.raw.slice(t.raw),e).trim()}}result(t){let e=t.error||null,n=t.exitCode!=null?t.exitCode:e?1:this.exitCode==null?0:this.exitCode;return{stdout:t.stdout||"",stderr:t.stderr||"",error:e,output:t.output||"",exitCode:n,packages:t.packages||[],durationMs:t.durationMs==null?0:t.durationMs}}dispose(){this.disposed=!0,this.Module=null,this.resolver=null,this.loaded.clear()}};var Y=(()=>{if(typeof document<"u"&&document.currentScript&&document.currentScript.src)return j(document.currentScript.src);try{return j(import.meta.url)}catch{}return typeof location<"u"&&location.href?j(location.href):""})();function j(s){return String(s).slice(0,String(s).lastIndexOf("/")+1)}var tt=s=>String(s).endsWith("/")?String(s):String(s)+"/";async function et(s){let t=s||{},e=tt(t.baseUrl||Y),n=new b({...t,wasmUrl:t.wasmUrl||e+"mhs/mhs-embed.js",packagesUrl:t.packagesUrl||e+"pkgs/"});return await n.boot(),n}var ct={createHaskell:et,MicroHs:b};export{b as MicroHs,et as createHaskell,ct as default};
|
|
34
|
+
//# sourceMappingURL=browser-haskell.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/manifest.js", "../src/shim.js", "../src/repl.js", "../src/index.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * Which packages does a program need, and where do they come from?\n *\n * The wasm bundle embeds MicroHs's `base` (+ canvhs). Everything else ships as MicroHs\n * packages, described by a manifest that is fetched lazily and used to pull in only the\n * `.pkg` files a program actually imports:\n *\n * {\n * \"modules\": { \"Data.Map\": \"containers-0.8.pkg\", ... },\n * \"packages\": { \"containers-0.8.pkg\": [\"array-mhs-0.5.8.0.pkg\"], ... },\n * \"embedded\": [\"Data.List\", ...],\n * \"unavailable\": [{ \"prefix\": \"Data.Aeson\", \"reason\": \"not bundled here\" }]\n * }\n *\n * `embedded` and `unavailable` are what let an import we cannot satisfy come back with\n * \"not available, because X\" instead of a bare `Module not found`.\n *\n * Inside the compiler's virtual FS the layout is:\n * /pkgs/packages/<name>.pkg the serialized package\n * /pkgs/<Module/Path>.txt contains the package file name\n */\n\nconst withSlash = (url) => (url.endsWith('/') ? url : url + '/');\n\n/** Imported module names in a source file, in source order. Comments are ignored. */\nexport function importedModules(source) {\n const code = String(source)\n .replace(/\\{-[\\s\\S]*?-\\}/g, ' ')\n .split('\\n')\n .map((line) => line.replace(/--.*$/, ''))\n .join('\\n');\n const out = [];\n const re = /^[ \\t]*import[ \\t]+(?:safe[ \\t]+)?(?:qualified[ \\t]+)?(?:\"[^\"]*\"[ \\t]+)?([A-Z][A-Za-z0-9_.']*)/gm;\n let m;\n while ((m = re.exec(code)) !== null) {\n if (out.indexOf(m[1]) === -1) out.push(m[1]);\n }\n return out;\n}\n\n/** The package file name implied by a custom package URL. */\nfunction customName(url) {\n const clean = String(url).split('?')[0].split('#')[0];\n const last = clean.slice(clean.lastIndexOf('/') + 1);\n return last || 'custom.pkg';\n}\n\n/**\n * @param {object} options\n * @param {string} options.packagesUrl directory holding index.json and packages/\n * @param {Object<string,string>} [options.importmap] module -> .pkg URL, for packages\n * that are not in the manifest. They must be built by the same MicroHs version, and\n * any MicroHs dependencies they have must be mapped here too (the manifest cannot\n * know about them).\n * @param {(msg: string) => void} [options.log]\n * @param {typeof fetch} [options.fetch]\n */\nexport function createPackageResolver(options) {\n const opts = options || {};\n const base = withSlash(opts.packagesUrl);\n const importmap = opts.importmap || {};\n const log = opts.log || (() => {});\n const doFetch = opts.fetch || ((...args) => fetch(...args));\n\n /** module file name -> { name, url, modules } for importmap entries */\n const custom = new Map();\n for (const moduleName of Object.keys(importmap)) {\n const url = importmap[moduleName];\n if (typeof url !== 'string' || !url) continue;\n const name = customName(url);\n const entry = custom.get(name) || { name, url, modules: new Set() };\n entry.modules.add(moduleName);\n custom.set(name, entry);\n }\n\n let manifestPromise = null;\n let manifest = null;\n\n function loadManifest() {\n if (!manifestPromise) {\n const url = base + 'index.json';\n manifestPromise = doFetch(url, { cache: 'no-store' })\n .then((res) => (res.ok ? res.json() : null))\n .then((m) => {\n if (!m || Array.isArray(m)) {\n log('no package manifest at ' + url + '; only the embedded modules are available');\n return null;\n }\n manifest = m;\n return m;\n })\n .catch((err) => {\n log('failed to load ' + url + ': ' + (err && err.message));\n return null;\n });\n }\n return manifestPromise;\n }\n\n /**\n * @returns {{kind:'package'|'custom'|'embedded'|'unavailable'|'unknown', pkg?:string, url?:string, reason?:string}}\n */\n function classifyModule(name) {\n if (custom.has(name)) {\n const entry = custom.get(name);\n return { kind: 'package', pkg: entry.name, url: entry.url };\n }\n if (manifest && manifest.modules && manifest.modules[name]) {\n return { kind: 'package', pkg: manifest.modules[name] };\n }\n if (!manifest) {\n // Without a manifest only the embedded modules are known for sure.\n return { kind: 'unknown' };\n }\n if (manifest.embedded && manifest.embedded.indexOf(name) !== -1) return { kind: 'embedded' };\n for (const rule of manifest.unavailable || []) {\n if (name === rule.prefix || name.indexOf(rule.prefix + '.') === 0) {\n return { kind: 'unavailable', reason: rule.reason };\n }\n }\n return { kind: 'unknown' };\n }\n\n /**\n * What a program needs before it can compile.\n * @returns {{packages:string[], missing:{module:string, reason:string}[], urls:Object<string,string>}}\n */\n function analyzeImports(source) {\n const needed = new Set();\n const urls = {};\n const missing = [];\n\n for (const mod of importedModules(source)) {\n if (importmap[mod]) {\n const name = customName(importmap[mod]);\n needed.add(name);\n urls[name] = importmap[mod];\n continue;\n }\n const found = classifyModule(mod);\n if (found.kind === 'package') needed.add(found.pkg);\n else if (found.kind === 'unavailable') missing.push({ module: mod, reason: found.reason });\n else if (found.kind === 'unknown') {\n missing.push({ module: mod, reason: 'not bundled with this playground' });\n }\n }\n\n // A package brings its MicroHs dependencies with it.\n const closure = new Set();\n const queue = Array.from(needed);\n while (queue.length) {\n const pkg = queue.shift();\n if (closure.has(pkg)) continue;\n closure.add(pkg);\n const deps = (manifest && manifest.packages && manifest.packages[pkg]) || [];\n for (const dep of deps) {\n if (!closure.has(dep) && queue.indexOf(dep) === -1) queue.push(dep);\n }\n }\n\n return { packages: Array.from(closure).sort(), missing, urls };\n }\n\n /** The package file that provides a module (from the manifest or the importmap). */\n function packageOfModule(mod) {\n if (custom.has(mod)) return custom.get(mod).name;\n if (manifest && manifest.modules) return manifest.modules[mod] || null;\n return null;\n }\n\n /** Modules provided by the given package files (used to write the lookup maps). */\n function modulesOf(pkgFiles) {\n const out = [];\n const wanted = new Set(pkgFiles);\n if (manifest && manifest.modules) {\n for (const mod of Object.keys(manifest.modules)) {\n if (wanted.has(manifest.modules[mod])) out.push(mod);\n }\n }\n for (const entry of custom.values()) {\n if (wanted.has(entry.name)) out.push(...entry.modules);\n }\n return out;\n }\n\n /** Fetch package files. @returns {Promise<Object<string, Uint8Array>>} */\n function fetchPackages(names, urls) {\n const out = {};\n return Promise.all(\n names.map((name) => {\n const url = (urls && urls[name]) || base + 'packages/' + name;\n return doFetch(url, { cache: 'force-cache' })\n .then((res) => {\n if (!res.ok) throw new Error('HTTP ' + res.status + ' for ' + url);\n return res.arrayBuffer();\n })\n .then((buf) => {\n out[name] = new Uint8Array(buf);\n })\n .catch((err) => {\n log('could not fetch ' + url + ': ' + (err && err.message));\n });\n }),\n ).then(() => out);\n }\n\n /** A human explanation for imports we cannot satisfy, or null if there are none. */\n function explainMissing(missing) {\n if (!missing || !missing.length) return null;\n const lines = ['Not available in this playground:'];\n for (const item of missing) lines.push(' ' + item.module + ' \u2014 ' + item.reason);\n if (manifest && manifest.modules && manifest.packages) {\n const count = Object.keys(manifest.modules).length;\n const base = (manifest.embedded || []).length;\n const pkgs = Object.keys(manifest.packages).length;\n const examples = ['Data.Map', 'Control.Monad.State', 'System.Random', 'Data.Time', 'Test.Hspec']\n .filter((mod) => manifest.modules[mod] !== undefined);\n lines.push('');\n lines.push(\n 'This playground provides base (' + base + ' modules) plus ' + pkgs + ' packages (' + count +\n ' modules), including ' + (examples.length ? examples.join(', ') + ', \u2026' : 'see the manifest') + '.',\n );\n }\n return lines.join('\\n');\n }\n\n /**\n * The backstop for a `Module not found: X` the pre-check could not see \u2014 the reason\n * is appended so the message does not look like a broken package.\n */\n function explainNotFound(text) {\n if (!text) return text;\n const seen = [];\n const re = /Module not found:\\s*([A-Z][A-Za-z0-9_.']*)/g;\n let m;\n while ((m = re.exec(text)) !== null) {\n const name = m[1];\n if (seen.some((s) => s.module === name)) continue;\n const found = classifyModule(name);\n if (found.kind === 'unavailable') seen.push({ module: name, reason: found.reason });\n else if (found.kind === 'unknown') seen.push({ module: name, reason: 'not bundled with this playground' });\n else if (found.kind === 'package') {\n seen.push({ module: name, reason: 'its package (' + found.pkg + ') is not loaded' });\n }\n }\n const why = explainMissing(seen);\n return why ? text + '\\n\\n' + why : text;\n }\n\n return {\n loadManifest,\n classifyModule,\n analyzeImports,\n packageOfModule,\n modulesOf,\n fetchPackages,\n explainMissing,\n explainNotFound,\n get manifest() {\n return manifest;\n },\n };\n}\n", "/**\n * stdin for Haskell programs.\n *\n * The MicroHs web build has no usable fd 0: `getLine` throws\n * `Handle(stdin): end of file`, and the REPL's own input queue (`_set_input_char`)\n * belongs to the REPL \u2014 characters sent while a program runs are read by the REPL\n * afterwards, not by the program. So stdin has to arrive as *source*:\n *\n * 1. `lcInput` / `lcInputLines` / `lcInputWords` \u2014 pure bindings, no imports needed.\n * 2. Prelude's `getLine`, `readLn`, `getContents` and `interact` are shadowed by\n * equivalents that consume the same input, so ordinary programs work unchanged.\n * A top-level definition in Main shadows the imported one, which is what makes\n * this possible without touching the compiler.\n *\n * The shadowing needs `Data.IORef` and `System.IO.Unsafe`, so the imports are hoisted\n * to the top of the module (they cannot appear after declarations).\n */\n\nconst IMPORTS = ['import Data.IORef', 'import System.IO.Unsafe (unsafePerformIO)'];\n\n/** Names we shadow; skipped if the program defines them itself. */\nconst SHADOWED = ['getLine', 'readLn', 'getContents', 'interact'];\n\nconst ESCAPES = { '\\\\': '\\\\\\\\', '\"': '\\\\\"', '\\n': '\\\\n', '\\r': '\\\\r', '\\t': '\\\\t' };\n\n/** Escape text as a Haskell string literal. */\nexport function toHaskellString(text) {\n let out = '';\n for (const ch of String(text)) {\n if (ESCAPES[ch]) {\n out += ESCAPES[ch];\n continue;\n }\n const code = ch.codePointAt(0);\n if (code < 0x20 || code === 0x7f) {\n // Numeric escape; `\\&` keeps a following digit from joining the number.\n out += '\\\\' + code + '\\\\&';\n continue;\n }\n out += ch;\n }\n return out;\n}\n\n/** Does the program define this name at the top level? */\nfunction definesName(source, name) {\n return new RegExp('^' + name + '\\\\s*(::|=)', 'm').test(source);\n}\n\n/**\n * Where new import lines can legally go: after the module header if there is one,\n * otherwise after any leading pragmas and comments (which must come first).\n */\nfunction importInsertAt(lines) {\n const header = lines.findIndex((l) => /^module\\s+[A-Z][A-Za-z0-9_.']*\\s*(\\(.*)?\\bwhere\\b/.test(l));\n if (header !== -1) return header + 1;\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i].trim();\n const isLeading =\n line === '' ||\n line.startsWith('--') ||\n line.startsWith('{-#') ||\n line.startsWith('{-') ||\n line.startsWith('#');\n if (!isLeading) break;\n if (line.startsWith('{-') && !line.includes('-}')) {\n // Block comment: skip to its end.\n while (i < lines.length && !lines[i].includes('-}')) i++;\n i++;\n continue;\n }\n i++;\n }\n return i;\n}\n\nfunction shimSource(input, source) {\n const parts = [];\n const add = (name, text) => {\n if (!definesName(source, name)) parts.push(text);\n };\n\n add(\n 'lcInput',\n [\n '-- stdin, injected by @live-codes/browser-haskell (this build has no fd 0)',\n 'lcInput :: String',\n 'lcInput = \"' + toHaskellString(input) + '\"',\n ].join('\\n'),\n );\n add('lcInputLines', 'lcInputLines :: [String]\\nlcInputLines = lines lcInput');\n add('lcInputWords', 'lcInputWords :: [String]\\nlcInputWords = words lcInput');\n\n if (definesName(source, 'lcInput')) {\n // The program provides its own input; nothing to shadow it with.\n return parts.join('\\n\\n');\n }\n\n parts.push(\n [\n '{-# NOINLINE lcStdinRef #-}',\n 'lcStdinRef :: IORef String',\n 'lcStdinRef = unsafePerformIO (newIORef lcInput)',\n '',\n 'lcReadAll :: IO String',\n 'lcReadAll = do',\n ' s <- readIORef lcStdinRef',\n ' writeIORef lcStdinRef \"\"',\n ' return s',\n ].join('\\n'),\n );\n\n add(\n 'getLine',\n [\n 'getLine :: IO String',\n 'getLine = do',\n ' s <- readIORef lcStdinRef',\n ' case s of',\n ' [] -> return \"\"',\n ' _ -> do',\n ' let (l, rest) = break (== \\'\\\\n\\') s',\n ' writeIORef lcStdinRef (drop 1 rest)',\n ' return l',\n ].join('\\n'),\n );\n add('readLn', 'readLn :: Read a => IO a\\nreadLn = getLine >>= return . read');\n add('getContents', 'getContents :: IO String\\ngetContents = lcReadAll');\n add('interact', 'interact :: (String -> String) -> IO ()\\ninteract f = getContents >>= putStr . f');\n\n return parts.join('\\n\\n');\n}\n\n/**\n * Append stdin support to a program. Imports are hoisted; definitions are appended\n * (order does not matter in Haskell). A program with no stdin is left untouched.\n * @param {string} source\n * @param {string} input\n * @returns {string}\n */\nexport function injectStdin(source, input) {\n const code = String(source == null ? '' : source);\n const text = String(input == null ? '' : input);\n if (!text) return code;\n\n // Drop a trailing newline the editor may have added, so line counting stays sane.\n const lines = code.replace(/\\s*$/, '').split('\\n');\n const at = importInsertAt(lines);\n const hoisted = IMPORTS.filter((line) => !new RegExp('^' + line.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '\\\\s*$', 'm').test(code));\n const withImports = hoisted.length\n ? lines.slice(0, at).concat(['']).concat(hoisted).concat('').concat(lines.slice(at))\n : lines;\n\n return withImports.join('\\n') + '\\n\\n' + shimSource(text, code) + '\\n';\n}\n", "import { createPackageResolver } from './manifest.js';\nimport { injectStdin } from './shim.js';\n\n/**\n * MicroHs REPL driver.\n *\n * The published `mhs-embed` bundle cannot compile and run in batch mode, so the only\n * execution path is the interactive REPL: write Main.hs, `import Main` (which compiles,\n * so diagnostics surface here), `:reload` (the REPL caches modules, so a changed file is\n * otherwise ignored), then `:main` (which runs it). Output is read between sentinel\n * prompts.\n *\n * Program stdin does not exist at the OS level in this build, so it is injected into the\n * source instead \u2014 see shim.js.\n */\n\nconst HOME = '/home/web_user';\nconst MAIN_FILE = 'Main.hs';\nconst PROMPT = '<<<LC_PROMPT>>>';\nconst PKG_DIR = '/pkgs';\nconst BOOT_TIMEOUT = 30000;\nconst DEFAULT_TIMEOUT = 60000;\n\nconst delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Load the Emscripten glue, wherever this is running. */\nasync function loadScript(url) {\n if (typeof document !== 'undefined' && document.createElement) {\n await new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('failed to load ' + url));\n (document.head || document.body || document.documentElement).appendChild(script);\n });\n return;\n }\n if (typeof importScripts === 'function') {\n importScripts(url);\n return;\n }\n // Module worker (or Node, if someone points wasmUrl at a file URL).\n await import(/* webpackIgnore: true */ /* @vite-ignore */ url);\n}\n\n/** Backspaces delete the previous character, as a terminal would. */\nfunction applyBackspaces(text) {\n let out = '';\n for (const ch of text) {\n if (ch === '\\b') out = out.slice(0, -1);\n else out += ch;\n }\n return out;\n}\n\n/** Progress lines (\"adds [ ]\\radds [x]\") keep only their final state. */\nfunction applyCarriageReturns(text) {\n return text\n .split('\\n')\n .map((line) => {\n const i = line.lastIndexOf('\\r');\n return i >= 0 ? line.slice(i + 1) : line;\n })\n .join('\\n');\n}\n\n/** Drop prompts, ANSI control sequences, echoed input and REPL banner lines. */\nfunction clean(text, sentLines) {\n const noPrompts = text.split(PROMPT).join('');\n const noAnsi = applyCarriageReturns(\n applyBackspaces(\n noPrompts\n // eslint-disable-next-line no-control-regex\n .replace(/\\u001b\\[[0-9;?]*[A-Za-z]|\\u001b[@-Z\\\\-_]|\\u001b\\([A-Za-z0-9]/g, '')\n .replace(/\\u0007/g, ''),\n ),\n );\n const banner = [\n /^Welcome to interactive MicroHs/,\n /^Integer implemented with imath/,\n /^Loading embedded package /,\n /^Loading package /,\n /^loaded /,\n /^Type ':quit' to quit/,\n ];\n return noAnsi\n .split('\\n')\n .filter((line) => {\n const t = line.trim();\n if (banner.some((re) => re.test(t))) return false;\n if ((sentLines || []).some((s) => t === s)) return false;\n return true;\n })\n .join('\\n');\n}\n\n/** Is this line an error/diagnostic rather than program output? */\nfunction isErrorLine(line) {\n const t = line.trim();\n return (\n /^(\\*\\*\\* )?(Exception|error:|Error:)/.test(t) ||\n /^Unrecognized command/.test(t) ||\n // The compiler explains failed constraint solving on its own lines, on stdout.\n /^fully qualified:/.test(t) ||\n /: line \\d+, col \\d+:/.test(t)\n );\n}\n\nfunction classify(text) {\n const out = [];\n const errors = [];\n for (const line of text.split('\\n')) (isErrorLine(line) ? errors : out).push(line);\n return { out, errors };\n}\n\nconst joinLines = (lines) => lines.join('\\n').trim();\n\n/**\n * One MicroHs instance. Booting is expensive (~1-2s: 1.9 MB wasm), so create one and\n * reuse it for every run in the page/worker.\n */\nexport class MicroHs {\n constructor(options) {\n const opts = options || {};\n this.options = {\n wasmUrl: opts.wasmUrl,\n packagesUrl: opts.packagesUrl,\n importmap: opts.importmap || {},\n timeout: opts.timeout || DEFAULT_TIMEOUT,\n charDelay: opts.charDelay == null ? 0 : opts.charDelay,\n onLog: typeof opts.onLog === 'function' ? opts.onLog : null,\n fetch: opts.fetch,\n };\n\n this.raw = '';\n this.out = '';\n this.err = '';\n this.outDecoder = new TextDecoder('utf-8', { fatal: false });\n this.errDecoder = new TextDecoder('utf-8', { fatal: false });\n this.loaded = new Set();\n this.exitCode = null;\n this.fatal = null;\n this.ready = false;\n this.running = false;\n this.disposed = false;\n /** Set once a run has timed out: the REPL is mid-execution and cannot be reused. */\n this.poisoned = null;\n this.Module = null;\n this.resolver = null;\n }\n\n log(message) {\n if (this.options.onLog) this.options.onLog(message);\n }\n\n promptCount() {\n let n = 0;\n let i = 0;\n while ((i = this.raw.indexOf(PROMPT, i)) !== -1) {\n n++;\n i += PROMPT.length;\n }\n return n;\n }\n\n async waitFor(predicate, label, deadline) {\n for (;;) {\n if (predicate()) return;\n if (this.fatal) throw new Error(this.fatal);\n if (Date.now() > deadline) {\n const err = new Error('timed out waiting for ' + label);\n err.timeout = true;\n throw err;\n }\n await delay(1);\n }\n }\n\n /** Type a line into the REPL one character at a time, yielding between them. */\n async typeLine(text, deadline) {\n const bytes = new TextEncoder().encode(text + '\\n');\n for (const byte of bytes) {\n if (Date.now() > deadline) {\n const err = new Error('timed out while sending input');\n err.timeout = true;\n throw err;\n }\n this.Module._set_input_char(byte);\n await delay(this.options.charDelay);\n }\n }\n\n /** Type a REPL command and wait for the output it produces. */\n async step(line, deadline) {\n const baseline = this.promptCount();\n await this.typeLine(line, deadline);\n await this.waitFor(() => this.promptCount() > baseline, JSON.stringify(line), deadline);\n }\n\n /** Boot the compiler. Resolves once the REPL shows its first prompt. */\n async boot() {\n this.resolver = createPackageResolver({\n packagesUrl: this.options.packagesUrl,\n importmap: this.options.importmap,\n log: (m) => this.log(m),\n fetch: this.options.fetch,\n });\n await this.resolver.loadManifest();\n\n const wasmUrl = String(this.options.wasmUrl);\n const wasmDir = wasmUrl.slice(0, wasmUrl.lastIndexOf('/') + 1);\n\n const Module = {\n // `-aPATH` appends to the package search path. Declaring it up front (even while\n // /pkgs is empty) is what lets packages be written into the virtual FS later and\n // imported without restarting the REPL.\n arguments: ['-a' + PKG_DIR],\n locateFile: (file) => wasmDir + file,\n preRun: [\n function () {\n const FS = Module.FS;\n FS.mkdirTree(HOME);\n FS.chdir(HOME);\n FS.writeFile('.mhsi_rc', ':set prompt=' + PROMPT + '\\n');\n FS.writeFile(MAIN_FILE, '');\n },\n ],\n // Program stdin is unusable here; it is injected as source instead (shim.js).\n stdin: () => null,\n stdout: (code) => code !== null && this.appendOut(code),\n stderr: (code) => code !== null && this.appendErr(code),\n print: (text) => this.appendOut(text + '\\n'),\n printErr: (text) => this.appendErr(text + '\\n'),\n onExit: (code) => {\n this.exitCode = code;\n this.log('compiler exited with ' + code);\n },\n onAbort: (what) => {\n this.fatal = String(what);\n },\n };\n\n this.Module = Module;\n // The glue is a classic script that reads a global `Module`.\n globalThis.Module = Module;\n\n this.log('loading ' + wasmUrl);\n await loadScript(wasmUrl);\n await this.waitFor(() => this.promptCount() > 0, 'the REPL to start', Date.now() + BOOT_TIMEOUT);\n this.ready = true;\n this.log('ready');\n return this;\n }\n\n appendOut(text) {\n const s = typeof text === 'number' ? this.outDecoder.decode(new Uint8Array([text]), { stream: true }) : String(text);\n this.out += s;\n this.raw += s;\n }\n\n appendErr(text) {\n const s = typeof text === 'number' ? this.errDecoder.decode(new Uint8Array([text]), { stream: true }) : String(text);\n this.err += s;\n this.raw += s;\n }\n\n /**\n * Write package files into the live virtual FS, plus the module lookup maps that point\n * at them. No restart, no page reload: the search path was declared at boot.\n * @returns {Promise<string[]>} package files actually written\n */\n async loadPackages(names, urls) {\n const want = (names || []).filter((name) => !this.loaded.has(name));\n if (!want.length) return [];\n\n const bytes = await this.resolver.fetchPackages(want, urls);\n const got = Object.keys(bytes);\n if (!got.length) return [];\n\n const FS = this.Module.FS;\n FS.mkdirTree(PKG_DIR + '/packages');\n for (const name of got) FS.writeFile(PKG_DIR + '/packages/' + name, bytes[name]);\n this.writeModuleMaps(got);\n for (const name of got) this.loaded.add(name);\n this.log('loaded ' + got.length + ' package(s): ' + got.join(', '));\n return got;\n }\n\n /** `<Module/Path>.txt` containing the package file name, for each provided module. */\n writeModuleMaps(pkgFiles) {\n const FS = this.Module.FS;\n for (const mod of this.resolver.modulesOf(pkgFiles)) {\n const pkg = this.resolver.packageOfModule(mod);\n if (!pkg) continue;\n const path = PKG_DIR + '/' + mod.replace(/\\./g, '/') + '.txt';\n FS.mkdirTree(path.slice(0, path.lastIndexOf('/')));\n FS.writeFile(path, pkg);\n }\n }\n\n /**\n * Compile and run a program.\n * @param {{code: string, stdin?: string, timeout?: number}} options\n * @returns {Promise<{stdout:string, stderr:string, error:string|null, output:string,\n * exitCode:number, packages:string[], durationMs:number}>}\n */\n async run(options) {\n const opts = options || {};\n if (this.disposed) throw new Error('this instance has been disposed');\n if (this.poisoned) throw new Error(this.poisoned);\n if (!this.ready) throw new Error('the REPL is not ready');\n if (this.running) throw new Error('a run is already in progress');\n\n const timeout = opts.timeout || this.options.timeout;\n const deadline = Date.now() + timeout;\n const source = injectStdin(opts.code, opts.stdin);\n\n // Imports that can never be satisfied are reported before anything is compiled.\n const analysis = this.resolver.analyzeImports(source);\n if (analysis.missing.length) {\n return this.result({ error: this.resolver.explainMissing(analysis.missing) });\n }\n\n const loaded = await this.loadPackages(analysis.packages, analysis.urls);\n const absent = analysis.packages.filter((name) => !this.loaded.has(name));\n if (absent.length) {\n return this.result({ error: 'package file(s) missing from this build: ' + absent.join(', '), packages: loaded });\n }\n\n const mark = { raw: this.raw.length, out: this.out.length, err: this.err.length };\n const sent = [];\n const started = Date.now();\n let timedOut = false;\n\n this.running = true;\n try {\n this.Module.FS.writeFile(MAIN_FILE, source);\n // `import Main` compiles, so diagnostics appear here; :reload is what actually\n // picks up a changed file; :main runs it.\n for (const line of ['import Main', ':reload', ':main']) {\n sent.push(line);\n await this.step(line, deadline);\n }\n } catch (err) {\n timedOut = !!err.timeout;\n if (!timedOut) this.fatal = String((err && err.message) || err);\n } finally {\n this.running = false;\n }\n\n const collected = this.collect(mark, sent);\n if (timedOut) {\n this.poisoned = 'the previous run timed out and left the REPL busy; create a new instance';\n }\n\n return this.result({\n ...collected,\n error:\n collected.error ||\n (timedOut ? 'timed out after ' + timeout + 'ms' : null) ||\n (this.fatal ? this.fatal : null),\n exitCode: timedOut ? 124 : undefined,\n packages: loaded,\n durationMs: Date.now() - started,\n });\n }\n\n /** Split the output captured since `mark` into stdout, stderr and diagnostics. */\n collect(mark, sent) {\n const outC = classify(clean(this.out.slice(mark.out), sent));\n const errC = classify(clean(this.err.slice(mark.err), sent));\n const errors = [];\n for (const line of outC.errors.concat(errC.errors)) {\n if (!errors.includes(line)) errors.push(line);\n }\n const error = joinLines(errors);\n return {\n stdout: joinLines(outC.out),\n stderr: joinLines(errC.out),\n error: error ? this.resolver.explainNotFound(error) : null,\n output: clean(this.raw.slice(mark.raw), sent).trim(),\n };\n }\n\n result(extra) {\n const error = extra.error || null;\n const exitCode =\n extra.exitCode != null ? extra.exitCode : error ? 1 : this.exitCode == null ? 0 : this.exitCode;\n return {\n stdout: extra.stdout || '',\n stderr: extra.stderr || '',\n error,\n output: extra.output || '',\n exitCode,\n packages: extra.packages || [],\n durationMs: extra.durationMs == null ? 0 : extra.durationMs,\n };\n }\n\n /**\n * Release this instance. Browsers cannot unload a wasm module, so this drops our\n * references rather than freeing memory; one instance per page/worker is the model.\n */\n dispose() {\n this.disposed = true;\n this.Module = null;\n this.resolver = null;\n this.loaded.clear();\n }\n}\n", "import { MicroHs } from './repl.js';\n\n/**\n * @live-codes/browser-haskell \u2014 run Haskell in the browser.\n *\n * import { createHaskell } from '@live-codes/browser-haskell';\n *\n * const haskell = await createHaskell(); // boots MicroHs (~1-2s)\n * const result = await haskell.run({ code: 'main = putStrLn \"hi\"', stdin: '' });\n * result.stdout; // \"hi\\n\"\n * result.error; // compile errors / exceptions, or null\n * result.exitCode; // 0, 1, or 124 on timeout\n *\n * Everything is client-side: a wasm build of MicroHs plus lazily fetched MicroHs\n * packages. Assets (the wasm bundle and the package set) are looked up next to this\n * module by default; point `baseUrl` at wherever you host them.\n */\n\n/**\n * Where this file lives, so a default asset URL can be derived. Captured at load time\n * because `document.currentScript` is only meaningful then (IIFE build); the ESM build\n * uses `import.meta.url`.\n */\nconst SELF_DIR = (() => {\n if (typeof document !== 'undefined' && document.currentScript && document.currentScript.src) {\n return dirOf(document.currentScript.src);\n }\n try {\n return dirOf(import.meta.url);\n } catch (err) {\n // Not a module (IIFE build without a script tag): fall back to the page URL.\n }\n if (typeof location !== 'undefined' && location.href) return dirOf(location.href);\n return '';\n})();\n\nfunction dirOf(url) {\n return String(url).slice(0, String(url).lastIndexOf('/') + 1);\n}\n\nconst withSlash = (url) => (String(url).endsWith('/') ? String(url) : String(url) + '/');\n\n/**\n * Create a MicroHs instance.\n *\n * @param {object} [options]\n * @param {string} [options.baseUrl] Where the assets live: `mhs/mhs-embed.js` (+ .wasm)\n * and `pkgs/index.json` (+ `pkgs/packages/*.pkg`). Defaults to this module's directory.\n * @param {string} [options.wasmUrl] Full URL of `mhs-embed.js` (overrides baseUrl).\n * @param {string} [options.packagesUrl] Directory containing `index.json` and\n * `packages/` (overrides baseUrl).\n * @param {Object<string,string>} [options.importmap] Extra packages by module name,\n * e.g. `{ 'My.Module': 'https://example.com/my-pkg.pkg' }`. The `.pkg` must be built by\n * the same MicroHs version, and any MicroHs dependencies it has must be mapped too.\n * @param {number} [options.timeout] Per-run timeout in ms (default 60000).\n * @param {(message: string) => void} [options.onLog] Diagnostic logging.\n * @returns {Promise<MicroHs>}\n */\nexport async function createHaskell(options) {\n const opts = options || {};\n const baseUrl = withSlash(opts.baseUrl || SELF_DIR);\n const repl = new MicroHs({\n ...opts,\n wasmUrl: opts.wasmUrl || baseUrl + 'mhs/mhs-embed.js',\n packagesUrl: opts.packagesUrl || baseUrl + 'pkgs/',\n });\n await repl.boot();\n return repl;\n}\n\nexport { MicroHs };\nexport default { createHaskell, MicroHs };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["withSlash", "url", "importedModules", "source", "code", "line", "out", "re", "m", "customName", "clean", "createPackageResolver", "options", "opts", "base", "importmap", "log", "doFetch", "args", "custom", "moduleName", "name", "entry", "manifestPromise", "manifest", "loadManifest", "res", "err", "classifyModule", "rule", "analyzeImports", "needed", "urls", "missing", "mod", "found", "closure", "queue", "pkg", "deps", "dep", "packageOfModule", "modulesOf", "pkgFiles", "wanted", "fetchPackages", "names", "buf", "explainMissing", "lines", "item", "count", "pkgs", "examples", "explainNotFound", "text", "seen", "s", "why", "IMPORTS", "ESCAPES", "toHaskellString", "text", "out", "ch", "code", "definesName", "source", "name", "importInsertAt", "lines", "header", "l", "i", "line", "shimSource", "input", "parts", "add", "injectStdin", "at", "hoisted", "IMPORTS", "HOME", "MAIN_FILE", "PROMPT", "PKG_DIR", "BOOT_TIMEOUT", "DEFAULT_TIMEOUT", "delay", "ms", "resolve", "loadScript", "url", "reject", "script", "applyBackspaces", "text", "out", "ch", "applyCarriageReturns", "line", "i", "clean", "sentLines", "noPrompts", "noAnsi", "banner", "t", "re", "s", "isErrorLine", "classify", "errors", "joinLines", "lines", "MicroHs", "options", "opts", "message", "n", "predicate", "label", "deadline", "err", "bytes", "byte", "baseline", "createPackageResolver", "m", "wasmUrl", "wasmDir", "Module", "file", "FS", "code", "what", "names", "urls", "want", "name", "got", "pkgFiles", "mod", "pkg", "path", "timeout", "source", "injectStdin", "analysis", "loaded", "absent", "mark", "sent", "started", "timedOut", "collected", "outC", "errC", "error", "extra", "exitCode", "SELF_DIR", "dirOf", "url", "withSlash", "createHaskell", "options", "opts", "baseUrl", "repl", "MicroHs", "index_default", "createHaskell", "MicroHs"]
|
|
7
|
+
}
|